-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c80727a
Showing
24 changed files
with
4,555 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# OS metadata | ||
.DS_Store | ||
Thumbs.db | ||
|
||
# Ignore built ts files | ||
dist/**/* | ||
|
||
# Dependency directory | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"typescript.tsdk": "node_modules/typescript/lib" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"symbols":{"FakeEventBus":{"hasNamespace":false,"type":0,"moduleName":"FakeEventBus","relativePath":"__tests__/implementation/FakeEventBus"},"FakeEvent":{"hasNamespace":false,"type":0,"moduleName":"FakeEventBus","relativePath":"__tests__/implementation/FakeEventBus"},"CreateEventArguments":{"hasNamespace":false,"type":1,"moduleName":"EventMap.d","relativePath":"__tests__/implementation/EventMap.d"},"UpdateEventArguments":{"hasNamespace":false,"type":1,"moduleName":"EventMap.d","relativePath":"__tests__/implementation/EventMap.d"},"EventStore":{"hasNamespace":false,"type":1,"moduleName":"EventMap.d","relativePath":"__tests__/implementation/EventMap.d"},"InternalClassEventMetadata":{"hasNamespace":false,"type":1,"moduleName":"PubSub","relativePath":"src/PubSub"},"PubSubProvider":{"hasNamespace":false,"type":1,"moduleName":"PubSub","relativePath":"src/PubSub"},"PubSubEvent":{"hasNamespace":false,"type":1,"moduleName":"PubSub","relativePath":"src/PubSub"},"CreateDecorated":{"hasNamespace":false,"type":0,"moduleName":"DecoratedClass","relativePath":"__tests__/implementation/DecoratedClass"},"MalformedUpdateDecorated":{"hasNamespace":false,"type":0,"moduleName":"DecoratedClass","relativePath":"__tests__/implementation/DecoratedClass"}},"files":{"src/Listener.ts":"2019-06-17T19:44:30.779Z","src/PubSub.ts":"2019-06-17T19:46:22.976Z","src/index.ts":"2019-06-17T01:19:23.519Z","test/DecoratedClass.ts":"2019-06-17T18:03:12.985Z","test/FakeEventBus.ts":"2019-06-17T00:05:26.287Z","src/Observe.ts":"2019-06-17T21:40:56.203Z","test/PubSub.test.ts":"2019-06-17T18:04:00.418Z","__tests__/PubSub.test.ts":"2019-06-18T19:38:31.608Z","__tests__/implementation/FakeEventBus.ts":"2019-06-17T18:26:18.491Z","__tests__/implementation/DecoratedClass.ts":"2019-06-18T16:27:36.509Z","__tests__/implementation/EventMap.d.ts":"2019-06-17T18:44:43.087Z","__tests__/implementation/EventBusInstance.ts":"2019-06-17T19:47:26.821Z","__tests__/types_testing/index.d.ts":"2019-06-17T20:26:23.659Z","__tests__/types_testing/test.ts":"2019-06-17T20:24:44.770Z","__tests__/types/index.d.ts":"2019-06-17T21:34:58.611Z","__tests__/types/test.ts":"2019-06-18T16:24:41.568Z","__tests__/implementation/index.d.ts":"2019-06-17T20:21:11.415Z"}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { CreateDecorated, MalformedUpdateDecorated } from "./implementation/DecoratedClass"; | ||
import { FakeEventBusInstance } from "./implementation/EventBusInstance"; | ||
|
||
describe("The Declarated class", function() { | ||
it("instantiates", function() { | ||
const decorated = new CreateDecorated(); | ||
expect(decorated).toBeDefined(); | ||
}); | ||
it("stores the data received on the create event", function() { | ||
const decorated = new CreateDecorated(); | ||
FakeEventBusInstance | ||
.fromEvent("create") | ||
.publish({ firstArgument: "test" }); | ||
expect(decorated.firstArgument).toBe("test"); | ||
}); | ||
it("does not stores the data on malformed class update event", function () { | ||
const decorated = new MalformedUpdateDecorated(); | ||
FakeEventBusInstance | ||
.fromEvent("update") | ||
.publish({ update: true }); | ||
expect(decorated.shouldUpdate).toBeUndefined(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Listener, Observe } from "../../src"; | ||
import { FakeEventBusInstance } from "./EventBusInstance"; | ||
import { EventStore, CreateEventArguments, UpdateEventArguments } from "./EventMap"; | ||
|
||
|
||
|
||
@Listener<EventStore, CreateDecorated>(FakeEventBusInstance) | ||
export class CreateDecorated { | ||
public firstArgument: string; | ||
|
||
@Observe<EventStore>()("create") | ||
public onCreate(arg: CreateEventArguments) { | ||
this.firstArgument = arg.firstArgument; | ||
} | ||
} | ||
|
||
@Listener<EventStore, MalformedUpdateDecorated>(FakeEventBusInstance) | ||
export class MalformedUpdateDecorated { | ||
public shouldUpdate?: UpdateEventArguments; | ||
public onUpdate(_: UpdateEventArguments) {} | ||
|
||
@Observe<EventStore>()("update") | ||
public onOtherUpdate(arg: UpdateEventArguments) { | ||
this.shouldUpdate = arg; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { FakeEventBus } from "./FakeEventBus"; | ||
import { EventStore } from "./EventMap"; | ||
import { PubSubProvider } from "../../src"; | ||
|
||
export const FakeEventBusInstance: PubSubProvider<EventStore> = new FakeEventBus<EventStore>(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export interface CreateEventArguments { | ||
firstArgument: string; | ||
} | ||
|
||
export interface UpdateEventArguments { | ||
update: boolean; | ||
} | ||
|
||
export interface EventStore { | ||
create: CreateEventArguments; | ||
update: UpdateEventArguments; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { PubSubProvider, PubSubEvent } from "../../src/PubSub"; | ||
|
||
export class FakeEventBus<EventMap extends object> implements PubSubProvider<EventMap> { | ||
private internalDict: { [key in keyof EventMap]?: PubSubEvent<EventMap[key]>; } = {}; | ||
public fromEvent(event: keyof EventMap): PubSubEvent<EventMap[keyof EventMap]> { | ||
if (!this.internalDict[event]) { | ||
this.internalDict[event] = new FakeEvent(); | ||
} | ||
return this.internalDict[event]; | ||
} | ||
} | ||
|
||
export class FakeEvent<EventData> implements PubSubEvent<EventData> { | ||
private subscribed: Array<(data: EventData) => void> = []; | ||
public subscribe(callback: (data: EventData) => void): void { | ||
this.subscribed.push(callback); | ||
} | ||
|
||
public publish(data: EventData): void { | ||
this.subscribed.forEach((callback) => callback(data)); | ||
} | ||
|
||
public unsubscribe(): void { | ||
this.subscribed = []; | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// TypeScript Version: 2.9 | ||
|
||
declare module "Empty"; | ||
declare module "aaa"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Observe } from "../../src"; | ||
import { | ||
EventStore, | ||
UpdateEventArguments, | ||
CreateEventArguments | ||
} from "../implementation/EventMap"; | ||
|
||
// A word of caution: we are testing the types of our decorators, but dtslint does not allow for | ||
// testing that a decorator is compiling or not. | ||
// That's why we have to use TS' internal way to call decorators as higher order functions | ||
|
||
//#region Test Set Up | ||
export class MalformedUpdateDecorated { | ||
public shouldUpdate?: CreateEventArguments; | ||
public onUpdate(_: UpdateEventArguments) {} | ||
public onOtherUpdate(arg: CreateEventArguments) { | ||
this.shouldUpdate = arg; | ||
} | ||
} | ||
const observe = Observe<EventStore>()("update"); | ||
const malformed = new MalformedUpdateDecorated(); | ||
//#endregion | ||
|
||
// There should be a type error when trying to assign the observable to a method that does not receive the right arguments | ||
// $ExpectError | ||
observe(malformed, "onOtherUpdate", { value: malformed.onOtherUpdate }); | ||
|
||
// There should not be an error when the method implements the right arguments | ||
observe(malformed, "onUpdate", { value: malformed.onUpdate }); | ||
|
||
// There should be an error when a class uses @Observe and don't register as a @Listener | ||
|
||
// There should be an error when a class register as an @Listener and don't have any @Observer | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "es5", | ||
"module": "commonjs", | ||
/* Strict Type-Checking Options */ | ||
"strict": true, | ||
"noImplicitAny": true, | ||
"strictNullChecks": true, | ||
"strictFunctionTypes": true, | ||
"noImplicitThis": true, | ||
"alwaysStrict": true, | ||
/* Additional Checks */ | ||
"noUnusedParameters": true, | ||
"noImplicitReturns": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"experimentalDecorators": true, | ||
"types": [], | ||
"lib": [ | ||
"es5" | ||
], | ||
/* dtslint needs these to operate in this directory */ | ||
"baseUrl": ".", | ||
"paths": { | ||
"pubsub-class": [ | ||
"../../src" | ||
] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"extends": "dtslint/dtslint.json", | ||
"rules": { | ||
"no-useless-files": false, | ||
"eofline": false, | ||
"no-relative-import-in-test": false, | ||
"prefer-while": false, | ||
"no-unnecessary-callback-wrapper": false, | ||
"arrow-return-shorthand": false, | ||
"no-misused-new": false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const { defaults: tsjPreset } = require('ts-jest/presets'); | ||
|
||
module.exports = { | ||
testPathIgnorePatterns: ["/node_modules/", "__tests__/implementation" ], | ||
transform: { | ||
...tsjPreset.transform | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "pubsub-class", | ||
"version": "1.0.0", | ||
"description": "PubSub pattern binding using ES6 Decorators", | ||
"main": "index.js", | ||
"repository": "https://github.com/Psidium/pubsub-class", | ||
"author": "Psidium", | ||
"license": "MIT", | ||
"private": false, | ||
"devDependencies": { | ||
"@types/jest": "^24.0.14", | ||
"dtslint": "^0.8.0", | ||
"jest": "^24.8.0", | ||
"prettier": "1.18.2", | ||
"ts-jest": "^24.0.2", | ||
"tslint": "^5.17.0", | ||
"tslint-config-prettier": "^1.18.0", | ||
"tslint-plugin-prettier": "^2.0.1", | ||
"typescript": "^2.9" | ||
}, | ||
"scripts": { | ||
"build": "tsc -p tsconfig.json", | ||
"build:watch": "tsc -p tsconfig.json -w", | ||
"test": "jest", | ||
"dtslint": "dtslint __tests__/types" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { ListenerClass, Class, PubSubProvider } from "./PubSub"; | ||
|
||
|
||
export const Listener = < | ||
EventMap extends object, | ||
ListenedClass extends ListenerClass<ListenedClass, EventMap> | ||
>( | ||
eventBus: PubSubProvider<EventMap> | ||
) => (constructor: Class<ListenedClass>) => { | ||
const original = constructor; | ||
// override constructor to observe on every instantiation | ||
const ObserverClassConstructor = function(...args: any[]) { | ||
const instance = new original(...args); | ||
if (instance.__eventDefinitions) { | ||
// extract all listened observers | ||
for (const { | ||
specificEventIdentifier, | ||
methodName | ||
} of instance.__eventDefinitions) { | ||
// subscribe all observers | ||
eventBus | ||
.fromEvent(specificEventIdentifier) | ||
.subscribe((data: EventMap[keyof EventMap]) => { | ||
const method = instance[methodName]; | ||
if (typeof method === "function") { | ||
// bypassing type assertion to call the method | ||
((method as any) as Function).call(instance, data); | ||
} | ||
}); | ||
} | ||
} | ||
return instance; | ||
}; | ||
ObserverClassConstructor.prototype = original.prototype; | ||
// bypassing type checking because I can't make it work | ||
return (ObserverClassConstructor as any) as Class<ListenedClass>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { ListenerClass } from "./PubSub"; | ||
|
||
export const Observe = <EventMap extends object>() => | ||
// had to add another higher level function because I couldn't make typescript infer that the value of the argument 'event' should drive the argument of the observer | ||
<K extends keyof EventMap>(event: K) => < | ||
ThisClass extends ListenerClass<ThisClass, EventMap>, | ||
MethodType extends (data: EventMap[K]) => void | ||
>( | ||
targetObject: ThisClass, | ||
propertyKey: keyof ThisClass, | ||
descriptor: TypedPropertyDescriptor<MethodType> | ||
): TypedPropertyDescriptor<MethodType> => { | ||
createEventDefinitionsIfNeeded(targetObject); | ||
targetObject.__eventDefinitions!.push({ | ||
specificEventIdentifier: event, | ||
methodName: propertyKey | ||
}); | ||
return descriptor; | ||
}; | ||
|
||
function createEventDefinitionsIfNeeded< | ||
EventMap extends object, | ||
ThisClass extends ListenerClass<ThisClass, EventMap> | ||
>(targetObject: ThisClass) { | ||
if (!targetObject.__eventDefinitions) { | ||
targetObject.__eventDefinitions = []; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
interface InternalClassEventMetadata<ThisClass, EventMap extends object> { | ||
__eventDefinitions?: { | ||
specificEventIdentifier: keyof EventMap; | ||
methodName: keyof ThisClass; | ||
}[]; | ||
} | ||
|
||
export type ListenerClass<ThisClass, EventMap extends object> = Merge<ThisClass, InternalClassEventMetadata<ThisClass, EventMap>>; | ||
|
||
export interface PubSubProvider<EventMap extends object> { | ||
fromEvent<Key extends keyof EventMap>(event: Key): PubSubEvent<EventMap[Key]>; | ||
} | ||
|
||
export interface PubSubEvent<EventData> { | ||
subscribe(callback: (data: EventData) => void): void; | ||
publish(data: EventData): void; | ||
unsubscribe(): void; | ||
} | ||
|
||
// the following types were extracted from 'type-fest'; | ||
export type Class<T> = new(...arguments_: any[]) => T; | ||
export type Omit<ObjectType, KeysType extends keyof ObjectType> = Pick<ObjectType, Exclude<keyof ObjectType, KeysType>>; | ||
export type Merge<FirstType, SecondType> = Omit<FirstType, Extract<keyof FirstType, keyof SecondType>> & SecondType; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { Listener } from "./Listener"; | ||
import { Observe } from "./Observe"; | ||
import { PubSubEvent, PubSubProvider } from "./PubSub"; | ||
|
||
export { | ||
Listener, | ||
Observe, | ||
PubSubEvent, | ||
PubSubProvider | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"esModuleInterop": true, | ||
"target": "es5", | ||
"lib": [ "es5" ], | ||
"strict": true, | ||
"strictNullChecks": true, | ||
"strictFunctionTypes": true, | ||
"alwaysStrict": true, | ||
"noImplicitAny": true, | ||
"noImplicitReturns": true, | ||
"noImplicitThis": true, | ||
"moduleResolution": "node", | ||
"experimentalDecorators": true, | ||
"sourceMap": true, | ||
"outDir": "dist", | ||
"baseUrl": ".", | ||
"types": [] | ||
}, | ||
"include": [ | ||
"src/*" | ||
], | ||
"exclude": [ | ||
"__tests__/*", | ||
"node_modules" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"defaultSeverity": "error", | ||
"extends": [ | ||
"tslint:recommended", | ||
"tslint-clean-code", | ||
"tslint-plugin-prettier", | ||
"tslint-config-prettier" | ||
], | ||
"rules": { | ||
"prettier": true, | ||
"interface-name": [true, "never-prefix"], | ||
"try-catch-first": true, | ||
"max-func-args": [true, 3], | ||
"no-flag-args": true, | ||
"no-complex-conditionals": true, | ||
"no-commented-out-code": true | ||
} | ||
} |
Oops, something went wrong.