Comparing version 0.3.0 to 0.4.0
@@ -13,2 +13,14 @@ import { EventEmitter2 as EventEmitter } from "eventemitter2"; | ||
}> = ((payload: T["payload"]) => T) & EventTypeDescriptor<T>; | ||
declare type TestPredicateFn<P> = (payload: P) => boolean; | ||
declare type EventDefinitionOptions<P> = { | ||
test?: (payload: P) => boolean; | ||
}; | ||
export declare function createEventDefinition<P>(options?: EventDefinitionOptions<P> | TestPredicateFn<P>): <T extends string>(type: T) => { | ||
(payload: P): { | ||
type: T; | ||
payload: P; | ||
}; | ||
eventType: T; | ||
toString(): T; | ||
}; | ||
export declare function defineEvent<T extends BusEvent>(type: T["type"]): EventCreatorFn<T>; | ||
@@ -15,0 +27,0 @@ export declare class EventBus { |
@@ -16,2 +16,7 @@ "use strict"; | ||
var eventemitter2_1 = require("eventemitter2"); | ||
function showWarning(msg) { | ||
if (process && process.env && process.env.NODE_ENV !== "production") { | ||
console.warn(msg); | ||
} | ||
} | ||
function isEventDescriptor(descriptor) { | ||
@@ -23,3 +28,25 @@ return !!descriptor && descriptor.eventType; | ||
} | ||
function createEventDefinition(options) { | ||
return function (type) { | ||
var eventCreator = function (payload) { | ||
// Allow runtime payload checking for plain JavaScript usage | ||
if (options) { | ||
var testFn = typeof options === "function" ? options : options.test; | ||
if (testFn && !testFn(payload)) { | ||
showWarning(JSON.stringify(payload) + " does not match expected payload."); | ||
} | ||
} | ||
return { | ||
type: type, | ||
payload: payload | ||
}; | ||
}; | ||
eventCreator.eventType = type; | ||
eventCreator.toString = function () { return type; }; // allow String coercion to deliver the eventType | ||
return eventCreator; | ||
}; | ||
} | ||
exports.createEventDefinition = createEventDefinition; | ||
function defineEvent(type) { | ||
showWarning("defineEvent is deprecated and will be removed in the future. Please use createEventDefinition instead."); | ||
var eventCreator = function (payload) { return ({ | ||
@@ -26,0 +53,0 @@ type: type, |
@@ -1,1 +0,1 @@ | ||
export { EventBus, defineEvent } from "./EventBus"; | ||
export { EventBus, defineEvent, createEventDefinition } from "./EventBus"; |
@@ -6,2 +6,3 @@ "use strict"; | ||
exports.defineEvent = EventBus_1.defineEvent; | ||
exports.createEventDefinition = EventBus_1.createEventDefinition; | ||
//# sourceMappingURL=index.js.map |
@@ -15,3 +15,57 @@ "use strict"; | ||
var index_1 = require("./index"); | ||
var mockWarn = jest.fn(); | ||
console.warn = mockWarn; | ||
describe("Basic usage", function () { | ||
describe("createEventDefinition", function () { | ||
it("should work with createEventDefinition", function () { | ||
// mock subscription | ||
var handleSubscription = jest.fn(); | ||
var myEventCreator = index_1.createEventDefinition()("myevent"); | ||
// create a bus | ||
var bus = new index_1.EventBus(); | ||
bus.subscribe(myEventCreator, handleSubscription); | ||
// create n event | ||
var event = myEventCreator({ foo: "Hello" }); | ||
// Call it once | ||
bus.publish(event); | ||
expect(handleSubscription.mock.calls).toEqual([ | ||
[ | ||
{ | ||
type: "myevent", | ||
payload: { foo: "Hello" } | ||
} | ||
] | ||
]); | ||
// call a few times | ||
bus.publish(event); | ||
bus.publish(event); | ||
bus.publish(event); | ||
expect(handleSubscription.mock.calls.length).toBe(4); | ||
}); | ||
it("should show deprecation warning when using defineEvent", function () { | ||
mockWarn.mockReset(); | ||
index_1.defineEvent("myevent"); | ||
expect(mockWarn.mock.calls[0][0]).toEqual("defineEvent is deprecated and will be removed in the future. Please use createEventDefinition instead."); | ||
}); | ||
it("should allow runtime type warnings", function () { | ||
mockWarn.mockReset(); | ||
var testFn = function (o) { return o.foo && typeof o.foo === "string"; }; | ||
var myEventCreator = index_1.createEventDefinition(testFn)("myevent"); | ||
// @ts-ignore | ||
myEventCreator({ ding: "baz" }); | ||
expect(mockWarn.mock.calls[0][0]).toEqual("{\"ding\":\"baz\"} does not match expected payload."); | ||
}); | ||
it("should allow runtime type warnings with the options object", function () { | ||
mockWarn.mockReset(); | ||
var testFn = function (o) { return o.foo && typeof o.foo === "string"; }; | ||
var myEventCreator = index_1.createEventDefinition({ test: testFn })("myevent"); | ||
// @ts-ignore | ||
myEventCreator({ ding: "baz" }); | ||
expect(mockWarn.mock.calls[0][0]).toEqual("{\"ding\":\"baz\"} does not match expected payload."); | ||
}); | ||
it("should allow string coercion to return the eventType", function () { | ||
var myEventCreator = index_1.createEventDefinition()("myevent"); | ||
expect(String(myEventCreator)).toEqual("myevent"); | ||
}); | ||
}); | ||
it("should respond to events being dispatched", function () { | ||
@@ -18,0 +72,0 @@ // mock subscription |
{ | ||
"name": "ts-bus", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"main": "index.js", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -18,12 +18,7 @@ <p align="center"> | ||
```ts | ||
import { EventBus, defineEvent } from "ts-bus"; | ||
import { EventBus, createEventDefinition } from "ts-bus"; | ||
// Define Event | ||
type SomeEvent = { | ||
type: "SOME_EVENT"; | ||
payload: { url: string }; | ||
}; | ||
export const someEvent = createEventDefinition<{ url: string }>()("SOME_EVENT"); | ||
export const someEvent = defineEvent<SomeEvent>("SOME_EVENT"); | ||
// Create bus | ||
@@ -83,3 +78,3 @@ const bus = new EventBus(); | ||
#### Create a bus | ||
### Create a bus | ||
@@ -94,3 +89,3 @@ Create your EventBus globally somewhere: | ||
#### Declare events | ||
### Declare events | ||
@@ -101,36 +96,31 @@ Next create some Events: | ||
// events.ts | ||
import { defineEvent } from "ts-bus"; | ||
import { createEventDefinition } from "ts-bus"; | ||
type TaskCreatedEvent = { | ||
type: "task.created"; | ||
payload: { | ||
id: string; | ||
listId: string; | ||
value: string; | ||
}; | ||
}; | ||
export const taskCreated = createEventDefinition<{ | ||
id: string; | ||
listId: string; | ||
value: string; | ||
}>()("task.created"); | ||
export const taskCreated = defineEvent<TaskCreatedEvent>("task.created"); | ||
// Note we have to pass in a string as typescript does | ||
// not allow for a way to create a string from typeland | ||
// This is typed however so you should have | ||
// autocompletion and should not find yourself making errors | ||
export const taskLabelUpdated = createEventDefinition<{ | ||
id: string; | ||
label: string; | ||
}>()("task.label.updated"); | ||
``` | ||
_TIP_ | ||
Notice we need to call the curried function to create the event creator this is because it is [the only way we can allow effective discriminated unions](https://github.com/ryardley/ts-bus/issues/9). | ||
> I find putting the event type inline within the definition leads to more concise event definition code | ||
### Runtime payload checking | ||
```ts | ||
// Inline example | ||
export const taskLabelUpdated = defineEvent<{ | ||
type: "task.label.updated"; | ||
payload: { | ||
id: string; | ||
label: string; | ||
}; | ||
}>("task.label.updated"); | ||
You can also provide a function to do runtime payload type checking. This might be useful if you are working in JavaScript: | ||
```js | ||
import p from "pdsl"; | ||
export const taskLabelUpdated = createEventDefinition(p`{ | ||
id: String, | ||
label: String, | ||
}`)("task.label.updated"); | ||
``` | ||
#### Subscription | ||
### Subscription | ||
@@ -167,3 +157,3 @@ Let's subscribe to our events | ||
#### Publishing events | ||
### Publishing events | ||
@@ -204,2 +194,4 @@ Now let's publish our events somewhere | ||
```ts | ||
import p from "pdsl"; | ||
// get an event from a socket | ||
@@ -210,7 +202,13 @@ socket.on("event-sync", (event: BusEvent<any>) => { | ||
// This is a shorthand utility that creates predicate functions based on a given object shape. | ||
// For more details see https://github.com/ryardley/pdsl | ||
const predicateFn = p`{ | ||
type:${/^shared\./}, | ||
meta: { | ||
remote: !true | ||
} | ||
}`; | ||
// Prevent sending a event-sync if the event was remote | ||
const isSharedAndLocalEvent = event => | ||
/^shared\./.test(event.type) && !(event.meta && event.meta.remote); | ||
bus.subscribe(isSharedAndLocalEvent, event => { | ||
bus.subscribe(predicateFn, event => { | ||
socket.emit("event-sync", event); | ||
@@ -237,3 +235,3 @@ }); | ||
#### BusProvider | ||
### BusProvider | ||
@@ -260,3 +258,3 @@ Wrap your app using the `BusProvider` | ||
#### useBus | ||
### useBus | ||
@@ -283,3 +281,3 @@ Access the bus instance with `useBus` | ||
#### useBusReducer | ||
### useBusReducer | ||
@@ -286,0 +284,0 @@ This connects state changes to bus events via a state reducer function. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
262610
27
410
308
3