@player-ui/player 0.8.0--canary.307.9621 → 0.8.0-next.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/dist/Player.native.js +11630 -0
- package/dist/Player.native.js.map +1 -0
- package/dist/cjs/index.cjs +5626 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/{index.esm.js → index.legacy-esm.js} +2044 -1667
- package/dist/{index.cjs.js → index.mjs} +2052 -1761
- package/dist/index.mjs.map +1 -0
- package/package.json +29 -63
- package/src/__tests__/data.test.ts +498 -0
- package/src/__tests__/flow.test.ts +312 -0
- package/src/__tests__/helpers/action-exp.plugin.ts +22 -0
- package/src/__tests__/helpers/actions.flow.ts +67 -0
- package/src/__tests__/helpers/binding.plugin.ts +125 -0
- package/src/__tests__/helpers/expression.plugin.ts +88 -0
- package/src/__tests__/helpers/transform-plugin.ts +19 -0
- package/src/__tests__/helpers/validation.flow.ts +56 -0
- package/src/__tests__/player.test.ts +597 -0
- package/src/__tests__/string-resolver.test.ts +186 -0
- package/src/__tests__/validation.test.ts +3555 -0
- package/src/__tests__/view.test.ts +715 -0
- package/src/binding/__tests__/binding.test.ts +113 -0
- package/src/binding/__tests__/index.test.ts +208 -0
- package/src/binding/__tests__/resolver.test.ts +83 -0
- package/src/binding/binding.ts +6 -6
- package/src/binding/index.ts +34 -34
- package/src/binding/resolver.ts +19 -19
- package/src/binding/utils.ts +7 -7
- package/src/binding-grammar/__tests__/parser.test.ts +64 -0
- package/src/binding-grammar/__tests__/test-utils/ast-cases.ts +198 -0
- package/src/binding-grammar/__tests__/test-utils/perf-test.ts +66 -0
- package/src/binding-grammar/ast.ts +11 -11
- package/src/binding-grammar/custom/index.ts +19 -22
- package/src/binding-grammar/ebnf/index.ts +20 -21
- package/src/binding-grammar/ebnf/types.ts +13 -13
- package/src/binding-grammar/index.ts +4 -4
- package/src/binding-grammar/parsimmon/index.ts +14 -14
- package/src/controllers/constants/__tests__/index.test.ts +106 -0
- package/src/controllers/constants/index.ts +3 -3
- package/src/controllers/constants/utils.ts +4 -4
- package/src/controllers/data/controller.ts +22 -22
- package/src/controllers/data/index.ts +1 -1
- package/src/controllers/data/utils.ts +7 -7
- package/src/controllers/flow/__tests__/controller.test.ts +195 -0
- package/src/controllers/flow/__tests__/flow.test.ts +381 -0
- package/src/controllers/flow/controller.ts +13 -13
- package/src/controllers/flow/flow.ts +23 -23
- package/src/controllers/flow/index.ts +2 -2
- package/src/controllers/index.ts +5 -5
- package/src/controllers/validation/binding-tracker.ts +71 -59
- package/src/controllers/validation/controller.ts +104 -104
- package/src/controllers/validation/index.ts +2 -2
- package/src/controllers/view/asset-transform.ts +20 -20
- package/src/controllers/view/controller.ts +27 -27
- package/src/controllers/view/index.ts +4 -4
- package/src/controllers/view/store.ts +3 -3
- package/src/controllers/view/types.ts +7 -7
- package/src/data/__tests__/__snapshots__/dependency-tracker.test.ts.snap +64 -0
- package/src/data/__tests__/dependency-tracker.test.ts +146 -0
- package/src/data/__tests__/local-model.test.ts +46 -0
- package/src/data/__tests__/model.test.ts +78 -0
- package/src/data/dependency-tracker.ts +16 -16
- package/src/data/index.ts +4 -4
- package/src/data/local-model.ts +6 -6
- package/src/data/model.ts +17 -17
- package/src/data/noop-model.ts +1 -1
- package/src/expressions/__tests__/__snapshots__/parser.test.ts.snap +854 -0
- package/src/expressions/__tests__/evaluator-functions.test.ts +47 -0
- package/src/expressions/__tests__/evaluator.test.ts +410 -0
- package/src/expressions/__tests__/parser.test.ts +115 -0
- package/src/expressions/__tests__/utils.test.ts +44 -0
- package/src/expressions/evaluator-functions.ts +6 -6
- package/src/expressions/evaluator.ts +71 -67
- package/src/expressions/index.ts +4 -4
- package/src/expressions/parser.ts +102 -105
- package/src/expressions/types.ts +29 -21
- package/src/expressions/utils.ts +32 -21
- package/src/index.ts +13 -13
- package/src/logger/__tests__/consoleLogger.test.ts +46 -0
- package/src/logger/__tests__/noopLogger.test.ts +13 -0
- package/src/logger/__tests__/proxyLogger.test.ts +31 -0
- package/src/logger/__tests__/tapableLogger.test.ts +41 -0
- package/src/logger/consoleLogger.ts +9 -9
- package/src/logger/index.ts +5 -5
- package/src/logger/noopLogger.ts +1 -1
- package/src/logger/proxyLogger.ts +6 -6
- package/src/logger/tapableLogger.ts +7 -7
- package/src/logger/types.ts +2 -2
- package/src/player.ts +60 -58
- package/src/plugins/default-exp-plugin.ts +10 -10
- package/src/plugins/default-view-plugin.ts +29 -0
- package/src/plugins/flow-exp-plugin.ts +6 -6
- package/src/schema/__tests__/schema.test.ts +243 -0
- package/src/schema/index.ts +2 -2
- package/src/schema/schema.ts +24 -24
- package/src/schema/types.ts +4 -4
- package/src/string-resolver/__tests__/index.test.ts +361 -0
- package/src/string-resolver/index.ts +17 -17
- package/src/types.ts +17 -17
- package/src/utils/__tests__/replaceParams.test.ts +33 -0
- package/src/utils/index.ts +1 -1
- package/src/utils/replaceParams.ts +1 -1
- package/src/validator/__tests__/binding-map-splice.test.ts +53 -0
- package/src/validator/__tests__/validation-middleware.test.ts +127 -0
- package/src/validator/binding-map-splice.ts +5 -5
- package/src/validator/index.ts +4 -4
- package/src/validator/registry.ts +1 -1
- package/src/validator/types.ts +13 -13
- package/src/validator/validation-middleware.ts +15 -15
- package/src/view/__tests__/view.immutable.test.ts +269 -0
- package/src/view/__tests__/view.test.ts +959 -0
- package/src/view/builder/index.test.ts +69 -0
- package/src/view/builder/index.ts +3 -3
- package/src/view/index.ts +5 -5
- package/src/view/parser/__tests__/__snapshots__/parser.test.ts.snap +394 -0
- package/src/view/parser/__tests__/parser.test.ts +264 -0
- package/src/view/parser/index.ts +43 -33
- package/src/view/parser/types.ts +11 -11
- package/src/view/parser/utils.ts +5 -5
- package/src/view/plugins/__tests__/__snapshots__/template.test.ts.snap +278 -0
- package/src/view/plugins/__tests__/applicability.test.ts +265 -0
- package/src/view/plugins/__tests__/string.test.ts +122 -0
- package/src/view/plugins/__tests__/template.test.ts +724 -0
- package/src/view/plugins/applicability.ts +19 -19
- package/src/view/plugins/index.ts +4 -5
- package/src/view/plugins/options.ts +1 -1
- package/src/view/plugins/string-resolver.ts +22 -22
- package/src/view/plugins/switch.ts +22 -23
- package/src/view/plugins/template-plugin.ts +26 -27
- package/src/view/resolver/__tests__/dependencies.test.ts +321 -0
- package/src/view/resolver/__tests__/edgecases.test.ts +626 -0
- package/src/view/resolver/index.ts +42 -42
- package/src/view/resolver/types.ts +21 -20
- package/src/view/resolver/utils.ts +9 -9
- package/src/view/view.ts +32 -22
- package/types/binding/binding.d.ts +50 -0
- package/types/binding/index.d.ts +29 -0
- package/types/binding/resolver.d.ts +26 -0
- package/types/binding/utils.d.ts +12 -0
- package/types/binding-grammar/ast.d.ts +67 -0
- package/types/binding-grammar/custom/index.d.ts +4 -0
- package/types/binding-grammar/ebnf/index.d.ts +4 -0
- package/types/binding-grammar/ebnf/types.d.ts +75 -0
- package/types/binding-grammar/index.d.ts +5 -0
- package/types/binding-grammar/parsimmon/index.d.ts +4 -0
- package/types/controllers/constants/index.d.ts +45 -0
- package/types/controllers/constants/utils.d.ts +6 -0
- package/types/controllers/data/controller.d.ts +45 -0
- package/types/controllers/data/index.d.ts +2 -0
- package/types/controllers/data/utils.d.ts +14 -0
- package/types/controllers/flow/controller.d.ts +25 -0
- package/types/controllers/flow/flow.d.ts +50 -0
- package/types/controllers/flow/index.d.ts +3 -0
- package/types/controllers/index.d.ts +6 -0
- package/types/controllers/validation/binding-tracker.d.ts +32 -0
- package/types/controllers/validation/controller.d.ts +151 -0
- package/types/controllers/validation/index.d.ts +3 -0
- package/types/controllers/view/asset-transform.d.ts +19 -0
- package/types/controllers/view/controller.d.ts +37 -0
- package/types/controllers/view/index.d.ts +5 -0
- package/types/controllers/view/store.d.ts +20 -0
- package/types/controllers/view/types.d.ts +16 -0
- package/types/data/dependency-tracker.d.ts +49 -0
- package/types/data/index.d.ts +5 -0
- package/types/data/local-model.d.ts +16 -0
- package/types/data/model.d.ts +86 -0
- package/types/data/noop-model.d.ts +13 -0
- package/types/expressions/evaluator-functions.d.ts +15 -0
- package/types/expressions/evaluator.d.ts +52 -0
- package/types/expressions/index.d.ts +5 -0
- package/types/expressions/parser.d.ts +10 -0
- package/types/expressions/types.d.ts +144 -0
- package/types/expressions/utils.d.ts +12 -0
- package/types/index.d.ts +14 -0
- package/types/logger/consoleLogger.d.ts +17 -0
- package/types/logger/index.d.ts +6 -0
- package/types/logger/noopLogger.d.ts +10 -0
- package/types/logger/proxyLogger.d.ts +15 -0
- package/types/logger/tapableLogger.d.ts +23 -0
- package/types/logger/types.d.ts +6 -0
- package/types/player.d.ts +101 -0
- package/types/plugins/default-exp-plugin.d.ts +9 -0
- package/types/plugins/default-view-plugin.d.ts +9 -0
- package/types/plugins/flow-exp-plugin.d.ts +11 -0
- package/types/schema/index.d.ts +3 -0
- package/types/schema/schema.d.ts +36 -0
- package/types/schema/types.d.ts +38 -0
- package/types/string-resolver/index.d.ts +30 -0
- package/types/types.d.ts +73 -0
- package/types/utils/index.d.ts +2 -0
- package/types/utils/replaceParams.d.ts +9 -0
- package/types/validator/binding-map-splice.d.ts +10 -0
- package/types/validator/index.d.ts +5 -0
- package/types/validator/registry.d.ts +11 -0
- package/types/validator/types.d.ts +53 -0
- package/types/validator/validation-middleware.d.ts +36 -0
- package/types/view/builder/index.d.ts +35 -0
- package/types/view/index.d.ts +6 -0
- package/types/view/parser/index.d.ts +52 -0
- package/types/view/parser/types.d.ts +109 -0
- package/types/view/parser/utils.d.ts +6 -0
- package/types/view/plugins/applicability.d.ts +10 -0
- package/types/view/plugins/index.d.ts +5 -0
- package/types/view/plugins/options.d.ts +4 -0
- package/types/view/plugins/string-resolver.d.ts +13 -0
- package/types/view/plugins/switch.d.ts +14 -0
- package/types/view/plugins/template-plugin.d.ts +33 -0
- package/types/view/resolver/index.d.ts +73 -0
- package/types/view/resolver/types.d.ts +129 -0
- package/types/view/resolver/utils.d.ts +11 -0
- package/types/view/view.d.ts +37 -0
- package/dist/index.d.ts +0 -1814
- package/dist/player.dev.js +0 -11472
- package/dist/player.prod.js +0 -2
- package/src/view/plugins/plugin.ts +0 -21
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Node } from
|
|
2
|
-
import { NodeType } from
|
|
3
|
-
import { LocalStateStore } from
|
|
4
|
-
import type { TransformRegistry } from
|
|
5
|
-
import type { ViewController } from
|
|
1
|
+
import type { Node } from "../../view";
|
|
2
|
+
import { NodeType } from "../../view";
|
|
3
|
+
import { LocalStateStore } from "./store";
|
|
4
|
+
import type { TransformRegistry } from "./types";
|
|
5
|
+
import type { ViewController } from "./controller";
|
|
6
6
|
|
|
7
7
|
/** Traverse up the nodes until the target is found */
|
|
8
8
|
function findUp(node: Node.Node, target: Node.Node): boolean {
|
|
@@ -32,18 +32,18 @@ export class AssetTransformCorePlugin {
|
|
|
32
32
|
constructor(registry: TransformRegistry) {
|
|
33
33
|
this.registry = registry;
|
|
34
34
|
this.stateStore = new Map();
|
|
35
|
-
this.beforeResolveSymbol = Symbol(
|
|
36
|
-
this.resolveSymbol = Symbol(
|
|
37
|
-
this.beforeResolveCountSymbol = Symbol(
|
|
38
|
-
this.resolveCountSymbol = Symbol(
|
|
35
|
+
this.beforeResolveSymbol = Symbol("before resolve");
|
|
36
|
+
this.resolveSymbol = Symbol("resolve");
|
|
37
|
+
this.beforeResolveCountSymbol = Symbol("before resolve count");
|
|
38
|
+
this.resolveCountSymbol = Symbol("resolve count");
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
apply(viewController: ViewController) {
|
|
42
|
-
viewController.hooks.view.tap(
|
|
42
|
+
viewController.hooks.view.tap("asset-transform", (view) => {
|
|
43
43
|
// Clear out everything when we create a new view
|
|
44
44
|
this.stateStore.clear();
|
|
45
45
|
|
|
46
|
-
view.hooks.resolver.tap(
|
|
46
|
+
view.hooks.resolver.tap("asset-transform", (resolver) => {
|
|
47
47
|
let lastUpdatedNode: Node.Node | undefined;
|
|
48
48
|
|
|
49
49
|
/** A function to update the state and trigger a view re-compute */
|
|
@@ -74,27 +74,27 @@ export class AssetTransformCorePlugin {
|
|
|
74
74
|
|
|
75
75
|
return {
|
|
76
76
|
useSharedState: (
|
|
77
|
-
key: string | symbol
|
|
77
|
+
key: string | symbol,
|
|
78
78
|
): (<T>(initialState: T) => readonly [T, (value: T) => void]) => {
|
|
79
79
|
return store.useSharedState(key);
|
|
80
80
|
},
|
|
81
81
|
useLocalState: <T>(initialState: T) => {
|
|
82
82
|
return store.getLocalStateFunction<T>(
|
|
83
83
|
stepKey,
|
|
84
|
-
countKey
|
|
84
|
+
countKey,
|
|
85
85
|
)(initialState);
|
|
86
86
|
},
|
|
87
87
|
};
|
|
88
88
|
};
|
|
89
89
|
|
|
90
|
-
resolver.hooks.beforeResolve.tap(
|
|
91
|
-
if (node && (node.type ===
|
|
90
|
+
resolver.hooks.beforeResolve.tap("asset-transform", (node, options) => {
|
|
91
|
+
if (node && (node.type === "asset" || node.type === "view")) {
|
|
92
92
|
const transform = this.registry.get(node.value);
|
|
93
93
|
|
|
94
94
|
if (transform?.beforeResolve) {
|
|
95
95
|
const store = getStore(
|
|
96
96
|
options.node ?? node,
|
|
97
|
-
this.beforeResolveSymbol
|
|
97
|
+
this.beforeResolveSymbol,
|
|
98
98
|
);
|
|
99
99
|
|
|
100
100
|
return transform.beforeResolve(node, options, store);
|
|
@@ -104,11 +104,11 @@ export class AssetTransformCorePlugin {
|
|
|
104
104
|
return node;
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
resolver.hooks.afterUpdate.tap(
|
|
107
|
+
resolver.hooks.afterUpdate.tap("asset-transform", () => {
|
|
108
108
|
lastUpdatedNode = undefined;
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
-
resolver.hooks.skipResolve.tap(
|
|
111
|
+
resolver.hooks.skipResolve.tap("asset-transform", (skip, node) => {
|
|
112
112
|
if (!skip || !lastUpdatedNode) {
|
|
113
113
|
return skip;
|
|
114
114
|
}
|
|
@@ -120,7 +120,7 @@ export class AssetTransformCorePlugin {
|
|
|
120
120
|
});
|
|
121
121
|
|
|
122
122
|
resolver.hooks.afterResolve.tap(
|
|
123
|
-
|
|
123
|
+
"asset-transform",
|
|
124
124
|
(value, node, options) => {
|
|
125
125
|
if (node.type !== NodeType.Asset && node.type !== NodeType.View) {
|
|
126
126
|
return value;
|
|
@@ -141,7 +141,7 @@ export class AssetTransformCorePlugin {
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
return value;
|
|
144
|
-
}
|
|
144
|
+
},
|
|
145
145
|
);
|
|
146
146
|
});
|
|
147
147
|
});
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { SyncHook, SyncWaterfallHook } from
|
|
2
|
-
import queueMicrotask from
|
|
3
|
-
import { Registry } from
|
|
4
|
-
import type { View, NavigationFlowViewState } from
|
|
5
|
-
|
|
6
|
-
import { resolveDataRefsInString } from
|
|
7
|
-
import type { Resolve } from
|
|
8
|
-
import { ViewInstance } from
|
|
9
|
-
import type { Logger } from
|
|
10
|
-
import type { FlowInstance, FlowController } from
|
|
11
|
-
import type { DataController } from
|
|
12
|
-
import { AssetTransformCorePlugin } from
|
|
13
|
-
import type { TransformRegistry } from
|
|
14
|
-
import type { BindingInstance } from
|
|
1
|
+
import { SyncHook, SyncWaterfallHook } from "tapable-ts";
|
|
2
|
+
import queueMicrotask from "queue-microtask";
|
|
3
|
+
import { Registry } from "@player-ui/partial-match-registry";
|
|
4
|
+
import type { View, NavigationFlowViewState } from "@player-ui/types";
|
|
5
|
+
|
|
6
|
+
import { resolveDataRefsInString } from "../../string-resolver";
|
|
7
|
+
import type { Resolve } from "../../view";
|
|
8
|
+
import { ViewInstance } from "../../view";
|
|
9
|
+
import type { Logger } from "../../logger";
|
|
10
|
+
import type { FlowInstance, FlowController } from "../flow";
|
|
11
|
+
import type { DataController } from "../data/controller";
|
|
12
|
+
import { AssetTransformCorePlugin } from "./asset-transform";
|
|
13
|
+
import type { TransformRegistry } from "./types";
|
|
14
|
+
import type { BindingInstance } from "../../binding";
|
|
15
15
|
|
|
16
16
|
export interface ViewControllerOptions {
|
|
17
17
|
/** Where to get data from */
|
|
@@ -51,7 +51,7 @@ export class ViewController {
|
|
|
51
51
|
|
|
52
52
|
constructor(
|
|
53
53
|
initialViews: View[],
|
|
54
|
-
options: Resolve.ResolverOptions & ViewControllerOptions
|
|
54
|
+
options: Resolve.ResolverOptions & ViewControllerOptions,
|
|
55
55
|
) {
|
|
56
56
|
this.viewOptions = options;
|
|
57
57
|
this.viewMap = initialViews.reduce<Record<string, View>>(
|
|
@@ -60,22 +60,22 @@ export class ViewController {
|
|
|
60
60
|
viewMap[view.id] = view;
|
|
61
61
|
return viewMap;
|
|
62
62
|
},
|
|
63
|
-
{}
|
|
63
|
+
{},
|
|
64
64
|
);
|
|
65
65
|
|
|
66
66
|
new AssetTransformCorePlugin(this.transformRegistry).apply(this);
|
|
67
67
|
|
|
68
68
|
options.flowController.hooks.flow.tap(
|
|
69
|
-
|
|
69
|
+
"viewController",
|
|
70
70
|
(flow: FlowInstance) => {
|
|
71
|
-
flow.hooks.transition.tap(
|
|
72
|
-
if (newState.value.state_type ===
|
|
71
|
+
flow.hooks.transition.tap("viewController", (_oldState, newState) => {
|
|
72
|
+
if (newState.value.state_type === "VIEW") {
|
|
73
73
|
this.onView(newState.value);
|
|
74
74
|
} else {
|
|
75
75
|
this.currentView = undefined;
|
|
76
76
|
}
|
|
77
77
|
});
|
|
78
|
-
}
|
|
78
|
+
},
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
/** Trigger a view update */
|
|
@@ -90,21 +90,21 @@ export class ViewController {
|
|
|
90
90
|
};
|
|
91
91
|
|
|
92
92
|
options.model.hooks.onUpdate.tap(
|
|
93
|
-
|
|
93
|
+
"viewController",
|
|
94
94
|
(updates, updateOptions) => {
|
|
95
95
|
update(
|
|
96
96
|
new Set(updates.map((t) => t.binding)),
|
|
97
|
-
updateOptions?.silent ?? false
|
|
97
|
+
updateOptions?.silent ?? false,
|
|
98
98
|
);
|
|
99
|
-
}
|
|
99
|
+
},
|
|
100
100
|
);
|
|
101
101
|
|
|
102
|
-
options.model.hooks.onDelete.tap(
|
|
102
|
+
options.model.hooks.onDelete.tap("viewController", (binding) => {
|
|
103
103
|
const parentBinding = binding.parent();
|
|
104
104
|
const property = binding.key();
|
|
105
105
|
|
|
106
106
|
// Deleting an array item will trigger an update for the entire array
|
|
107
|
-
if (typeof property ===
|
|
107
|
+
if (typeof property === "number" && parentBinding) {
|
|
108
108
|
update(new Set([parentBinding]));
|
|
109
109
|
} else {
|
|
110
110
|
update(new Set([binding]));
|
|
@@ -148,7 +148,7 @@ export class ViewController {
|
|
|
148
148
|
resolveDataRefsInString(possibleViewIdMatch, {
|
|
149
149
|
model: this.viewOptions.model,
|
|
150
150
|
evaluate: this.viewOptions.evaluator.evaluate,
|
|
151
|
-
})
|
|
151
|
+
}),
|
|
152
152
|
);
|
|
153
153
|
|
|
154
154
|
if (matchingViewId && this.viewMap[matchingViewId]) {
|
|
@@ -162,7 +162,7 @@ export class ViewController {
|
|
|
162
162
|
const source = this.hooks.resolveView.call(
|
|
163
163
|
this.getViewForRef(viewId),
|
|
164
164
|
viewId,
|
|
165
|
-
state
|
|
165
|
+
state,
|
|
166
166
|
);
|
|
167
167
|
|
|
168
168
|
if (!source) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
1
|
+
export * from "./asset-transform";
|
|
2
|
+
export * from "./controller";
|
|
3
|
+
export * from "./store";
|
|
4
|
+
export * from "./types";
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
export interface Store {
|
|
2
2
|
useLocalState<T>(initialState: T): readonly [T, (value: T) => void];
|
|
3
3
|
useSharedState<T>(
|
|
4
|
-
key: string | symbol
|
|
4
|
+
key: string | symbol,
|
|
5
5
|
): (initialState: T) => readonly [T, (value: T) => void];
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
interface SharedStore {
|
|
9
9
|
getLocalStateFunction<T>(
|
|
10
10
|
key: string | symbol,
|
|
11
|
-
countKey: symbol
|
|
11
|
+
countKey: symbol,
|
|
12
12
|
): (initialState: T) => readonly [T, (value: T) => void];
|
|
13
13
|
useSharedState<T>(
|
|
14
|
-
key: string | symbol
|
|
14
|
+
key: string | symbol,
|
|
15
15
|
): (initialState: T) => readonly [T, (value: T) => void];
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import type { Asset } from
|
|
2
|
-
import type { Registry } from
|
|
1
|
+
import type { Asset } from "@player-ui/types";
|
|
2
|
+
import type { Registry } from "@player-ui/partial-match-registry";
|
|
3
3
|
|
|
4
|
-
import type { Resolve, Node } from
|
|
5
|
-
import type { Store } from
|
|
4
|
+
import type { Resolve, Node } from "../../view";
|
|
5
|
+
import type { Store } from "./store";
|
|
6
6
|
|
|
7
7
|
/** Transform function that is ran on the Asset before it's resolved */
|
|
8
8
|
export type BeforeTransformFunction<AuthoredAsset extends Asset = Asset> = (
|
|
9
9
|
asset: Node.Asset<AuthoredAsset> | Node.View<AuthoredAsset>,
|
|
10
10
|
options: Resolve.NodeResolveOptions,
|
|
11
|
-
store: Store
|
|
11
|
+
store: Store,
|
|
12
12
|
) => Node.Node;
|
|
13
13
|
|
|
14
14
|
/** Transform function that is ran on the Asset after it's resolved */
|
|
15
15
|
export type TransformFunction<
|
|
16
16
|
AuthoredAsset extends Asset = Asset,
|
|
17
|
-
TransformedAsset extends Asset = AuthoredAsset
|
|
17
|
+
TransformedAsset extends Asset = AuthoredAsset,
|
|
18
18
|
> = (
|
|
19
19
|
asset: AuthoredAsset,
|
|
20
20
|
options: Resolve.NodeResolveOptions,
|
|
21
|
-
store: Store
|
|
21
|
+
store: Store,
|
|
22
22
|
) => TransformedAsset;
|
|
23
23
|
|
|
24
24
|
export interface TransformFunctions {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`dependency model > tracks dependency sets correctly 1`] = `
|
|
4
|
+
Set {
|
|
5
|
+
BindingInstance {
|
|
6
|
+
"factory": [Function],
|
|
7
|
+
"joined": "foo.bar",
|
|
8
|
+
"split": [
|
|
9
|
+
"foo",
|
|
10
|
+
"bar",
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
}
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
exports[`dependency model > tracks dependency sets correctly 2`] = `
|
|
17
|
+
Set {
|
|
18
|
+
BindingInstance {
|
|
19
|
+
"factory": [Function],
|
|
20
|
+
"joined": "foo.baz",
|
|
21
|
+
"split": [
|
|
22
|
+
"foo",
|
|
23
|
+
"baz",
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
BindingInstance {
|
|
27
|
+
"factory": [Function],
|
|
28
|
+
"joined": "foo.bad",
|
|
29
|
+
"split": [
|
|
30
|
+
"foo",
|
|
31
|
+
"bad",
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
exports[`dependency model > tracks dependency sets correctly 3`] = `
|
|
38
|
+
Set {
|
|
39
|
+
BindingInstance {
|
|
40
|
+
"factory": [Function],
|
|
41
|
+
"joined": "foo.bar",
|
|
42
|
+
"split": [
|
|
43
|
+
"foo",
|
|
44
|
+
"bar",
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
BindingInstance {
|
|
48
|
+
"factory": [Function],
|
|
49
|
+
"joined": "foo.baz",
|
|
50
|
+
"split": [
|
|
51
|
+
"foo",
|
|
52
|
+
"baz",
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
BindingInstance {
|
|
56
|
+
"factory": [Function],
|
|
57
|
+
"joined": "foo.bad",
|
|
58
|
+
"split": [
|
|
59
|
+
"foo",
|
|
60
|
+
"bad",
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { BindingParser } from "../../binding";
|
|
3
|
+
import { LocalModel, DependencyModel, DependencyMiddleware } from "..";
|
|
4
|
+
|
|
5
|
+
const parser = new BindingParser({
|
|
6
|
+
get: () => undefined,
|
|
7
|
+
set: () => undefined,
|
|
8
|
+
evaluate: () => undefined,
|
|
9
|
+
});
|
|
10
|
+
const binding = parser.parse("foo.bar");
|
|
11
|
+
|
|
12
|
+
describe("dependency model", () => {
|
|
13
|
+
it("tracks reads", () => {
|
|
14
|
+
const trackedModel = new DependencyModel(
|
|
15
|
+
new LocalModel({ foo: { bar: "baz" } }),
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
trackedModel.get(binding);
|
|
19
|
+
expect(trackedModel.readsBinding(binding)).toBe(true);
|
|
20
|
+
expect(trackedModel.readsBinding(parser.parse("foo.baz"))).toBe(false);
|
|
21
|
+
expect(trackedModel.getDependencies().size).toBe(1);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("tracks writes", () => {
|
|
25
|
+
const trackedModel = new DependencyModel(
|
|
26
|
+
new LocalModel({ foo: { bar: "baz" } }),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
trackedModel.set([[binding, "not baz"]]);
|
|
30
|
+
expect(trackedModel.writesBinding(binding)).toBe(true);
|
|
31
|
+
expect(trackedModel.writesBinding(parser.parse("foo.baz"))).toBe(false);
|
|
32
|
+
expect(trackedModel.getModified().size).toBe(1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it(`uses the existing set instead of recreating a new one`, () => {
|
|
36
|
+
const trackedModel = new DependencyModel(
|
|
37
|
+
new LocalModel({ foo: { bar: "baz" } }),
|
|
38
|
+
);
|
|
39
|
+
const binding2 = parser.parse("foo.baz");
|
|
40
|
+
|
|
41
|
+
trackedModel.trackSubset("core");
|
|
42
|
+
trackedModel.get(binding);
|
|
43
|
+
trackedModel.trackSubset("core");
|
|
44
|
+
trackedModel.get(binding2);
|
|
45
|
+
|
|
46
|
+
expect(trackedModel.getDependencies("core").size).toBe(2);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("tracks dependency sets correctly", () => {
|
|
50
|
+
const trackedModel = new DependencyModel(
|
|
51
|
+
new LocalModel({ foo: { bar: "baz" } }),
|
|
52
|
+
);
|
|
53
|
+
const binding2 = parser.parse("foo.baz");
|
|
54
|
+
const binding3 = parser.parse("foo.bad");
|
|
55
|
+
|
|
56
|
+
trackedModel.trackSubset("children");
|
|
57
|
+
trackedModel.get(binding);
|
|
58
|
+
trackedModel.trackSubset("core");
|
|
59
|
+
trackedModel.get(binding2);
|
|
60
|
+
trackedModel.trackDefault();
|
|
61
|
+
trackedModel.get(binding3);
|
|
62
|
+
|
|
63
|
+
expect(trackedModel.getDependencies("children")).toMatchSnapshot();
|
|
64
|
+
expect(trackedModel.getDependencies("core")).toMatchSnapshot();
|
|
65
|
+
expect(trackedModel.getDependencies()).toMatchSnapshot();
|
|
66
|
+
|
|
67
|
+
trackedModel.reset();
|
|
68
|
+
expect(trackedModel.getDependencies("children").size).toBe(0);
|
|
69
|
+
expect(trackedModel.getDependencies("core").size).toBe(0);
|
|
70
|
+
expect(trackedModel.getDependencies().size).toBe(0);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("adds a tracked dependency to children set", () => {
|
|
74
|
+
const trackedModel = new DependencyModel(
|
|
75
|
+
new LocalModel({ foo: { bar: "baz" } }),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
trackedModel.addChildReadDep(binding);
|
|
79
|
+
expect(trackedModel.getDependencies("children").size).toBe(1);
|
|
80
|
+
expect(trackedModel.getDependencies("core").size).toBe(0);
|
|
81
|
+
expect(trackedModel.getDependencies().size).toBe(1);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("dependency model middleware", () => {
|
|
86
|
+
it("tracks reads", () => {
|
|
87
|
+
const base = new LocalModel({ foo: { bar: "baz" } });
|
|
88
|
+
const trackedModel = new DependencyMiddleware();
|
|
89
|
+
|
|
90
|
+
trackedModel.get(binding, undefined, base);
|
|
91
|
+
expect(trackedModel.readsBinding(binding)).toBe(true);
|
|
92
|
+
expect(trackedModel.readsBinding(parser.parse("foo.baz"))).toBe(false);
|
|
93
|
+
expect(trackedModel.getDependencies().size).toBe(1);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("tracks a subset of read dependencies", () => {
|
|
97
|
+
const base = new LocalModel({ foo: { bar: "baz" } });
|
|
98
|
+
const binding2 = parser.parse("foo.baz");
|
|
99
|
+
const trackedModel = new DependencyMiddleware();
|
|
100
|
+
|
|
101
|
+
trackedModel.trackSubset("children");
|
|
102
|
+
trackedModel.get(binding, undefined, base);
|
|
103
|
+
trackedModel.trackDefault();
|
|
104
|
+
trackedModel.get(binding2, undefined, base);
|
|
105
|
+
|
|
106
|
+
expect(trackedModel.getDependencies("children").size).toBe(1);
|
|
107
|
+
expect(trackedModel.getDependencies("core").size).toBe(1);
|
|
108
|
+
expect(trackedModel.getDependencies().size).toBe(2);
|
|
109
|
+
|
|
110
|
+
trackedModel.reset();
|
|
111
|
+
expect(trackedModel.getDependencies("children").size).toBe(0);
|
|
112
|
+
expect(trackedModel.getDependencies("core").size).toBe(0);
|
|
113
|
+
expect(trackedModel.getDependencies().size).toBe(0);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("tracks writes", () => {
|
|
117
|
+
const base = new LocalModel({ foo: { bar: "baz" } });
|
|
118
|
+
const trackedModel = new DependencyMiddleware();
|
|
119
|
+
trackedModel.set([[binding, "not baz"]], undefined, base);
|
|
120
|
+
expect(trackedModel.writesBinding(binding)).toBe(true);
|
|
121
|
+
expect(trackedModel.writesBinding(parser.parse("foo.baz"))).toBe(false);
|
|
122
|
+
expect(trackedModel.getModified().size).toBe(1);
|
|
123
|
+
trackedModel.reset();
|
|
124
|
+
expect(trackedModel.getModified().size).toBe(0);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("tracks a subset of write dependencies", () => {
|
|
128
|
+
const base = new LocalModel({ foo: { bar: "baz" } });
|
|
129
|
+
const binding2 = parser.parse("foo.baz");
|
|
130
|
+
const trackedModel = new DependencyMiddleware();
|
|
131
|
+
|
|
132
|
+
trackedModel.trackSubset("children");
|
|
133
|
+
trackedModel.set([[binding, "not baz"]], undefined, base);
|
|
134
|
+
trackedModel.trackDefault();
|
|
135
|
+
trackedModel.set([[binding2, "not bar"]], undefined, base);
|
|
136
|
+
|
|
137
|
+
expect(trackedModel.getModified("children").size).toBe(1);
|
|
138
|
+
expect(trackedModel.getModified("core").size).toBe(1);
|
|
139
|
+
expect(trackedModel.getModified().size).toBe(2);
|
|
140
|
+
|
|
141
|
+
trackedModel.reset();
|
|
142
|
+
expect(trackedModel.getModified("children").size).toBe(0);
|
|
143
|
+
expect(trackedModel.getModified("core").size).toBe(0);
|
|
144
|
+
expect(trackedModel.getModified().size).toBe(0);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { it, expect } from "vitest";
|
|
2
|
+
import { BindingParser } from "../../binding";
|
|
3
|
+
import { LocalModel } from "..";
|
|
4
|
+
|
|
5
|
+
const parser = new BindingParser({
|
|
6
|
+
get: () => undefined,
|
|
7
|
+
set: () => undefined,
|
|
8
|
+
evaluate: () => undefined,
|
|
9
|
+
});
|
|
10
|
+
const binding = parser.parse("foo.bar");
|
|
11
|
+
it("sets data", () => {
|
|
12
|
+
const model = new LocalModel();
|
|
13
|
+
model.set([[binding, "baz"]]);
|
|
14
|
+
expect(model.get(binding)).toBe("baz");
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("overrides data", () => {
|
|
18
|
+
const model = new LocalModel({ foo: { bar: "baz" } });
|
|
19
|
+
expect(model.get(binding)).toBe("baz");
|
|
20
|
+
model.set([[binding, "not baz"]]);
|
|
21
|
+
expect(model.get(binding)).toBe("not baz");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("gets data", () => {
|
|
25
|
+
const model = new LocalModel({ foo: { bar: "baz" } });
|
|
26
|
+
expect(model.get(binding)).toBe("baz");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("resets data", () => {
|
|
30
|
+
const model = new LocalModel({ foo: { bar: "baz" } });
|
|
31
|
+
expect(model.get(binding)).toBe("baz");
|
|
32
|
+
model.reset();
|
|
33
|
+
expect(model.get(binding)).toBe(undefined);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("resets data starting with new model", () => {
|
|
37
|
+
const model = new LocalModel({ foo: { bar: "baz" } });
|
|
38
|
+
expect(model.get(binding)).toBe("baz");
|
|
39
|
+
model.reset({ foo: { bar: "not baz" } });
|
|
40
|
+
expect(model.get(binding)).toBe("not baz");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("retuns the whole model when no binding is passed", () => {
|
|
44
|
+
const model = new LocalModel({ foo: { bar: "baz" } });
|
|
45
|
+
expect(model.get()).toStrictEqual({ foo: { bar: "baz" } });
|
|
46
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vitest } from "vitest";
|
|
2
|
+
import { BindingInstance, BindingParser } from "../../binding";
|
|
3
|
+
import type { DataModelMiddleware } from "..";
|
|
4
|
+
import { LocalModel, PipelinedDataModel } from "..";
|
|
5
|
+
import { withParser } from "../model";
|
|
6
|
+
import type { BatchSetTransaction } from "../model";
|
|
7
|
+
|
|
8
|
+
const { parse } = new BindingParser({
|
|
9
|
+
get: () => undefined,
|
|
10
|
+
set: () => undefined,
|
|
11
|
+
evaluate: () => undefined,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("model", () => {
|
|
15
|
+
let localModel: LocalModel;
|
|
16
|
+
let model: PipelinedDataModel;
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
localModel = new LocalModel();
|
|
20
|
+
|
|
21
|
+
const middleware: DataModelMiddleware = {
|
|
22
|
+
get(binding, options, next) {
|
|
23
|
+
return next?.get(binding, options);
|
|
24
|
+
},
|
|
25
|
+
set(transaction, options, next) {
|
|
26
|
+
const newTransaction: BatchSetTransaction = [];
|
|
27
|
+
transaction.forEach(([binding, val]) => {
|
|
28
|
+
if (val !== "bad") {
|
|
29
|
+
newTransaction.push([binding, val]);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return next?.set(newTransaction, options) ?? [];
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
model = new PipelinedDataModel();
|
|
38
|
+
model.addMiddleware(localModel);
|
|
39
|
+
model.addMiddleware(middleware);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("works with basic middleware", () => {
|
|
43
|
+
model.set([
|
|
44
|
+
[parse("foo.bar"), "bad"],
|
|
45
|
+
[parse("foo.baz"), "good"],
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
expect(localModel.get(parse("foo.bar"))).toBe(undefined);
|
|
49
|
+
expect(localModel.get(parse("foo.baz"))).toBe("good");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("works with withParser", () => {
|
|
53
|
+
const mockParse = vitest.fn(() => new BindingInstance(["some", "binding"]));
|
|
54
|
+
|
|
55
|
+
const modelWithParser = withParser(model, mockParse);
|
|
56
|
+
|
|
57
|
+
modelWithParser.get("some.binding");
|
|
58
|
+
|
|
59
|
+
expect(mockParse).toHaveBeenCalledWith(
|
|
60
|
+
"some.binding",
|
|
61
|
+
expect.objectContaining({ readOnly: true }),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
modelWithParser.set([["some.binding", "test"]]);
|
|
65
|
+
|
|
66
|
+
expect(mockParse).toHaveBeenCalledWith(
|
|
67
|
+
"some.binding",
|
|
68
|
+
expect.objectContaining({ readOnly: false }),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
modelWithParser.delete(["some.binding"]);
|
|
72
|
+
|
|
73
|
+
expect(mockParse).toHaveBeenCalledWith(
|
|
74
|
+
"some.binding",
|
|
75
|
+
expect.objectContaining({ readOnly: false }),
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
});
|