@vandeurenglenn/little-pubsub 1.4.8 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,6 +17,20 @@ import PubSub from '@vandeurenglenn/little-pubsub'
17
17
  const pubsub = new PubSub()
18
18
  ```
19
19
 
20
+ ## Breaking Changes
21
+
22
+ ### v1.5.0
23
+
24
+ `subscribe[context]` & `unsubscribe[context]` -> `subscribe[options({keepValue, context})]`
25
+
26
+ ```js
27
+ // before
28
+ pusbub.subscribe(topic, handler, context)
29
+
30
+ // now
31
+ pusbub.subscribe(topic, handler, { context })
32
+ ```
33
+
20
34
  ## Example
21
35
 
22
36
  ```js
@@ -57,7 +71,9 @@ pubsub = new PubSub({
57
71
 
58
72
  `name`: name of the channel to subscribe to<br>
59
73
  `handler`: method<br>
60
- `context`: context<br>
74
+ `options`: { context, keepValue }<br>
75
+
76
+ subscribing to an event will also return it's initial value
61
77
 
62
78
  ```js
63
79
  pubsub.subscribe('event-name', (data) => {
@@ -69,12 +85,16 @@ pubsub.subscribe('event-name', (data) => {
69
85
 
70
86
  `name`: name of the channel to unsubscribe<br>
71
87
  `handler`: method<br>
72
- `context`: context<br>
88
+ `options`: { context, keepValue }<br>
73
89
 
74
90
  ```js
75
- pubsub.unsubscribe('event-name', (data) => {
76
- console.log(data)
77
- })
91
+ pubsub.unsubscribe(
92
+ 'event-name',
93
+ (data) => {
94
+ console.log(data)
95
+ },
96
+ { keepValue: false } // default
97
+ )
78
98
  ```
79
99
 
80
100
  #### publish
package/index.d.ts CHANGED
@@ -10,9 +10,17 @@ export default class LittlePubSub {
10
10
  _handleContext(handler: Function, context?: Function): Function;
11
11
  hasSubscribers(event: string): boolean;
12
12
  getValue(event: string): any;
13
- subscribe(event: string, handler: Function, context?: Function): void;
14
- unsubscribe(event: string, handler: Function, context?: Function): void;
13
+ subscribe(event: string, handler: Function, options?: {
14
+ context?: Function;
15
+ }): void;
16
+ unsubscribe(event: string, handler: Function, options?: {
17
+ keepValue?: boolean;
18
+ context?: Function;
19
+ }): void;
15
20
  publish(event: string, value: string | number | boolean | object | Array<any>, verbose?: boolean): void;
16
21
  publishVerbose(event: string, value: string | number | boolean | object | Array<any>): void;
17
- once(event: string): Promise<string | number | boolean | object | Array<any>>;
22
+ once(event: string, options?: {
23
+ keepValue?: boolean;
24
+ context?: Function;
25
+ }): Promise<string | number | boolean | object | Array<any>>;
18
26
  }
package/index.js CHANGED
@@ -18,19 +18,26 @@ export default class LittlePubSub {
18
18
  return this.subscribers[event].value;
19
19
  return undefined;
20
20
  }
21
- subscribe(event, handler, context) {
21
+ subscribe(event, handler, options) {
22
22
  if (!this.hasSubscribers(event))
23
23
  this.subscribers[event] = { handlers: [], value: undefined };
24
- context = this._handleContext(handler, context);
25
- this.subscribers[event].handlers.push(handler.bind(context));
24
+ const context = this._handleContext(handler, options?.context);
25
+ const _handler = handler.bind(context);
26
+ this.subscribers[event].handlers.push(_handler);
27
+ if (this.subscribers[event].value !== undefined)
28
+ _handler(this.subscribers[event].value, undefined);
26
29
  }
27
- unsubscribe(event, handler, context) {
30
+ unsubscribe(event, handler, options) {
31
+ if (!options)
32
+ options = { keepValue: false };
28
33
  if (!this.hasSubscribers(event))
29
34
  return;
30
- context = this._handleContext(handler, context);
35
+ const context = this._handleContext(handler, options.context);
31
36
  const index = this.subscribers[event].handlers.indexOf(handler.bind(context));
32
37
  this.subscribers[event].handlers.splice(index);
33
- if (this.subscribers[event].handlers.length === 0)
38
+ // delete event if no handlers left but supports keeping value for later use
39
+ // (like when unsubscribing from a value that is still needed because others might subscibe to it)
40
+ if (this.subscribers[event].handlers.length === 0 && !options.keepValue)
34
41
  delete this.subscribers[event];
35
42
  }
36
43
  publish(event, value, verbose) {
@@ -50,13 +57,13 @@ export default class LittlePubSub {
50
57
  publishVerbose(event, value) {
51
58
  this.publish(event, value, true);
52
59
  }
53
- once(event) {
60
+ once(event, options) {
54
61
  return new Promise((resolve) => {
55
62
  const cb = (value) => {
56
63
  resolve(value);
57
- this.unsubscribe(event, cb);
64
+ this.unsubscribe(event, cb, options);
58
65
  };
59
- this.subscribe(event, cb);
66
+ this.subscribe(event, cb, options);
60
67
  });
61
68
  }
62
69
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vandeurenglenn/little-pubsub",
3
- "version": "1.4.8",
3
+ "version": "1.5.0",
4
4
  "description": "Publish & Subscribe",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -10,12 +10,15 @@
10
10
  "types": "./index.d.ts"
11
11
  }
12
12
  },
13
+ "files": [
14
+ "index.js",
15
+ "index.d.ts"
16
+ ],
13
17
  "repository": "https://github.com/vandeurenglenn/little-pubsub",
14
18
  "author": "vandeurenglenn <vandeurenglenn@gmail.com>",
15
19
  "license": "MIT",
16
20
  "type": "module",
17
21
  "private": false,
18
- "flat": true,
19
22
  "scripts": {
20
23
  "build": "npx tsc",
21
24
  "test": "node test.js"
@@ -28,6 +31,6 @@
28
31
  ],
29
32
  "devDependencies": {
30
33
  "tape": "^5.8.1",
31
- "typescript": "^5.5.3"
34
+ "typescript": "^5.6.2"
32
35
  }
33
36
  }
package/.prettierrc DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "tabWidth": 2,
3
- "semi": false,
4
- "singleQuote": true,
5
- "printWidth": 80,
6
- "trailingComma": "none"
7
- }
package/.travis.yml DELETED
@@ -1,8 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - '16'
4
- - '22'
5
- cache:
6
- yarn: true
7
- before_script:
8
- - npm run build
package/src/index.ts DELETED
@@ -1,83 +0,0 @@
1
- export default class LittlePubSub {
2
- subscribers: { [index: string]: { value?: any; handlers?: Function[] } } = {}
3
- verbose: boolean
4
-
5
- constructor(verbose?: boolean) {
6
- this.verbose = verbose
7
- }
8
-
9
- _handleContext(handler: Function, context?: Function): Function {
10
- if (typeof context === 'undefined') {
11
- context = handler
12
- }
13
- return context
14
- }
15
-
16
- hasSubscribers(event: string): boolean {
17
- return this.subscribers[event] ? true : false
18
- }
19
-
20
- getValue(event: string): any {
21
- if (this.subscribers[event]) return this.subscribers[event].value
22
- return undefined
23
- }
24
-
25
- subscribe(event: string, handler: Function, context?: Function): void {
26
- if (!this.hasSubscribers(event))
27
- this.subscribers[event] = { handlers: [], value: undefined }
28
-
29
- context = this._handleContext(handler, context)
30
- this.subscribers[event].handlers.push(handler.bind(context))
31
- }
32
-
33
- unsubscribe(event: string, handler: Function, context?: Function): void {
34
- if (!this.hasSubscribers(event)) return
35
-
36
- context = this._handleContext(handler, context)
37
- const index = this.subscribers[event].handlers.indexOf(
38
- handler.bind(context)
39
- )
40
- this.subscribers[event].handlers.splice(index)
41
- if (this.subscribers[event].handlers.length === 0)
42
- delete this.subscribers[event]
43
- }
44
-
45
- publish(
46
- event: string,
47
- value: string | number | boolean | object | Array<any>,
48
- verbose?: boolean
49
- ): void {
50
- // always set value even when having no subscribers
51
- if (!this.hasSubscribers(event))
52
- this.subscribers[event] = {
53
- handlers: []
54
- }
55
- const oldValue = this.subscribers[event]?.value
56
-
57
- if (this.verbose || verbose || oldValue !== value) {
58
- this.subscribers[event].value = value
59
- for (const handler of this.subscribers[event].handlers) {
60
- handler(value, oldValue)
61
- }
62
- }
63
- }
64
-
65
- publishVerbose(
66
- event: string,
67
- value: string | number | boolean | object | Array<any>
68
- ) {
69
- this.publish(event, value, true)
70
- }
71
-
72
- once(
73
- event: string
74
- ): Promise<string | number | boolean | object | Array<any>> {
75
- return new Promise((resolve) => {
76
- const cb = (value: string | number | boolean | object | Array<any>) => {
77
- resolve(value)
78
- this.unsubscribe(event, cb)
79
- }
80
- this.subscribe(event, cb)
81
- })
82
- }
83
- }
package/test.js DELETED
@@ -1,53 +0,0 @@
1
- import test from 'tape'
2
- import PubSub from './index.js'
3
-
4
- test('pubsub is defined', (tape) => {
5
- tape.plan(1)
6
- const pubsub = new PubSub()
7
- tape.ok(typeof pubsub === 'object')
8
-
9
- test('pubsub subscribes & publishes & unsubscribes', (tape) => {
10
- tape.plan(1)
11
- pubsub.subscribe('on', (value) => {
12
- tape.ok(value)
13
- pubsub.unsubscribe('on', (value) => tape.ok(value))
14
- })
15
- pubsub.publish('on', 5)
16
- })
17
-
18
- test('pubsub subscribes & publishesVerbose', (tape) => {
19
- tape.plan(2)
20
- pubsub.subscribe('on', (value) => tape.ok(value))
21
- pubsub.publish('on', 5)
22
- pubsub.publishVerbose('on', 5)
23
- })
24
-
25
- test('pubsub getValue', (tape) => {
26
- tape.plan(1)
27
- let value = pubsub.getValue('on')
28
- tape.ok(value === 5)
29
- })
30
-
31
- test('pubsub unsubscribes', (tape) => {
32
- tape.plan(1)
33
- pubsub.unsubscribe('on', (value) => tape.ok(value))
34
- tape.ok(Boolean(Object.keys(pubsub.subscribers).length === 0))
35
- })
36
-
37
- test('pubsub once', async (tape) => {
38
- tape.plan(1)
39
- setTimeout(() => pubsub.publish('on', true), 1000)
40
- let value = await pubsub.once('on')
41
- tape.ok(value === true)
42
- })
43
-
44
- test('pubsub without subscribers', async (tape) => {
45
- tape.plan(1)
46
- try {
47
- pubsub.publish('on', true)
48
- tape.ok(true)
49
- } catch (error) {
50
- tape.ok(false)
51
- }
52
- })
53
- })
package/tsconfig.json DELETED
@@ -1,14 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "outDir": "./",
4
- "moduleResolution": "NodeNext",
5
- "esModuleInterop": true,
6
- "allowSyntheticDefaultImports": true,
7
- "allowJs": false,
8
- "declaration": true,
9
- "target": "ES2022",
10
- "module": "NodeNext"
11
- },
12
- "include": ["./src/**/*"],
13
- "exclude": ["node_modules"]
14
- }