@ms-cloudpack/data-bus 0.0.2 → 0.1.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/CHANGELOG.json +46 -1
- package/CHANGELOG.md +10 -2
- package/README.md +1 -1
- package/lib/addProvider.d.ts +5 -0
- package/lib/addProvider.js +10 -0
- package/lib/addProvider.js.map +1 -0
- package/lib/addProvider.test.d.ts +1 -0
- package/lib/addProvider.test.js +58 -0
- package/lib/addProvider.test.js.map +1 -0
- package/lib/createDataBus.d.ts +5 -0
- package/lib/createDataBus.js +23 -0
- package/lib/createDataBus.js.map +1 -0
- package/lib/createDataBus.test.d.ts +1 -0
- package/lib/createDataBus.test.js +26 -0
- package/lib/createDataBus.test.js.map +1 -0
- package/lib/createNode.d.ts +2 -0
- package/lib/createNode.js +6 -0
- package/lib/createNode.js.map +1 -0
- package/lib/getData.d.ts +5 -0
- package/lib/getData.js +9 -0
- package/lib/getData.js.map +1 -0
- package/lib/getData.test.d.ts +1 -0
- package/lib/getData.test.js +33 -0
- package/lib/getData.test.js.map +1 -0
- package/lib/getNode.d.ts +9 -0
- package/lib/getNode.js +20 -0
- package/lib/getNode.js.map +1 -0
- package/lib/getNode.test.d.ts +1 -0
- package/lib/getNode.test.js +42 -0
- package/lib/getNode.test.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/publish.d.ts +5 -0
- package/lib/publish.js +23 -0
- package/lib/publish.js.map +1 -0
- package/lib/publish.test.d.ts +1 -0
- package/lib/publish.test.js +25 -0
- package/lib/publish.test.js.map +1 -0
- package/lib/subscribe.d.ts +2 -0
- package/lib/subscribe.js +44 -0
- package/lib/subscribe.js.map +1 -0
- package/lib/subscribe.test.d.ts +1 -0
- package/lib/subscribe.test.js +66 -0
- package/lib/subscribe.test.js.map +1 -0
- package/lib/tsdoc-metadata.json +11 -0
- package/lib/types.d.ts +39 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/package.json +12 -8
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,52 @@
|
|
|
2
2
|
"name": "@ms-cloudpack/data-bus",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Fri, 12 Aug 2022 08:12:22 GMT",
|
|
6
|
+
"tag": "@ms-cloudpack/data-bus_v0.1.0",
|
|
7
|
+
"version": "0.1.0",
|
|
8
|
+
"comments": {
|
|
9
|
+
"minor": [
|
|
10
|
+
{
|
|
11
|
+
"author": "dzearing@microsoft.com",
|
|
12
|
+
"package": "@ms-cloudpack/data-bus",
|
|
13
|
+
"commit": "e733241cb555d1ae14cdfd8fe211d1d05b471e29",
|
|
14
|
+
"comment": "Providers can now be added to the root of the data tree."
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "Fri, 20 May 2022 04:26:15 GMT",
|
|
21
|
+
"tag": "@ms-cloudpack/data-bus_v0.0.2",
|
|
22
|
+
"version": "0.0.2",
|
|
23
|
+
"comments": {
|
|
24
|
+
"none": [
|
|
25
|
+
{
|
|
26
|
+
"author": "dzearing@microsoft.com",
|
|
27
|
+
"package": "@ms-cloudpack/data-bus",
|
|
28
|
+
"commit": "b39bb143fc53e622c39f9e9fd349f71c9ebadd77",
|
|
29
|
+
"comment": "Adding api:update script."
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"date": "Sat, 14 May 2022 04:36:11 GMT",
|
|
36
|
+
"tag": "@ms-cloudpack/data-bus_v0.0.2",
|
|
37
|
+
"version": "0.0.2",
|
|
38
|
+
"comments": {
|
|
39
|
+
"none": [
|
|
40
|
+
{
|
|
41
|
+
"author": "dzearing@microsoft.com",
|
|
42
|
+
"package": "@ms-cloudpack/data-bus",
|
|
43
|
+
"commit": "cc0844a7d18790d69e59b16dbd6eef8fab5bc4e0",
|
|
44
|
+
"comment": "Updating package details."
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"date": "Mon, 09 May 2022 18:54:56 GMT",
|
|
6
51
|
"tag": "@ms-cloudpack/data-bus_v0.0.2",
|
|
7
52
|
"version": "0.0.2",
|
|
8
53
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
# Change Log - @ms-cloudpack/data-bus
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Fri, 12 Aug 2022 08:12:22 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 0.1.0
|
|
8
|
+
|
|
9
|
+
Fri, 12 Aug 2022 08:12:22 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- Providers can now be added to the root of the data tree. (dzearing@microsoft.com)
|
|
14
|
+
|
|
7
15
|
## 0.0.2
|
|
8
16
|
|
|
9
|
-
Mon, 09 May 2022 18:54:
|
|
17
|
+
Mon, 09 May 2022 18:54:56 GMT
|
|
10
18
|
|
|
11
19
|
### Patches
|
|
12
20
|
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ export const bus = createDataBus();
|
|
|
28
28
|
### Subscribing to data
|
|
29
29
|
|
|
30
30
|
The data bus provides a method `subscribe` for consumers to subscribe to different types of data. As that data changes, consumers will be notified of changes. Any number of consumers can subscribe for the same data. Data is
|
|
31
|
-
|
|
31
|
+
hierarchical, so you can subscribe to a full branch, or to a leaf node within the tree. Paths are represented by
|
|
32
32
|
string arrays.
|
|
33
33
|
|
|
34
34
|
```js
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getNode } from './getNode.js';
|
|
2
|
+
/**
|
|
3
|
+
* Adds a provider.
|
|
4
|
+
*/
|
|
5
|
+
export function addProvider(state, provider) {
|
|
6
|
+
const { node } = getNode(state, provider.path, true);
|
|
7
|
+
node.providers ?? (node.providers = []);
|
|
8
|
+
node.providers.push(provider);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=addProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addProvider.js","sourceRoot":"","sources":["../src/addProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAmB,EAAE,QAAyB;IACxE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAErD,IAAI,CAAC,SAAS,KAAd,IAAI,CAAC,SAAS,GAAK,EAAE,EAAC;IACtB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { addProvider } from './addProvider.js';
|
|
3
|
+
import { publish } from './publish.js';
|
|
4
|
+
import { subscribe } from './subscribe.js';
|
|
5
|
+
import { createDataBus } from './createDataBus.js';
|
|
6
|
+
const testBus = createDataBus();
|
|
7
|
+
function getTestProvider(path) {
|
|
8
|
+
return {
|
|
9
|
+
path,
|
|
10
|
+
onActivate: jest.fn(),
|
|
11
|
+
onDeactivate: jest.fn(),
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
onPublish: jest.fn(),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
describe('addProvider', () => {
|
|
17
|
+
it('can add a provider', () => {
|
|
18
|
+
const state = { root: {} };
|
|
19
|
+
const provider = getTestProvider(['a']);
|
|
20
|
+
addProvider(state, provider);
|
|
21
|
+
expect(state.root.children?.['a']?.providers).toContain(provider);
|
|
22
|
+
});
|
|
23
|
+
it('can have onActivate executed when a path is subscribed', () => {
|
|
24
|
+
const state = { root: {} };
|
|
25
|
+
const provider = getTestProvider(['a']);
|
|
26
|
+
const changeFn = jest.fn();
|
|
27
|
+
addProvider(state, provider);
|
|
28
|
+
subscribe(state, testBus, ['a'], changeFn);
|
|
29
|
+
expect(provider.onActivate).toBeCalledTimes(1);
|
|
30
|
+
subscribe(state, testBus, ['a'], changeFn);
|
|
31
|
+
expect(provider.onActivate).toBeCalledTimes(1);
|
|
32
|
+
expect(changeFn).not.toBeCalled();
|
|
33
|
+
});
|
|
34
|
+
it('can have onDeactivate executed when a path is unsubscribed', () => {
|
|
35
|
+
const state = { root: {} };
|
|
36
|
+
const provider = getTestProvider(['a']);
|
|
37
|
+
addProvider(state, provider);
|
|
38
|
+
const unsubscribe1 = subscribe(state, testBus, ['a'], jest.fn());
|
|
39
|
+
const unsubscribe2 = subscribe(state, testBus, ['a'], jest.fn());
|
|
40
|
+
expect(provider.onActivate).toBeCalled();
|
|
41
|
+
expect(provider.onDeactivate).not.toBeCalled();
|
|
42
|
+
unsubscribe1();
|
|
43
|
+
expect(provider.onDeactivate).not.toBeCalled();
|
|
44
|
+
unsubscribe2();
|
|
45
|
+
expect(provider.onDeactivate).toBeCalled();
|
|
46
|
+
});
|
|
47
|
+
it('can intercept publishing', () => {
|
|
48
|
+
const state = { root: {} };
|
|
49
|
+
const provider = getTestProvider(['a']);
|
|
50
|
+
const changeFn = jest.fn();
|
|
51
|
+
provider.onPublish = ({ value }) => 'new-' + value;
|
|
52
|
+
addProvider(state, provider);
|
|
53
|
+
subscribe(state, testBus, ['a'], changeFn);
|
|
54
|
+
publish(state, testBus, ['a'], 'test');
|
|
55
|
+
expect(changeFn.mock.calls).toEqual([['new-test', undefined, ['a']]]);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=addProvider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addProvider.test.js","sourceRoot":"","sources":["../src/addProvider.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { addProvider } from './addProvider.js';
|
|
2
|
+
import { createNode } from './createNode.js';
|
|
3
|
+
import { getData } from './getData.js';
|
|
4
|
+
import { publish } from './publish.js';
|
|
5
|
+
import { subscribe } from './subscribe.js';
|
|
6
|
+
/**
|
|
7
|
+
* Creates a new data bus instance.
|
|
8
|
+
*/
|
|
9
|
+
export function createDataBus() {
|
|
10
|
+
const state = {
|
|
11
|
+
root: createNode(),
|
|
12
|
+
};
|
|
13
|
+
const bus = {
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
publish: (path, value) => publish(state, bus, path, value),
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
getData: (path) => getData(state, path),
|
|
18
|
+
subscribe: (path, change) => subscribe(state, bus, path, change),
|
|
19
|
+
addProvider: (provider) => addProvider(state, provider),
|
|
20
|
+
};
|
|
21
|
+
return bus;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=createDataBus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDataBus.js","sourceRoot":"","sources":["../src/createDataBus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,KAAK,GAAiB;QAC1B,IAAI,EAAE,UAAU,EAAE;KACnB,CAAC;IAEF,MAAM,GAAG,GAAG;QACV,8DAA8D;QAC9D,OAAO,EAAE,CAAC,IAAc,EAAE,KAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC;QAEzE,8DAA8D;QAC9D,OAAO,EAAE,CAAc,IAAc,EAAE,EAAE,CAAC,OAAO,CAAQ,KAAK,EAAE,IAAI,CAAC;QAErE,SAAS,EAAE,CAAC,IAAc,EAAE,MAA6B,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC;QAEjG,WAAW,EAAE,CAAC,QAAyB,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC;KACzE,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createDataBus } from './createDataBus.js';
|
|
2
|
+
import { jest } from '@jest/globals';
|
|
3
|
+
describe('createDataBus', () => {
|
|
4
|
+
it('can pub/sub using a root provider', () => {
|
|
5
|
+
const bus = createDataBus();
|
|
6
|
+
const provider = {
|
|
7
|
+
path: [],
|
|
8
|
+
onActivate: jest.fn(),
|
|
9
|
+
onDeactivate: jest.fn(),
|
|
10
|
+
};
|
|
11
|
+
// Register provider
|
|
12
|
+
bus.addProvider(provider);
|
|
13
|
+
// Set up subscription
|
|
14
|
+
const onNotify = jest.fn();
|
|
15
|
+
const dispose = bus.subscribe(['status'], onNotify);
|
|
16
|
+
// We have not received any published data.
|
|
17
|
+
expect(onNotify).toBeCalledTimes(0);
|
|
18
|
+
// Expect an activation from the root provider.
|
|
19
|
+
expect(provider.onActivate).toBeCalledTimes(1);
|
|
20
|
+
// Dispose the subscription.
|
|
21
|
+
dispose();
|
|
22
|
+
// Expect a deactivation from the root provider.
|
|
23
|
+
expect(provider.onDeactivate).toBeCalledTimes(1);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=createDataBus.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDataBus.test.js","sourceRoot":"","sources":["../src/createDataBus.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,EAAE;YACR,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE;YACrB,YAAY,EAAE,IAAI,CAAC,EAAE,EAAE;SACxB,CAAC;QAEF,oBAAoB;QACpB,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAE1B,sBAAsB;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;QAEpD,2CAA2C;QAC3C,MAAM,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAEpC,+CAA+C;QAC/C,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAE/C,4BAA4B;QAC5B,OAAO,EAAE,CAAC;QAEV,gDAAgD;QAChD,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createNode.js","sourceRoot":"","sources":["../src/createNode.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CAAC,IAAI,GAAG,EAAE;IAClC,OAAO;QACL,IAAI;KACL,CAAC;AACJ,CAAC"}
|
package/lib/getData.d.ts
ADDED
package/lib/getData.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getData.js","sourceRoot":"","sources":["../src/getData.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;GAEG;AACH,MAAM,UAAU,OAAO,CAAQ,KAAmB,EAAE,IAAc;IAChE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEtC,OAAO,IAAI,EAAE,KAAK,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { getData } from './getData.js';
|
|
2
|
+
const testState = {
|
|
3
|
+
root: {
|
|
4
|
+
name: '',
|
|
5
|
+
children: {
|
|
6
|
+
a: {
|
|
7
|
+
name: 'a',
|
|
8
|
+
value: 'a',
|
|
9
|
+
providers: [],
|
|
10
|
+
subscribers: new Set(),
|
|
11
|
+
children: {
|
|
12
|
+
b: {
|
|
13
|
+
name: 'b',
|
|
14
|
+
value: 'b',
|
|
15
|
+
providers: [],
|
|
16
|
+
subscribers: new Set(),
|
|
17
|
+
children: {},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
describe('getData', () => {
|
|
25
|
+
it('can get existing data', () => {
|
|
26
|
+
expect(getData(testState, ['a', 'b'])).toEqual('b');
|
|
27
|
+
});
|
|
28
|
+
it('returns undefined on missing data and does not create nodes', () => {
|
|
29
|
+
expect(getData(testState, ['a', 'b', 'c'])).toBeUndefined();
|
|
30
|
+
expect(testState.root.children?.['a']?.children?.['b']?.children?.['c']).toBeUndefined();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=getData.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getData.test.js","sourceRoot":"","sources":["../src/getData.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,MAAM,SAAS,GAAiB;IAC9B,IAAI,EAAE;QACJ,IAAI,EAAE,EAAE;QACR,QAAQ,EAAE;YACR,CAAC,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,GAAG;gBACV,SAAS,EAAE,EAAE;gBACb,WAAW,EAAE,IAAI,GAAG,EAAE;gBACtB,QAAQ,EAAE;oBACR,CAAC,EAAE;wBACD,IAAI,EAAE,GAAG;wBACT,KAAK,EAAE,GAAG;wBACV,SAAS,EAAE,EAAE;wBACb,WAAW,EAAE,IAAI,GAAG,EAAE;wBACtB,QAAQ,EAAE,EAAE;qBACb;iBACF;aACF;SACF;KACF;CACF,CAAC;AAEF,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC5D,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3F,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/lib/getNode.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DataBusNode, DataBusState } from './types.js';
|
|
2
|
+
export declare function getNode(state: DataBusState, path: string[]): {
|
|
3
|
+
node: DataBusNode;
|
|
4
|
+
nodePath: DataBusNode[];
|
|
5
|
+
};
|
|
6
|
+
export declare function getNode(state: DataBusState, path: string[], createPath: true): {
|
|
7
|
+
node: DataBusNode;
|
|
8
|
+
nodePath: DataBusNode[];
|
|
9
|
+
};
|
package/lib/getNode.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createNode } from './createNode.js';
|
|
2
|
+
export function getNode(state, path, createPath) {
|
|
3
|
+
let index = 0;
|
|
4
|
+
let node = state.root;
|
|
5
|
+
const nodePath = [state.root];
|
|
6
|
+
while (node && index < path.length) {
|
|
7
|
+
const pathName = path[index++];
|
|
8
|
+
if (!node.children?.[pathName] && createPath) {
|
|
9
|
+
node.children ?? (node.children = {});
|
|
10
|
+
node.children[pathName] = createNode(pathName);
|
|
11
|
+
}
|
|
12
|
+
node = node.children?.[pathName];
|
|
13
|
+
nodePath.push(node);
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
node,
|
|
17
|
+
nodePath,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=getNode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getNode.js","sourceRoot":"","sources":["../src/getNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAoB7C,MAAM,UAAU,OAAO,CACrB,KAAmB,EACnB,IAAc,EACd,UAAoB;IAKpB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,IAAI,GAA4B,KAAK,CAAC,IAAI,CAAC;IAC/C,MAAM,QAAQ,GAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE7C,OAAO,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAE/B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,IAAI,UAAU,EAAE;YAC5C,IAAI,CAAC,QAAQ,KAAb,IAAI,CAAC,QAAQ,GAAK,EAAE,EAAC;YACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;SAChD;QAED,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC,IAAmB,CAAC,CAAC;KACpC;IAED,OAAO;QACL,IAAI;QACJ,QAAQ;KACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getNode } from './getNode.js';
|
|
2
|
+
function createTestState() {
|
|
3
|
+
return {
|
|
4
|
+
root: {
|
|
5
|
+
name: '',
|
|
6
|
+
children: {
|
|
7
|
+
a: {
|
|
8
|
+
name: 'a',
|
|
9
|
+
children: {
|
|
10
|
+
b: {
|
|
11
|
+
name: 'b',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
describe('getNode', () => {
|
|
20
|
+
it('can return a node', () => {
|
|
21
|
+
const testState = createTestState();
|
|
22
|
+
const { node, nodePath } = getNode(testState, ['a', 'b']);
|
|
23
|
+
expect(node).toBeDefined();
|
|
24
|
+
expect(node.name).toEqual('b');
|
|
25
|
+
expect(nodePath).toEqual([
|
|
26
|
+
testState.root,
|
|
27
|
+
testState.root.children?.['a'],
|
|
28
|
+
testState.root.children?.['a'].children?.['b'],
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
it('can return undefined on missing path', () => {
|
|
32
|
+
const testState = createTestState();
|
|
33
|
+
expect(getNode(testState, ['a', 'c']).node).toBeUndefined();
|
|
34
|
+
expect(testState.root.children?.['a']?.children?.['c']).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
it('can return undefined on missing path but create it when specified', () => {
|
|
37
|
+
const testState = createTestState();
|
|
38
|
+
expect(testState.root.children?.['a']?.children?.['c']).toBeUndefined();
|
|
39
|
+
expect(getNode(testState, ['a', 'c'], true).node).toBeTruthy();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=getNode.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getNode.test.js","sourceRoot":"","sources":["../src/getNode.test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,SAAS,eAAe;IACtB,OAAO;QACL,IAAI,EAAE;YACJ,IAAI,EAAE,EAAE;YACR,QAAQ,EAAE;gBACR,CAAC,EAAE;oBACD,IAAI,EAAE,GAAG;oBACT,QAAQ,EAAE;wBACR,CAAC,EAAE;4BACD,IAAI,EAAE,GAAG;yBACV;qBACF;iBACF;aACF;SACF;KACF,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;QACpC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAE1D,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YACvB,SAAS,CAAC,IAAI;YACd,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC;YAC9B,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC;SAC/C,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;QAEpC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;QAC5D,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;QAEpC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACxE,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
package/lib/publish.d.ts
ADDED
package/lib/publish.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { getNode } from './getNode.js';
|
|
2
|
+
/**
|
|
3
|
+
* Publishes data to a given dataPath/Id.
|
|
4
|
+
*/
|
|
5
|
+
export function publish(state, bus, path, value) {
|
|
6
|
+
const { node, nodePath } = getNode(state, path, true);
|
|
7
|
+
const oldValue = node.value;
|
|
8
|
+
// Notify pre-publishing providers and allow them to apply transforms or publish additional metadata.
|
|
9
|
+
for (let i = nodePath.length - 1; i >= 0; i--) {
|
|
10
|
+
nodePath[i].providers?.forEach((provider) => {
|
|
11
|
+
const newValue = provider.onPublish?.({ bus, value, oldValue, path });
|
|
12
|
+
if (newValue !== undefined) {
|
|
13
|
+
value = newValue;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
node.value = value;
|
|
18
|
+
// Notify subscribers
|
|
19
|
+
for (let i = nodePath.length - 1; i >= 0; i--) {
|
|
20
|
+
nodePath[i].subscribers?.forEach((subscriber) => subscriber(value, oldValue, path));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;GAEG;AACH,MAAM,UAAU,OAAO,CAAQ,KAAmB,EAAE,GAAY,EAAE,IAAc,EAAE,KAAY;IAC5F,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC;IAE5B,qGAAqG;IACrG,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;QAC7C,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC1C,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAEtE,IAAI,QAAQ,KAAK,SAAS,EAAE;gBAC1B,KAAK,GAAG,QAAQ,CAAC;aAClB;QACH,CAAC,CAAC,CAAC;KACJ;IAED,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IAEnB,qBAAqB;IACrB,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;QAC7C,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;KACrF;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { publish } from './publish.js';
|
|
2
|
+
import { createDataBus } from './createDataBus.js';
|
|
3
|
+
const testBus = createDataBus();
|
|
4
|
+
describe('publish', () => {
|
|
5
|
+
it('can publish to an existing value', () => {
|
|
6
|
+
const state = {
|
|
7
|
+
root: {
|
|
8
|
+
children: {
|
|
9
|
+
a: {
|
|
10
|
+
name: 'a',
|
|
11
|
+
value: 42,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
publish(state, testBus, ['a'], 43);
|
|
17
|
+
expect(state.root.children?.['a'].value).toEqual(43);
|
|
18
|
+
});
|
|
19
|
+
it('can publish to a non-existing value', () => {
|
|
20
|
+
const state = { root: {} };
|
|
21
|
+
publish(state, testBus, ['a'], 43);
|
|
22
|
+
expect(state.root.children?.['a'].value).toEqual(43);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=publish.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.test.js","sourceRoot":"","sources":["../src/publish.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAEhC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,KAAK,GAAiB;YAC1B,IAAI,EAAE;gBACJ,QAAQ,EAAE;oBACR,CAAC,EAAE;wBACD,IAAI,EAAE,GAAG;wBACT,KAAK,EAAE,EAAE;qBACV;iBACF;aACF;SACF,CAAC;QAEF,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAEnC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,KAAK,GAAiB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAEzC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/lib/subscribe.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { getNode } from './getNode.js';
|
|
2
|
+
export function subscribe(state, bus, path, change) {
|
|
3
|
+
const { node, nodePath } = getNode(state, path, true);
|
|
4
|
+
const { value } = node;
|
|
5
|
+
const pathString = path.join('/');
|
|
6
|
+
node.subscribers ?? (node.subscribers = new Set());
|
|
7
|
+
node.subscribers.add(change);
|
|
8
|
+
// Fire the initial change with the value.
|
|
9
|
+
if (value !== undefined) {
|
|
10
|
+
change(value, value, path);
|
|
11
|
+
}
|
|
12
|
+
// Activate any deactivated providers available for this path.
|
|
13
|
+
for (let index = nodePath.length - 1; index >= 0; index--) {
|
|
14
|
+
const currentNode = nodePath[index];
|
|
15
|
+
if (currentNode.providers?.length) {
|
|
16
|
+
const activeProviders = (currentNode.activeProviders ?? (currentNode.activeProviders = {}));
|
|
17
|
+
currentNode.providers.forEach((provider) => {
|
|
18
|
+
activeProviders[pathString] ?? (activeProviders[pathString] = { provider, count: 0 });
|
|
19
|
+
if (activeProviders[pathString].count === 0) {
|
|
20
|
+
provider.onActivate?.({ path, bus });
|
|
21
|
+
}
|
|
22
|
+
activeProviders[pathString].count++;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return () => {
|
|
27
|
+
node.subscribers?.delete(change);
|
|
28
|
+
// Deactivate providers.
|
|
29
|
+
for (let index = nodePath.length - 1; index >= 0; index--) {
|
|
30
|
+
const currentNode = nodePath[index];
|
|
31
|
+
if (currentNode.providers?.length) {
|
|
32
|
+
const activeRecord = currentNode.activeProviders?.[pathString];
|
|
33
|
+
if (activeRecord) {
|
|
34
|
+
activeRecord.count--;
|
|
35
|
+
if (!activeRecord.count) {
|
|
36
|
+
activeRecord?.provider.onDeactivate?.({ path, bus });
|
|
37
|
+
delete currentNode.activeProviders?.[pathString];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=subscribe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../src/subscribe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,MAAM,UAAU,SAAS,CACvB,KAAmB,EACnB,GAAY,EACZ,IAAc,EACd,MAA6B;IAE7B,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IACvB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,CAAC,WAAW,KAAhB,IAAI,CAAC,WAAW,GAAK,IAAI,GAAG,EAAyB,EAAC;IACtD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE7B,0CAA0C;IAC1C,IAAI,KAAK,KAAK,SAAS,EAAE;QACvB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;KAC5B;IAED,8DAA8D;IAC9D,KAAK,IAAI,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;QACzD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAEpC,IAAI,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE;YACjC,MAAM,eAAe,GAAG,CAAC,WAAW,CAAC,eAAe,KAA3B,WAAW,CAAC,eAAe,GAAK,EAAE,EAAC,CAAC;YAE7D,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;gBACzC,eAAe,CAAC,UAAU,MAA1B,eAAe,CAAC,UAAU,IAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,EAAC;gBAEvD,IAAI,eAAe,CAAC,UAAU,CAAC,CAAC,KAAK,KAAK,CAAC,EAAE;oBAC3C,QAAQ,CAAC,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;iBACtC;gBAED,eAAe,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC;YACtC,CAAC,CAAC,CAAC;SACJ;KACF;IAED,OAAO,GAAG,EAAE;QACV,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAEjC,wBAAwB;QACxB,KAAK,IAAI,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;YACzD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAEpC,IAAI,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE;gBACjC,MAAM,YAAY,GAAG,WAAW,CAAC,eAAe,EAAE,CAAC,UAAU,CAAC,CAAC;gBAE/D,IAAI,YAAY,EAAE;oBAChB,YAAY,CAAC,KAAK,EAAE,CAAC;oBAErB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE;wBACvB,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;wBACrD,OAAO,WAAW,CAAC,eAAe,EAAE,CAAC,UAAU,CAAC,CAAC;qBAClD;iBACF;aACF;SACF;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { createDataBus } from './createDataBus.js';
|
|
2
|
+
import { subscribe } from './subscribe.js';
|
|
3
|
+
import { getNode } from './getNode.js';
|
|
4
|
+
import { publish } from './publish.js';
|
|
5
|
+
import { jest } from '@jest/globals';
|
|
6
|
+
const testBus = createDataBus();
|
|
7
|
+
const testFunction = jest.fn();
|
|
8
|
+
describe('subscribe', () => {
|
|
9
|
+
it('can subscribe to missing data', () => {
|
|
10
|
+
const state = { root: {} };
|
|
11
|
+
subscribe(state, testBus, ['a', 'b'], testFunction);
|
|
12
|
+
expect(state.root.children?.['a']?.children?.['b']?.subscribers?.has(testFunction)).toBeTruthy();
|
|
13
|
+
});
|
|
14
|
+
it('can subscribe to existing data', () => {
|
|
15
|
+
const state = { root: {} };
|
|
16
|
+
// initialize nodes.
|
|
17
|
+
getNode(state, ['a', 'b'], true);
|
|
18
|
+
subscribe(state, testBus, ['a', 'b'], testFunction);
|
|
19
|
+
expect(state.root.children?.['a']?.children?.['b'].subscribers?.has(testFunction)).toBeTruthy();
|
|
20
|
+
});
|
|
21
|
+
it('is idempotent', () => {
|
|
22
|
+
const state = { root: {} };
|
|
23
|
+
subscribe(state, testBus, ['a', 'b'], testFunction);
|
|
24
|
+
subscribe(state, testBus, ['a', 'b'], testFunction);
|
|
25
|
+
expect(state.root.children?.['a']?.children?.['b'].subscribers?.size).toEqual(1);
|
|
26
|
+
});
|
|
27
|
+
it('does not fire a change when data is unavailable', () => {
|
|
28
|
+
const state = { root: {} };
|
|
29
|
+
const mockFunction = jest.fn();
|
|
30
|
+
subscribe(state, testBus, ['a', 'b'], mockFunction);
|
|
31
|
+
expect(mockFunction).toBeCalledTimes(0);
|
|
32
|
+
});
|
|
33
|
+
it('fires a change when data is available', () => {
|
|
34
|
+
const state = { root: {} };
|
|
35
|
+
const mockFunction = jest.fn();
|
|
36
|
+
publish(state, testBus, ['a', 'b'], 42);
|
|
37
|
+
subscribe(state, testBus, ['a', 'b'], mockFunction);
|
|
38
|
+
expect(mockFunction).toBeCalledTimes(1);
|
|
39
|
+
});
|
|
40
|
+
it('fires a change when data becomes available', () => {
|
|
41
|
+
const state = { root: {} };
|
|
42
|
+
const mockFunction = jest.fn();
|
|
43
|
+
subscribe(state, testBus, ['a', 'b'], mockFunction);
|
|
44
|
+
expect(mockFunction).toBeCalledTimes(0);
|
|
45
|
+
publish(state, testBus, ['a', 'b'], 42);
|
|
46
|
+
expect(mockFunction).toBeCalledTimes(1);
|
|
47
|
+
});
|
|
48
|
+
it('can subscribe to nested data', () => {
|
|
49
|
+
const state = { root: {} };
|
|
50
|
+
const mockFunction = jest.fn();
|
|
51
|
+
subscribe(state, testBus, ['a'], mockFunction);
|
|
52
|
+
expect(mockFunction).toBeCalledTimes(0);
|
|
53
|
+
publish(state, testBus, ['a', 'b'], 42);
|
|
54
|
+
expect(mockFunction).toBeCalledTimes(1);
|
|
55
|
+
expect(mockFunction.mock.calls[0]).toEqual([42, undefined, ['a', 'b']]);
|
|
56
|
+
});
|
|
57
|
+
it('can unsubscribe', () => {
|
|
58
|
+
const state = { root: {} };
|
|
59
|
+
const mockFunction = jest.fn();
|
|
60
|
+
const unsubscribe = subscribe(state, testBus, ['a', 'b'], mockFunction);
|
|
61
|
+
unsubscribe();
|
|
62
|
+
publish(state, testBus, ['a', 'b'], 42);
|
|
63
|
+
expect(mockFunction).toBeCalledTimes(0);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=subscribe.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscribe.test.js","sourceRoot":"","sources":["../src/subscribe.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
|
2
|
+
// It should be published with your NPM package. It should not be tracked by Git.
|
|
3
|
+
{
|
|
4
|
+
"tsdocVersion": "0.12",
|
|
5
|
+
"toolPackages": [
|
|
6
|
+
{
|
|
7
|
+
"packageName": "@microsoft/api-extractor",
|
|
8
|
+
"packageVersion": "7.29.0"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare type DataBusChangeFunction = <TData>(value: TData, oldValue: TData, path: string[]) => void;
|
|
2
|
+
export declare type DisposeFunction = () => void;
|
|
3
|
+
export interface DataBusProvider<TData = any> {
|
|
4
|
+
path: string[];
|
|
5
|
+
onActivate?: (options: {
|
|
6
|
+
path: string[];
|
|
7
|
+
bus: DataBus;
|
|
8
|
+
}) => void;
|
|
9
|
+
onDeactivate?: (options: {
|
|
10
|
+
path: string[];
|
|
11
|
+
bus: DataBus;
|
|
12
|
+
}) => void;
|
|
13
|
+
onPublish?: (options: {
|
|
14
|
+
value: TData;
|
|
15
|
+
oldValue: TData;
|
|
16
|
+
path: string[];
|
|
17
|
+
bus: DataBus;
|
|
18
|
+
}) => TData | undefined;
|
|
19
|
+
}
|
|
20
|
+
export interface DataBusNode {
|
|
21
|
+
name?: string;
|
|
22
|
+
value?: any;
|
|
23
|
+
providers?: DataBusProvider[];
|
|
24
|
+
activeProviders?: Record<string, {
|
|
25
|
+
provider: DataBusProvider;
|
|
26
|
+
count: number;
|
|
27
|
+
}>;
|
|
28
|
+
subscribers?: Set<DataBusChangeFunction>;
|
|
29
|
+
children?: Record<string, DataBusNode>;
|
|
30
|
+
}
|
|
31
|
+
export interface DataBusState {
|
|
32
|
+
root: DataBusNode;
|
|
33
|
+
}
|
|
34
|
+
export interface DataBus {
|
|
35
|
+
publish: (path: string[], value: any) => void;
|
|
36
|
+
subscribe: (path: string[], callback: DataBusChangeFunction) => DisposeFunction;
|
|
37
|
+
getData: (path: string[]) => any;
|
|
38
|
+
addProvider: (provider: DataBusProvider) => void;
|
|
39
|
+
}
|
package/lib/types.js
ADDED
package/lib/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ms-cloudpack/data-bus",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A data bus implementation.",
|
|
5
|
+
"license": "MIT",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"types": "./lib/index.js",
|
|
7
8
|
"sideEffects": false,
|
|
@@ -12,12 +13,15 @@
|
|
|
12
13
|
}
|
|
13
14
|
},
|
|
14
15
|
"scripts": {
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
16
|
+
"api:update": "cloudpack-scripts api-update",
|
|
17
|
+
"api": "cloudpack-scripts api",
|
|
18
|
+
"build:watch": "cloudpack-scripts build-watch",
|
|
19
|
+
"build": "cloudpack-scripts build",
|
|
20
|
+
"lint:update": "cloudpack-scripts lint-update",
|
|
21
|
+
"lint": "cloudpack-scripts lint",
|
|
22
|
+
"test:update": "cloudpack-scripts test-update",
|
|
23
|
+
"test:watch": "cloudpack-scripts test-watch",
|
|
24
|
+
"test": "cloudpack-scripts test"
|
|
21
25
|
},
|
|
22
26
|
"devDependencies": {
|
|
23
27
|
"@ms-cloudpack/scripts": "*",
|