@ankhorage/runtime 5.0.6 → 5.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.md +12 -0
- package/README.md +1 -1
- package/dist/ManifestContext.d.ts +7 -3
- package/dist/ManifestContext.d.ts.map +1 -1
- package/dist/ManifestContext.js +9 -2
- package/dist/ManifestContext.js.map +1 -1
- package/dist/RuntimeRenderer.d.ts.map +1 -1
- package/dist/RuntimeRenderer.js +36 -26
- package/dist/RuntimeRenderer.js.map +1 -1
- package/dist/RuntimeScreen.d.ts.map +1 -1
- package/dist/RuntimeScreen.js +6 -3
- package/dist/RuntimeScreen.js.map +1 -1
- package/dist/capabilities/index.d.ts +47 -0
- package/dist/capabilities/index.d.ts.map +1 -1
- package/dist/capabilities/index.js +34 -0
- package/dist/capabilities/index.js.map +1 -1
- package/dist/runtimeCapabilityExecutor.d.ts +3 -1
- package/dist/runtimeCapabilityExecutor.d.ts.map +1 -1
- package/dist/runtimeCapabilityExecutor.js +91 -2
- package/dist/runtimeCapabilityExecutor.js.map +1 -1
- package/dist/runtimeStateAdapter.d.ts.map +1 -1
- package/dist/runtimeStateAdapter.js +25 -13
- package/dist/runtimeStateAdapter.js.map +1 -1
- package/dist/useRuntimeStateBindings.d.ts +9 -0
- package/dist/useRuntimeStateBindings.d.ts.map +1 -0
- package/dist/useRuntimeStateBindings.js +50 -0
- package/dist/useRuntimeStateBindings.js.map +1 -0
- package/package.json +70 -3
- package/paradox/badges/npm.svg +3 -3
- package/paradox/components.md +8 -5
- package/paradox/diagrams/architecture-overview.mmd +13 -0
- package/paradox/diagrams/export-graph.mmd +2 -0
- package/paradox/diagrams/module-relationships.mmd +11 -0
- package/paradox/diagrams/sequences/runtime-screen.mmd +5 -0
- package/paradox/exports.json +25 -18
- package/paradox/exports.md +23 -14
- package/paradox/index.html +259 -92
- package/paradox/paradox.json +534 -99
|
@@ -1,8 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
import { isRecord } from '@ankhorage/utility/object';
|
|
2
|
+
/*** Routes API and state capabilities before delegating application-owned capabilities. */
|
|
2
3
|
export function composeRuntimeCapabilityExecutor(composition) {
|
|
3
4
|
return async (args) => args.capability.startsWith('api.')
|
|
4
5
|
? composition.apiCapabilityExecutor(args)
|
|
5
|
-
:
|
|
6
|
+
: args.capability === 'state.set'
|
|
7
|
+
? executeStateSetCapabilityAsync(args, composition.stateAdapter)
|
|
8
|
+
: executeApplicationCapabilityAsync(args, composition.capabilityExecutor);
|
|
9
|
+
}
|
|
10
|
+
/*** Applies one serializable state value through the configured application state adapter. */
|
|
11
|
+
function executeStateSetCapabilityAsync(args, stateAdapter) {
|
|
12
|
+
if (stateAdapter === undefined)
|
|
13
|
+
return Promise.resolve(missingStateAdapterResult());
|
|
14
|
+
const input = resolveStateSetInput(args.input);
|
|
15
|
+
if (input === undefined)
|
|
16
|
+
return Promise.resolve(invalidStateSetInputResult());
|
|
17
|
+
try {
|
|
18
|
+
const result = stateAdapter.set(input.path, input.value);
|
|
19
|
+
return Promise.resolve(result.ok
|
|
20
|
+
? { data: { path: input.path, value: input.value }, ok: true }
|
|
21
|
+
: {
|
|
22
|
+
diagnostics: [
|
|
23
|
+
{
|
|
24
|
+
code: result.error.code,
|
|
25
|
+
message: result.error.message,
|
|
26
|
+
severity: 'error',
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
ok: false,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return Promise.resolve(stateAdapterSetErrorResult(error));
|
|
34
|
+
}
|
|
6
35
|
}
|
|
7
36
|
async function executeApplicationCapabilityAsync(args, capabilityExecutor) {
|
|
8
37
|
if (capabilityExecutor !== undefined)
|
|
@@ -18,4 +47,64 @@ async function executeApplicationCapabilityAsync(args, capabilityExecutor) {
|
|
|
18
47
|
ok: false,
|
|
19
48
|
};
|
|
20
49
|
}
|
|
50
|
+
function resolveStateSetInput(input) {
|
|
51
|
+
if (!isRecord(input) || !('value' in input))
|
|
52
|
+
return undefined;
|
|
53
|
+
const { path, value } = input;
|
|
54
|
+
if (!isStatePath(path) || !isStateValue(value))
|
|
55
|
+
return undefined;
|
|
56
|
+
return { path, value };
|
|
57
|
+
}
|
|
58
|
+
function isStatePath(value) {
|
|
59
|
+
return ((typeof value === 'string' && value.trim().length > 0) ||
|
|
60
|
+
(Array.isArray(value) &&
|
|
61
|
+
value.length > 0 &&
|
|
62
|
+
value.every((part) => typeof part === 'string' && part.trim().length > 0)));
|
|
63
|
+
}
|
|
64
|
+
function isStateValue(value) {
|
|
65
|
+
if (value === null || typeof value === 'boolean' || typeof value === 'string')
|
|
66
|
+
return true;
|
|
67
|
+
if (typeof value === 'number')
|
|
68
|
+
return Number.isFinite(value);
|
|
69
|
+
if (Array.isArray(value))
|
|
70
|
+
return value.every(isStateValue);
|
|
71
|
+
return isRecord(value) && Object.values(value).every(isStateValue);
|
|
72
|
+
}
|
|
73
|
+
/*** Converts thrown adapter failures into capability diagnostics at the public Runtime boundary. */
|
|
74
|
+
function stateAdapterSetErrorResult(error) {
|
|
75
|
+
return {
|
|
76
|
+
diagnostics: [
|
|
77
|
+
{
|
|
78
|
+
code: 'state-adapter-error',
|
|
79
|
+
message: error instanceof Error ? error.message : 'StateAdapter.set failed.',
|
|
80
|
+
severity: 'error',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
ok: false,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function missingStateAdapterResult() {
|
|
87
|
+
return {
|
|
88
|
+
diagnostics: [
|
|
89
|
+
{
|
|
90
|
+
code: 'missing-adapter',
|
|
91
|
+
message: "Capability 'state.set' requires a configured StateAdapter.",
|
|
92
|
+
severity: 'error',
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
ok: false,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function invalidStateSetInputResult() {
|
|
99
|
+
return {
|
|
100
|
+
diagnostics: [
|
|
101
|
+
{
|
|
102
|
+
code: 'invalid-input',
|
|
103
|
+
message: "Capability 'state.set' requires a non-empty path and serializable value.",
|
|
104
|
+
severity: 'error',
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
ok: false,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
21
110
|
//# sourceMappingURL=runtimeCapabilityExecutor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimeCapabilityExecutor.js","sourceRoot":"","sources":["../src/runtimeCapabilityExecutor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtimeCapabilityExecutor.js","sourceRoot":"","sources":["../src/runtimeCapabilityExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StateAdapter, StatePath, StateValue } from '@ankhorage/contracts';\nimport { isRecord } from '@ankhorage/utility/object';\n\nimport type {\n RuntimeCapabilityExecutionArgs,\n RuntimeCapabilityExecutionResult,\n RuntimeCapabilityExecutor,\n} from './runtimeBindings';\n\nexport interface RuntimeCapabilityExecutorComposition {\n readonly apiCapabilityExecutor: RuntimeCapabilityExecutor;\n readonly capabilityExecutor?: RuntimeCapabilityExecutor;\n readonly stateAdapter?: StateAdapter;\n}\n\n/*** Routes API and state capabilities before delegating application-owned capabilities. */\nexport function composeRuntimeCapabilityExecutor(\n composition: RuntimeCapabilityExecutorComposition,\n): RuntimeCapabilityExecutor {\n return async (args) =>\n args.capability.startsWith('api.')\n ? composition.apiCapabilityExecutor(args)\n : args.capability === 'state.set'\n ? executeStateSetCapabilityAsync(args, composition.stateAdapter)\n : executeApplicationCapabilityAsync(args, composition.capabilityExecutor);\n}\n\n/*** Applies one serializable state value through the configured application state adapter. */\nfunction executeStateSetCapabilityAsync(\n args: RuntimeCapabilityExecutionArgs,\n stateAdapter: StateAdapter | undefined,\n): Promise<RuntimeCapabilityExecutionResult> {\n if (stateAdapter === undefined) return Promise.resolve(missingStateAdapterResult());\n\n const input = resolveStateSetInput(args.input);\n if (input === undefined) return Promise.resolve(invalidStateSetInputResult());\n\n try {\n const result = stateAdapter.set(input.path, input.value);\n return Promise.resolve(\n result.ok\n ? { data: { path: input.path, value: input.value }, ok: true }\n : {\n diagnostics: [\n {\n code: result.error.code,\n message: result.error.message,\n severity: 'error',\n },\n ],\n ok: false,\n },\n );\n } catch (error) {\n return Promise.resolve(stateAdapterSetErrorResult(error));\n }\n}\n\nasync function executeApplicationCapabilityAsync(\n args: RuntimeCapabilityExecutionArgs,\n capabilityExecutor: RuntimeCapabilityExecutor | undefined,\n): Promise<RuntimeCapabilityExecutionResult> {\n if (capabilityExecutor !== undefined) return capabilityExecutor(args);\n return {\n diagnostics: [\n {\n code: 'missing-operation',\n message: `Capability '${args.capability}' has no configured executor.`,\n severity: 'error',\n },\n ],\n ok: false,\n };\n}\n\nfunction resolveStateSetInput(\n input: RuntimeCapabilityExecutionArgs['input'],\n): { readonly path: StatePath; readonly value: StateValue } | undefined {\n if (!isRecord(input) || !('value' in input)) return undefined;\n const { path, value } = input;\n if (!isStatePath(path) || !isStateValue(value)) return undefined;\n return { path, value };\n}\n\nfunction isStatePath(value: unknown): value is StatePath {\n return (\n (typeof value === 'string' && value.trim().length > 0) ||\n (Array.isArray(value) &&\n value.length > 0 &&\n value.every((part) => typeof part === 'string' && part.trim().length > 0))\n );\n}\n\nfunction isStateValue(value: unknown): value is StateValue {\n if (value === null || typeof value === 'boolean' || typeof value === 'string') return true;\n if (typeof value === 'number') return Number.isFinite(value);\n if (Array.isArray(value)) return value.every(isStateValue);\n return isRecord(value) && Object.values(value).every(isStateValue);\n}\n\n/*** Converts thrown adapter failures into capability diagnostics at the public Runtime boundary. */\nfunction stateAdapterSetErrorResult(error: unknown): RuntimeCapabilityExecutionResult {\n return {\n diagnostics: [\n {\n code: 'state-adapter-error',\n message: error instanceof Error ? error.message : 'StateAdapter.set failed.',\n severity: 'error',\n },\n ],\n ok: false,\n };\n}\n\nfunction missingStateAdapterResult(): RuntimeCapabilityExecutionResult {\n return {\n diagnostics: [\n {\n code: 'missing-adapter',\n message: \"Capability 'state.set' requires a configured StateAdapter.\",\n severity: 'error',\n },\n ],\n ok: false,\n };\n}\n\nfunction invalidStateSetInputResult(): RuntimeCapabilityExecutionResult {\n return {\n diagnostics: [\n {\n code: 'invalid-input',\n message: \"Capability 'state.set' requires a non-empty path and serializable value.\",\n severity: 'error',\n },\n ],\n ok: false,\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimeStateAdapter.d.ts","sourceRoot":"","sources":["../src/runtimeStateAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAMZ,UAAU,EACX,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"runtimeStateAdapter.d.ts","sourceRoot":"","sources":["../src/runtimeStateAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAMZ,UAAU,EACX,MAAM,sBAAsB,CAAC;AAS9B,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;CAC9D;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,gCAAqC,GAC7C,YAAY,CAmFd"}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
export function createRuntimeMemoryStateAdapter(options = {}) {
|
|
2
2
|
let rootState = { ...(options.initialState ?? {}) };
|
|
3
3
|
const listeners = new Map();
|
|
4
|
-
const emit = (path
|
|
4
|
+
const emit = (path) => {
|
|
5
5
|
const pathResult = normalizeStatePath(path);
|
|
6
6
|
if (!pathResult.ok)
|
|
7
7
|
return;
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
listener
|
|
8
|
+
for (const entry of listeners.values()) {
|
|
9
|
+
if (!areStatePathsRelated(pathResult.parts, entry.parts))
|
|
10
|
+
continue;
|
|
11
|
+
const value = readStatePath(rootState, entry.parts);
|
|
12
|
+
for (const listener of entry.listeners) {
|
|
13
|
+
listener(value);
|
|
14
|
+
}
|
|
13
15
|
}
|
|
14
16
|
};
|
|
15
17
|
return {
|
|
@@ -32,7 +34,7 @@ export function createRuntimeMemoryStateAdapter(options = {}) {
|
|
|
32
34
|
if (!nextStateResult.ok)
|
|
33
35
|
return nextStateResult;
|
|
34
36
|
rootState = nextStateResult.data;
|
|
35
|
-
emit(path
|
|
37
|
+
emit(path);
|
|
36
38
|
return { ok: true };
|
|
37
39
|
},
|
|
38
40
|
subscribe(path, listener) {
|
|
@@ -40,16 +42,19 @@ export function createRuntimeMemoryStateAdapter(options = {}) {
|
|
|
40
42
|
if (!pathResult.ok)
|
|
41
43
|
return pathResult;
|
|
42
44
|
const key = pathPartsToKey(pathResult.parts);
|
|
43
|
-
const
|
|
45
|
+
const entry = listeners.get(key) ?? {
|
|
46
|
+
listeners: new Set(),
|
|
47
|
+
parts: pathResult.parts,
|
|
48
|
+
};
|
|
44
49
|
const wrappedListener = (value) => {
|
|
45
50
|
listener({ path, value: value });
|
|
46
51
|
};
|
|
47
|
-
|
|
48
|
-
listeners.set(key,
|
|
52
|
+
entry.listeners.add(wrappedListener);
|
|
53
|
+
listeners.set(key, entry);
|
|
49
54
|
return createStateDataResult({
|
|
50
55
|
unsubscribe() {
|
|
51
|
-
|
|
52
|
-
if (
|
|
56
|
+
entry.listeners.delete(wrappedListener);
|
|
57
|
+
if (entry.listeners.size === 0) {
|
|
53
58
|
listeners.delete(key);
|
|
54
59
|
}
|
|
55
60
|
},
|
|
@@ -63,7 +68,7 @@ export function createRuntimeMemoryStateAdapter(options = {}) {
|
|
|
63
68
|
if (!nextStateResult.ok)
|
|
64
69
|
return nextStateResult;
|
|
65
70
|
rootState = nextStateResult.data;
|
|
66
|
-
emit(path
|
|
71
|
+
emit(path);
|
|
67
72
|
return { ok: true };
|
|
68
73
|
},
|
|
69
74
|
};
|
|
@@ -82,6 +87,13 @@ function normalizeStatePath(path) {
|
|
|
82
87
|
function pathPartsToKey(parts) {
|
|
83
88
|
return parts.join('.');
|
|
84
89
|
}
|
|
90
|
+
/*** Determines whether a state mutation changes an ancestor, descendant, or exact subscription. */
|
|
91
|
+
function areStatePathsRelated(changedParts, subscribedParts) {
|
|
92
|
+
const sharedLength = Math.min(changedParts.length, subscribedParts.length);
|
|
93
|
+
return changedParts
|
|
94
|
+
.slice(0, sharedLength)
|
|
95
|
+
.every((part, index) => part === subscribedParts[index]);
|
|
96
|
+
}
|
|
85
97
|
function readStatePath(source, parts) {
|
|
86
98
|
let currentValue = source;
|
|
87
99
|
for (const part of parts) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimeStateAdapter.js","sourceRoot":"","sources":["../src/runtimeStateAdapter.ts"],"names":[],"mappings":"AAiBA,MAAM,UAAU,+BAA+B,CAC7C,UAA4C,EAAE;IAE9C,IAAI,SAAS,GAAuB,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,CAAC;IACxE,MAAM,SAAS,GAAG,IAAI,GAAG,EAA4B,CAAC;IAEtD,MAAM,IAAI,GAAG,CAAC,IAAe,EAAE,KAA6B,EAAE,EAAE;QAC9D,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,UAAU,CAAC,EAAE;YAAE,OAAO;QAE3B,MAAM,gBAAgB,GAAG,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QACzE,IAAI,gBAAgB,KAAK,SAAS;YAAE,OAAO;QAE3C,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;YACxC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,YAAY,EAAE;YACZ,aAAa,EAAE,IAAI;YACnB,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,KAAK;SACnB;QACD,GAAG,CAAyC,IAAe;YACzD,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,UAAU,CAAC,EAAE;gBAAE,OAAO,UAAU,CAAC;YAEtC,OAAO,qBAAqB,CAC1B,aAAa,CAAC,SAAS,EAAE,UAAU,CAAC,KAAK,CAAuB,CACjE,CAAC;QACJ,CAAC;QACD,GAAG,CAAyC,IAAe,EAAE,KAAa;YACxE,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,UAAU,CAAC,EAAE;gBAAE,OAAO,UAAU,CAAC;YAEtC,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACzE,IAAI,CAAC,eAAe,CAAC,EAAE;gBAAE,OAAO,eAAe,CAAC;YAEhD,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC;YACjC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAClB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;QACD,SAAS,CACP,IAAe,EACf,QAA+B;YAE/B,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,UAAU,CAAC,EAAE;gBAAE,OAAO,UAAU,CAAC;YAEtC,MAAM,GAAG,GAAG,cAAc,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,gBAAgB,GACpB,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,EAA2C,CAAC;YAC3E,MAAM,eAAe,GAAG,CAAC,KAA6B,EAAE,EAAE;gBACxD,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAA2B,EAAE,CAAC,CAAC;YACzD,CAAC,CAAC;YAEF,gBAAgB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YACtC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;YAErC,OAAO,qBAAqB,CAAC;gBAC3B,WAAW;oBACT,gBAAgB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;oBACzC,IAAI,gBAAgB,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;wBAChC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBACxB,CAAC;gBACH,CAAC;aACF,CAAC,CAAC;QACL,CAAC;QACD,MAAM,CAAC,IAAe;YACpB,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,UAAU,CAAC,EAAE;gBAAE,OAAO,UAAU,CAAC;YAEtC,MAAM,eAAe,GAAG,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;YACrE,IAAI,CAAC,eAAe,CAAC,EAAE;gBAAE,OAAO,eAAe,CAAC;YAEhD,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC;YACjC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACtB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC;AAcD,SAAS,kBAAkB,CAAC,IAAe;IACzC,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEpE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,gBAAgB,CAAC,cAAc,EAAE,+CAA+C,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR,KAAK,EAAE,UAAU;KAClB,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAwB;IAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,aAAa,CACpB,MAA0B,EAC1B,KAAwB;IAExB,IAAI,YAAY,GAA2B,MAAM,CAAC;IAElD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;YACjC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAS,YAAY,CACnB,MAA0B,EAC1B,KAAwB,EACxB,KAAiB;IAEjB,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC;IAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,gBAAgB,CAAC,cAAc,EAAE,+CAA+C,CAAC,CAAC;IAC3F,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,qBAAqB,CAAC;YAC3B,GAAG,MAAM;YACT,CAAC,IAAI,CAAC,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,gBAAgB,CACrB,eAAe,EACf,0DAA0D,IAAI,IAAI,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACrD,IAAI,CAAC,WAAW,CAAC,EAAE;QAAE,OAAO,WAAW,CAAC;IAExC,OAAO,qBAAqB,CAAC;QAC3B,GAAG,MAAM;QACT,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,IAAI;KACzB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CACtB,MAA0B,EAC1B,KAAwB;IAExB,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC;IAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,gBAAgB,CAAC,cAAc,EAAE,+CAA+C,CAAC,CAAC;IAC3F,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,SAAS,GAAuB,EAAE,CAAC;QACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACjB,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACzB,CAAC;QACH,CAAC;QAED,OAAO,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,gBAAgB,CACrB,eAAe,EACf,6DAA6D,IAAI,IAAI,CACtE,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,WAAW,CAAC,EAAE;QAAE,OAAO,WAAW,CAAC;IAExC,OAAO,qBAAqB,CAAC;QAC3B,GAAG,MAAM;QACT,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,IAAI;KACzB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,KAA6B;IAClD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,OAAe;IACrD,MAAM,KAAK,GAAsB,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACnD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,qBAAqB,CAAS,IAAY;IACjD,MAAM,MAAM,GAAG;QACb,EAAE,EAAE,IAAI;QACR,IAAI;KACL,CAAC;IAEF,OAAO,MAA6B,CAAC;AACvC,CAAC","sourcesContent":["import type {\n StateAdapter,\n StateAdapterError,\n StateListener,\n StatePath,\n StateResult,\n StateSubscription,\n StateValue,\n} from '@ankhorage/contracts';\n\ntype MutableStateRecord = Record<string, StateValue>;\ntype StateListenerSet = Set<(value: StateValue | undefined) => void>;\n\nexport interface RuntimeMemoryStateAdapterOptions {\n readonly initialState?: Readonly<Record<string, StateValue>>;\n}\n\nexport function createRuntimeMemoryStateAdapter(\n options: RuntimeMemoryStateAdapterOptions = {},\n): StateAdapter {\n let rootState: MutableStateRecord = { ...(options.initialState ?? {}) };\n const listeners = new Map<string, StateListenerSet>();\n\n const emit = (path: StatePath, value: StateValue | undefined) => {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return;\n\n const listenersForPath = listeners.get(pathPartsToKey(pathResult.parts));\n if (listenersForPath === undefined) return;\n\n for (const listener of listenersForPath) {\n listener(value);\n }\n };\n\n return {\n capabilities: {\n subscriptions: true,\n computed: false,\n persistence: false,\n },\n get<TValue extends StateValue = StateValue>(path: StatePath): StateResult<TValue | undefined> {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return pathResult;\n\n return createStateDataResult(\n readStatePath(rootState, pathResult.parts) as TValue | undefined,\n );\n },\n set<TValue extends StateValue = StateValue>(path: StatePath, value: TValue): StateResult {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return pathResult;\n\n const nextStateResult = setStatePath(rootState, pathResult.parts, value);\n if (!nextStateResult.ok) return nextStateResult;\n\n rootState = nextStateResult.data;\n emit(path, value);\n return { ok: true };\n },\n subscribe<TValue extends StateValue = StateValue>(\n path: StatePath,\n listener: StateListener<TValue>,\n ): StateResult<StateSubscription> {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return pathResult;\n\n const key = pathPartsToKey(pathResult.parts);\n const listenersForPath =\n listeners.get(key) ?? new Set<(value: StateValue | undefined) => void>();\n const wrappedListener = (value: StateValue | undefined) => {\n listener({ path, value: value as TValue | undefined });\n };\n\n listenersForPath.add(wrappedListener);\n listeners.set(key, listenersForPath);\n\n return createStateDataResult({\n unsubscribe() {\n listenersForPath.delete(wrappedListener);\n if (listenersForPath.size === 0) {\n listeners.delete(key);\n }\n },\n });\n },\n delete(path: StatePath): StateResult {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return pathResult;\n\n const nextStateResult = deleteStatePath(rootState, pathResult.parts);\n if (!nextStateResult.ok) return nextStateResult;\n\n rootState = nextStateResult.data;\n emit(path, undefined);\n return { ok: true };\n },\n };\n}\n\ninterface ResolvedStatePath {\n readonly ok: true;\n readonly parts: readonly string[];\n}\n\ninterface StatePathError {\n readonly ok: false;\n readonly error: StateAdapterError;\n}\n\ntype StatePathResult = ResolvedStatePath | StatePathError;\n\nfunction normalizeStatePath(path: StatePath): StatePathResult {\n const parts = typeof path === 'string' ? path.split('.') : [...path];\n const normalized = parts.map((part) => part.trim()).filter(Boolean);\n\n if (normalized.length === 0) {\n return createStateError('invalid_path', 'State path must contain at least one segment.');\n }\n\n return {\n ok: true,\n parts: normalized,\n };\n}\n\nfunction pathPartsToKey(parts: readonly string[]): string {\n return parts.join('.');\n}\n\nfunction readStatePath(\n source: MutableStateRecord,\n parts: readonly string[],\n): StateValue | undefined {\n let currentValue: StateValue | undefined = source;\n\n for (const part of parts) {\n if (!isStateRecord(currentValue)) {\n return undefined;\n }\n\n currentValue = currentValue[part];\n }\n\n return currentValue;\n}\n\nfunction setStatePath(\n source: MutableStateRecord,\n parts: readonly string[],\n value: StateValue,\n): StateResult<MutableStateRecord> {\n const [head, ...tail] = parts;\n if (head === undefined) {\n return createStateError('invalid_path', 'State path must contain at least one segment.');\n }\n\n if (tail.length === 0) {\n return createStateDataResult({\n ...source,\n [head]: value,\n });\n }\n\n const existing = source[head];\n const child = existing === undefined ? {} : existing;\n if (!isStateRecord(child)) {\n return createStateError(\n 'path_conflict',\n `Cannot set nested state below non-object path segment \"${head}\".`,\n );\n }\n\n const childResult = setStatePath(child, tail, value);\n if (!childResult.ok) return childResult;\n\n return createStateDataResult({\n ...source,\n [head]: childResult.data,\n });\n}\n\nfunction deleteStatePath(\n source: MutableStateRecord,\n parts: readonly string[],\n): StateResult<MutableStateRecord> {\n const [head, ...tail] = parts;\n if (head === undefined) {\n return createStateError('invalid_path', 'State path must contain at least one segment.');\n }\n\n if (tail.length === 0) {\n const nextState: MutableStateRecord = {};\n for (const [key, value] of Object.entries(source)) {\n if (key !== head) {\n nextState[key] = value;\n }\n }\n\n return createStateDataResult(nextState);\n }\n\n const existing = source[head];\n if (existing === undefined) {\n return createStateDataResult(source);\n }\n\n if (!isStateRecord(existing)) {\n return createStateError(\n 'path_conflict',\n `Cannot delete nested state below non-object path segment \"${head}\".`,\n );\n }\n\n const childResult = deleteStatePath(existing, tail);\n if (!childResult.ok) return childResult;\n\n return createStateDataResult({\n ...source,\n [head]: childResult.data,\n });\n}\n\nfunction isStateRecord(value: StateValue | undefined): value is MutableStateRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction createStateError(code: string, message: string): StatePathError {\n const error: StateAdapterError = { code, message };\n return { ok: false, error };\n}\n\nfunction createStateDataResult<TValue>(data: TValue): StateResult<TValue> {\n const result = {\n ok: true,\n data,\n };\n\n return result as StateResult<TValue>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"runtimeStateAdapter.js","sourceRoot":"","sources":["../src/runtimeStateAdapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n StateAdapter,\n StateAdapterError,\n StateListener,\n StatePath,\n StateResult,\n StateSubscription,\n StateValue,\n} from '@ankhorage/contracts';\n\ntype MutableStateRecord = Record<string, StateValue>;\ntype StateListenerSet = Set<(value: StateValue | undefined) => void>;\ninterface StateListenerEntry {\n readonly listeners: StateListenerSet;\n readonly parts: readonly string[];\n}\n\nexport interface RuntimeMemoryStateAdapterOptions {\n readonly initialState?: Readonly<Record<string, StateValue>>;\n}\n\nexport function createRuntimeMemoryStateAdapter(\n options: RuntimeMemoryStateAdapterOptions = {},\n): StateAdapter {\n let rootState: MutableStateRecord = { ...(options.initialState ?? {}) };\n const listeners = new Map<string, StateListenerEntry>();\n\n const emit = (path: StatePath) => {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return;\n\n for (const entry of listeners.values()) {\n if (!areStatePathsRelated(pathResult.parts, entry.parts)) continue;\n\n const value = readStatePath(rootState, entry.parts);\n for (const listener of entry.listeners) {\n listener(value);\n }\n }\n };\n\n return {\n capabilities: {\n subscriptions: true,\n computed: false,\n persistence: false,\n },\n get<TValue extends StateValue = StateValue>(path: StatePath): StateResult<TValue | undefined> {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return pathResult;\n\n return createStateDataResult(\n readStatePath(rootState, pathResult.parts) as TValue | undefined,\n );\n },\n set<TValue extends StateValue = StateValue>(path: StatePath, value: TValue): StateResult {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return pathResult;\n\n const nextStateResult = setStatePath(rootState, pathResult.parts, value);\n if (!nextStateResult.ok) return nextStateResult;\n\n rootState = nextStateResult.data;\n emit(path);\n return { ok: true };\n },\n subscribe<TValue extends StateValue = StateValue>(\n path: StatePath,\n listener: StateListener<TValue>,\n ): StateResult<StateSubscription> {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return pathResult;\n\n const key = pathPartsToKey(pathResult.parts);\n const entry = listeners.get(key) ?? {\n listeners: new Set<(value: StateValue | undefined) => void>(),\n parts: pathResult.parts,\n };\n const wrappedListener = (value: StateValue | undefined) => {\n listener({ path, value: value as TValue | undefined });\n };\n\n entry.listeners.add(wrappedListener);\n listeners.set(key, entry);\n\n return createStateDataResult({\n unsubscribe() {\n entry.listeners.delete(wrappedListener);\n if (entry.listeners.size === 0) {\n listeners.delete(key);\n }\n },\n });\n },\n delete(path: StatePath): StateResult {\n const pathResult = normalizeStatePath(path);\n if (!pathResult.ok) return pathResult;\n\n const nextStateResult = deleteStatePath(rootState, pathResult.parts);\n if (!nextStateResult.ok) return nextStateResult;\n\n rootState = nextStateResult.data;\n emit(path);\n return { ok: true };\n },\n };\n}\n\ninterface ResolvedStatePath {\n readonly ok: true;\n readonly parts: readonly string[];\n}\n\ninterface StatePathError {\n readonly ok: false;\n readonly error: StateAdapterError;\n}\n\ntype StatePathResult = ResolvedStatePath | StatePathError;\n\nfunction normalizeStatePath(path: StatePath): StatePathResult {\n const parts = typeof path === 'string' ? path.split('.') : [...path];\n const normalized = parts.map((part) => part.trim()).filter(Boolean);\n\n if (normalized.length === 0) {\n return createStateError('invalid_path', 'State path must contain at least one segment.');\n }\n\n return {\n ok: true,\n parts: normalized,\n };\n}\n\nfunction pathPartsToKey(parts: readonly string[]): string {\n return parts.join('.');\n}\n\n/*** Determines whether a state mutation changes an ancestor, descendant, or exact subscription. */\nfunction areStatePathsRelated(\n changedParts: readonly string[],\n subscribedParts: readonly string[],\n): boolean {\n const sharedLength = Math.min(changedParts.length, subscribedParts.length);\n return changedParts\n .slice(0, sharedLength)\n .every((part, index) => part === subscribedParts[index]);\n}\n\nfunction readStatePath(\n source: MutableStateRecord,\n parts: readonly string[],\n): StateValue | undefined {\n let currentValue: StateValue | undefined = source;\n\n for (const part of parts) {\n if (!isStateRecord(currentValue)) {\n return undefined;\n }\n\n currentValue = currentValue[part];\n }\n\n return currentValue;\n}\n\nfunction setStatePath(\n source: MutableStateRecord,\n parts: readonly string[],\n value: StateValue,\n): StateResult<MutableStateRecord> {\n const [head, ...tail] = parts;\n if (head === undefined) {\n return createStateError('invalid_path', 'State path must contain at least one segment.');\n }\n\n if (tail.length === 0) {\n return createStateDataResult({\n ...source,\n [head]: value,\n });\n }\n\n const existing = source[head];\n const child = existing === undefined ? {} : existing;\n if (!isStateRecord(child)) {\n return createStateError(\n 'path_conflict',\n `Cannot set nested state below non-object path segment \"${head}\".`,\n );\n }\n\n const childResult = setStatePath(child, tail, value);\n if (!childResult.ok) return childResult;\n\n return createStateDataResult({\n ...source,\n [head]: childResult.data,\n });\n}\n\nfunction deleteStatePath(\n source: MutableStateRecord,\n parts: readonly string[],\n): StateResult<MutableStateRecord> {\n const [head, ...tail] = parts;\n if (head === undefined) {\n return createStateError('invalid_path', 'State path must contain at least one segment.');\n }\n\n if (tail.length === 0) {\n const nextState: MutableStateRecord = {};\n for (const [key, value] of Object.entries(source)) {\n if (key !== head) {\n nextState[key] = value;\n }\n }\n\n return createStateDataResult(nextState);\n }\n\n const existing = source[head];\n if (existing === undefined) {\n return createStateDataResult(source);\n }\n\n if (!isStateRecord(existing)) {\n return createStateError(\n 'path_conflict',\n `Cannot delete nested state below non-object path segment \"${head}\".`,\n );\n }\n\n const childResult = deleteStatePath(existing, tail);\n if (!childResult.ok) return childResult;\n\n return createStateDataResult({\n ...source,\n [head]: childResult.data,\n });\n}\n\nfunction isStateRecord(value: StateValue | undefined): value is MutableStateRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction createStateError(code: string, message: string): StatePathError {\n const error: StateAdapterError = { code, message };\n return { ok: false, error };\n}\n\nfunction createStateDataResult<TValue>(data: TValue): StateResult<TValue> {\n const result = {\n ok: true,\n data,\n };\n\n return result as StateResult<TValue>;\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BindingExpression, ComponentDataBindingRegistry, StateAdapter } from '@ankhorage/contracts';
|
|
2
|
+
/*** Re-renders a Runtime node when one of its state-backed presentation bindings changes. */
|
|
3
|
+
export declare function useRuntimeStateBindings(args: {
|
|
4
|
+
readonly dataBindings?: ComponentDataBindingRegistry;
|
|
5
|
+
readonly nodeId: string;
|
|
6
|
+
readonly repeatSource?: BindingExpression;
|
|
7
|
+
readonly stateAdapter?: StateAdapter;
|
|
8
|
+
}): void;
|
|
9
|
+
//# sourceMappingURL=useRuntimeStateBindings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRuntimeStateBindings.d.ts","sourceRoot":"","sources":["../src/useRuntimeStateBindings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,4BAA4B,EAC5B,YAAY,EACb,MAAM,sBAAsB,CAAC;AAG9B,6FAA6F;AAC7F,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,QAAQ,CAAC,YAAY,CAAC,EAAE,4BAA4B,CAAC;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;CACtC,GAAG,IAAI,CAsBP"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/*** Re-renders a Runtime node when one of its state-backed presentation bindings changes. */
|
|
3
|
+
export function useRuntimeStateBindings(args) {
|
|
4
|
+
const { dataBindings, nodeId, repeatSource, stateAdapter } = args;
|
|
5
|
+
const paths = React.useMemo(() => collectStateBindingPaths(findDataBindingProps(dataBindings, nodeId), repeatSource), [dataBindings, nodeId, repeatSource]);
|
|
6
|
+
const [, setVersion] = React.useState(0);
|
|
7
|
+
React.useEffect(() => {
|
|
8
|
+
if (stateAdapter === undefined || paths.length === 0)
|
|
9
|
+
return undefined;
|
|
10
|
+
const subscriptions = paths.flatMap((path) => {
|
|
11
|
+
const result = stateAdapter.subscribe(path, () => {
|
|
12
|
+
setVersion((version) => version + 1);
|
|
13
|
+
});
|
|
14
|
+
return result.ok ? [result.data] : [];
|
|
15
|
+
});
|
|
16
|
+
return () => {
|
|
17
|
+
for (const subscription of subscriptions)
|
|
18
|
+
void subscription.unsubscribe();
|
|
19
|
+
};
|
|
20
|
+
}, [paths, stateAdapter]);
|
|
21
|
+
}
|
|
22
|
+
function findDataBindingProps(dataBindings, nodeId) {
|
|
23
|
+
return Object.values(dataBindings ?? {}).find((binding) => binding.componentId === nodeId)?.props;
|
|
24
|
+
}
|
|
25
|
+
function collectStateBindingPaths(props, repeatSource) {
|
|
26
|
+
const paths = [
|
|
27
|
+
...Object.values(props ?? {}).flatMap((binding) => collectStateExpressionPaths(binding.value)),
|
|
28
|
+
...(repeatSource ? collectStateExpressionPaths(repeatSource) : []),
|
|
29
|
+
];
|
|
30
|
+
return [...new Set(paths)].sort();
|
|
31
|
+
}
|
|
32
|
+
function collectStateExpressionPaths(expression) {
|
|
33
|
+
if ('capability' in expression)
|
|
34
|
+
return expression.capability.startsWith('state.')
|
|
35
|
+
? [expression.capability.slice('state.'.length)]
|
|
36
|
+
: [];
|
|
37
|
+
if (expression.kind === 'literal')
|
|
38
|
+
return [];
|
|
39
|
+
if (expression.kind === 'array')
|
|
40
|
+
return expression.items.flatMap(collectStateExpressionPaths);
|
|
41
|
+
if (expression.kind === 'object')
|
|
42
|
+
return Object.values(expression.fields).flatMap(collectStateExpressionPaths);
|
|
43
|
+
if (expression.kind === 'transform')
|
|
44
|
+
return collectStateExpressionPaths(expression.value);
|
|
45
|
+
return [
|
|
46
|
+
...collectStateExpressionPaths(expression.value),
|
|
47
|
+
...collectStateExpressionPaths(expression.fallback),
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=useRuntimeStateBindings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRuntimeStateBindings.js","sourceRoot":"","sources":["../src/useRuntimeStateBindings.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n BindingExpression,\n ComponentDataBindingRegistry,\n StateAdapter,\n} from '@ankhorage/contracts';\nimport React from 'react';\n\n/*** Re-renders a Runtime node when one of its state-backed presentation bindings changes. */\nexport function useRuntimeStateBindings(args: {\n readonly dataBindings?: ComponentDataBindingRegistry;\n readonly nodeId: string;\n readonly repeatSource?: BindingExpression;\n readonly stateAdapter?: StateAdapter;\n}): void {\n const { dataBindings, nodeId, repeatSource, stateAdapter } = args;\n const paths = React.useMemo(\n () => collectStateBindingPaths(findDataBindingProps(dataBindings, nodeId), repeatSource),\n [dataBindings, nodeId, repeatSource],\n );\n const [, setVersion] = React.useState(0);\n\n React.useEffect(() => {\n if (stateAdapter === undefined || paths.length === 0) return undefined;\n\n const subscriptions = paths.flatMap((path) => {\n const result = stateAdapter.subscribe(path, () => {\n setVersion((version) => version + 1);\n });\n return result.ok ? [result.data] : [];\n });\n\n return () => {\n for (const subscription of subscriptions) void subscription.unsubscribe();\n };\n }, [paths, stateAdapter]);\n}\n\nfunction findDataBindingProps(\n dataBindings: ComponentDataBindingRegistry | undefined,\n nodeId: string,\n): ComponentDataBindingRegistry[string]['props'] | undefined {\n return Object.values(dataBindings ?? {}).find((binding) => binding.componentId === nodeId)?.props;\n}\n\nfunction collectStateBindingPaths(\n props: ComponentDataBindingRegistry[string]['props'] | undefined,\n repeatSource: BindingExpression | undefined,\n): readonly string[] {\n const paths = [\n ...Object.values(props ?? {}).flatMap((binding) => collectStateExpressionPaths(binding.value)),\n ...(repeatSource ? collectStateExpressionPaths(repeatSource) : []),\n ];\n return [...new Set(paths)].sort();\n}\n\nfunction collectStateExpressionPaths(expression: BindingExpression): readonly string[] {\n if ('capability' in expression)\n return expression.capability.startsWith('state.')\n ? [expression.capability.slice('state.'.length)]\n : [];\n if (expression.kind === 'literal') return [];\n if (expression.kind === 'array') return expression.items.flatMap(collectStateExpressionPaths);\n if (expression.kind === 'object')\n return Object.values(expression.fields).flatMap(collectStateExpressionPaths);\n if (expression.kind === 'transform') return collectStateExpressionPaths(expression.value);\n return [\n ...collectStateExpressionPaths(expression.value),\n ...collectStateExpressionPaths(expression.fallback),\n ];\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/runtime",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "Platform-neutral runtime renderer, contracts, and helpers for Ankhorage generated apps.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -101,6 +101,71 @@
|
|
|
101
101
|
},
|
|
102
102
|
"label": "Runtime bindings"
|
|
103
103
|
},
|
|
104
|
+
{
|
|
105
|
+
"id": "state.set",
|
|
106
|
+
"owner": "@ankhorage/runtime",
|
|
107
|
+
"access": [
|
|
108
|
+
"invoke",
|
|
109
|
+
"write"
|
|
110
|
+
],
|
|
111
|
+
"binding": {
|
|
112
|
+
"kind": "state",
|
|
113
|
+
"bindableAs": [
|
|
114
|
+
"target"
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
"label": "Set runtime state",
|
|
118
|
+
"input": {
|
|
119
|
+
"schema": {
|
|
120
|
+
"type": "object",
|
|
121
|
+
"required": [
|
|
122
|
+
"path",
|
|
123
|
+
"value"
|
|
124
|
+
],
|
|
125
|
+
"properties": {
|
|
126
|
+
"path": {
|
|
127
|
+
"anyOf": [
|
|
128
|
+
{
|
|
129
|
+
"type": "string"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"type": "array",
|
|
133
|
+
"items": {
|
|
134
|
+
"type": "string"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
"value": {}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"output": {
|
|
144
|
+
"schema": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"required": [
|
|
147
|
+
"path",
|
|
148
|
+
"value"
|
|
149
|
+
],
|
|
150
|
+
"properties": {
|
|
151
|
+
"path": {
|
|
152
|
+
"anyOf": [
|
|
153
|
+
{
|
|
154
|
+
"type": "string"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"type": "array",
|
|
158
|
+
"items": {
|
|
159
|
+
"type": "string"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
"value": {}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
104
169
|
{
|
|
105
170
|
"id": "runtime.eventOperation",
|
|
106
171
|
"owner": "@ankhorage/runtime",
|
|
@@ -198,7 +263,7 @@
|
|
|
198
263
|
"@ankhorage/capability": "^0.2.2",
|
|
199
264
|
"@ankhorage/contracts": "^26.0.1",
|
|
200
265
|
"@ankhorage/data-sources": "^2.1.2",
|
|
201
|
-
"@ankhorage/utility": "^1.
|
|
266
|
+
"@ankhorage/utility": "^1.10.0"
|
|
202
267
|
},
|
|
203
268
|
"peerDependencies": {
|
|
204
269
|
"react": ">=19.2.0 <20",
|
|
@@ -211,14 +276,16 @@
|
|
|
211
276
|
}
|
|
212
277
|
},
|
|
213
278
|
"devDependencies": {
|
|
214
|
-
"@ankhorage/devtools": "^2.3.
|
|
279
|
+
"@ankhorage/devtools": "^2.3.23",
|
|
215
280
|
"@ankhorage/paradox": "^0.3.5",
|
|
216
281
|
"@types/bun": "^1.4.2",
|
|
217
282
|
"@types/node": "^26.6.4",
|
|
218
283
|
"@types/react": "^19.3.0",
|
|
219
284
|
"@types/react-dom": "^19.3.0",
|
|
285
|
+
"@types/react-test-renderer": "^19.1.0",
|
|
220
286
|
"react": "19.3.0",
|
|
221
287
|
"react-dom": "19.3.0",
|
|
288
|
+
"react-test-renderer": "19.3.0",
|
|
222
289
|
"react-native": "0.87.1",
|
|
223
290
|
"react-native-web": "~0.21.3",
|
|
224
291
|
"typescript": "~6.0.3"
|
package/paradox/badges/npm.svg
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="90" height="20" role="img" aria-label="npm: v5.0
|
|
2
|
-
<title>npm: v5.0
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="90" height="20" role="img" aria-label="npm: v5.1.0">
|
|
2
|
+
<title>npm: v5.1.0</title>
|
|
3
3
|
<rect width="38" height="20" fill="#374151"/>
|
|
4
4
|
<rect x="38" width="52" height="20" fill="#cb3837"/>
|
|
5
5
|
<text x="19" y="14" fill="#ffffff" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="11" text-anchor="middle">npm</text>
|
|
6
|
-
<text x="64" y="14" fill="#ffffff" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="11" text-anchor="middle">v5.0
|
|
6
|
+
<text x="64" y="14" fill="#ffffff" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="11" text-anchor="middle">v5.1.0</text>
|
|
7
7
|
</svg>
|
package/paradox/components.md
CHANGED
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## ManifestContext
|
|
4
4
|
|
|
5
|
-
Source: `src/ManifestContext.tsx:
|
|
5
|
+
Source: `src/ManifestContext.tsx:13:14`
|
|
6
6
|
|
|
7
7
|
Export paths: `src/index.ts`
|
|
8
8
|
|
|
9
9
|
| Prop | Type | Required | Default | Description |
|
|
10
10
|
| --- | --- | --- | --- | --- |
|
|
11
11
|
| children | `ReactNode` | no | — | |
|
|
12
|
-
| value | `ManifestContextValue \| null` | yes | — | |
|
|
12
|
+
| value | `import("../../../src/ManifestContext").ManifestContextValue \| null` | yes | — | |
|
|
13
13
|
|
|
14
14
|
## ManifestProvider
|
|
15
15
|
|
|
16
|
-
Source: `src/ManifestContext.tsx:
|
|
16
|
+
Source: `src/ManifestContext.tsx:16:1`
|
|
17
|
+
|
|
18
|
+
Owns one configured state adapter for every Runtime screen in an application tree.
|
|
17
19
|
|
|
18
20
|
Export paths: `src/index.ts`
|
|
19
21
|
|
|
@@ -23,10 +25,11 @@ Export paths: `src/index.ts`
|
|
|
23
25
|
| children | `React.ReactNode \| undefined` | no | — | |
|
|
24
26
|
| manifest | `AppManifest` | yes | — | |
|
|
25
27
|
| onScreenChange | `(screenId: string) => void \| undefined` | no | — | |
|
|
28
|
+
| stateAdapter | `StateAdapter \| undefined` | no | — | |
|
|
26
29
|
|
|
27
30
|
## RuntimeRenderer
|
|
28
31
|
|
|
29
|
-
Source: `src/RuntimeRenderer.tsx:
|
|
32
|
+
Source: `src/RuntimeRenderer.tsx:74:1`
|
|
30
33
|
|
|
31
34
|
Export paths: `src/index.ts`
|
|
32
35
|
|
|
@@ -62,7 +65,7 @@ Export paths: `src/index.ts`
|
|
|
62
65
|
|
|
63
66
|
## RuntimeScreen
|
|
64
67
|
|
|
65
|
-
Source: `src/RuntimeScreen.tsx:
|
|
68
|
+
Source: `src/RuntimeScreen.tsx:20:1`
|
|
66
69
|
|
|
67
70
|
Export paths: `src/index.ts`
|
|
68
71
|
|
|
@@ -19,6 +19,7 @@ graph TD
|
|
|
19
19
|
module_src_index_ts["src/index.ts"]
|
|
20
20
|
module_src_ManifestContext_tsx["src/ManifestContext.tsx"]
|
|
21
21
|
package__ankhorage_runtime -.-> module_src_ManifestContext_tsx
|
|
22
|
+
module_src_ManifestContext_tsx --> module_src_runtimeStateAdapter_ts
|
|
22
23
|
module_src_react19Compatibility_test_tsx["src/react19Compatibility.test.tsx"]
|
|
23
24
|
package__ankhorage_runtime -.-> module_src_react19Compatibility_test_tsx
|
|
24
25
|
module_src_react19Compatibility_test_tsx --> module_src_ManifestContext_tsx
|
|
@@ -55,8 +56,11 @@ graph TD
|
|
|
55
56
|
package__ankhorage_runtime -.-> module_src_runtimeBindings_ts
|
|
56
57
|
module_src_runtimeCapabilityExecutor_test_ts["src/runtimeCapabilityExecutor.test.ts"]
|
|
57
58
|
package__ankhorage_runtime -.-> module_src_runtimeCapabilityExecutor_test_ts
|
|
59
|
+
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeActionRegistry_ts
|
|
58
60
|
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeCapabilityExecutor_ts
|
|
61
|
+
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeNodeProps_ts
|
|
59
62
|
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeScreenLoaders_ts
|
|
63
|
+
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeStateAdapter_ts
|
|
60
64
|
module_src_runtimeCapabilityExecutor_ts["src/runtimeCapabilityExecutor.ts"]
|
|
61
65
|
package__ankhorage_runtime -.-> module_src_runtimeCapabilityExecutor_ts
|
|
62
66
|
module_src_runtimeCapabilityExecutor_ts --> module_src_runtimeBindings_ts
|
|
@@ -107,6 +111,7 @@ graph TD
|
|
|
107
111
|
module_src_RuntimeRenderer_tsx --> module_src_runtimeRepeatDiagnostics_ts
|
|
108
112
|
module_src_RuntimeRenderer_tsx --> module_src_runtimeRepeatEmptyState_ts
|
|
109
113
|
module_src_RuntimeRenderer_tsx --> module_src_useRuntimeMediaProps_ts
|
|
114
|
+
module_src_RuntimeRenderer_tsx --> module_src_useRuntimeStateBindings_ts
|
|
110
115
|
module_src_RuntimeRendererConfig_tsx["src/RuntimeRendererConfig.tsx"]
|
|
111
116
|
package__ankhorage_runtime -.-> module_src_RuntimeRendererConfig_tsx
|
|
112
117
|
module_src_RuntimeRendererConfig_tsx --> module_src_registry_tsx
|
|
@@ -123,6 +128,7 @@ graph TD
|
|
|
123
128
|
package__ankhorage_runtime -.-> module_src_runtimeRepeatEmptyState_ts
|
|
124
129
|
module_src_RuntimeScreen_tsx["src/RuntimeScreen.tsx"]
|
|
125
130
|
package__ankhorage_runtime -.-> module_src_RuntimeScreen_tsx
|
|
131
|
+
module_src_RuntimeScreen_tsx --> module_src_ManifestContext_tsx
|
|
126
132
|
module_src_RuntimeScreen_tsx --> module_src_registry_tsx
|
|
127
133
|
module_src_RuntimeScreen_tsx --> module_src_runtimeApiCapabilities_ts
|
|
128
134
|
module_src_RuntimeScreen_tsx --> module_src_runtimeCapabilityExecutor_ts
|
|
@@ -138,9 +144,16 @@ graph TD
|
|
|
138
144
|
module_src_runtimeScreenLoaders_ts --> module_src_runtimeBindings_ts
|
|
139
145
|
module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"]
|
|
140
146
|
package__ankhorage_runtime -.-> module_src_runtimeStateAdapter_ts
|
|
147
|
+
module_src_runtimeStateReactivity_test_tsx["src/runtimeStateReactivity.test.tsx"]
|
|
148
|
+
package__ankhorage_runtime -.-> module_src_runtimeStateReactivity_test_tsx
|
|
149
|
+
module_src_runtimeStateReactivity_test_tsx --> module_src_registry_tsx
|
|
150
|
+
module_src_runtimeStateReactivity_test_tsx --> module_src_runtimeBindings_ts
|
|
151
|
+
module_src_runtimeStateReactivity_test_tsx --> module_src_runtimeStateAdapter_ts
|
|
141
152
|
module_src_useRuntimeMediaProps_ts["src/useRuntimeMediaProps.ts"]
|
|
142
153
|
package__ankhorage_runtime -.-> module_src_useRuntimeMediaProps_ts
|
|
143
154
|
module_src_useRuntimeMediaProps_ts --> module_src_runtimeMedia_ts
|
|
155
|
+
module_src_useRuntimeStateBindings_ts["src/useRuntimeStateBindings.ts"]
|
|
156
|
+
package__ankhorage_runtime -.-> module_src_useRuntimeStateBindings_ts
|
|
144
157
|
module_tests_reactNativeWebCompatibility_fixture_tsx["tests/reactNativeWebCompatibility.fixture.tsx"]
|
|
145
158
|
package__ankhorage_runtime -.-> module_tests_reactNativeWebCompatibility_fixture_tsx
|
|
146
159
|
module_tests_reactNativeWebCompatibility_fixture_tsx --> module_src_RuntimeRenderer_tsx
|
|
@@ -39,7 +39,9 @@ graph LR
|
|
|
39
39
|
module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"]
|
|
40
40
|
module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"]
|
|
41
41
|
module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"]
|
|
42
|
+
module_src_runtimeStateReactivity_test_tsx["src/runtimeStateReactivity.test.tsx"]
|
|
42
43
|
module_src_useRuntimeMediaProps_ts["src/useRuntimeMediaProps.ts"]
|
|
44
|
+
module_src_useRuntimeStateBindings_ts["src/useRuntimeStateBindings.ts"]
|
|
43
45
|
module_tests_reactNativeWebCompatibility_fixture_tsx["tests/reactNativeWebCompatibility.fixture.tsx"]
|
|
44
46
|
module_tests_reactNativeWebCompatibility_test_ts["tests/reactNativeWebCompatibility.test.ts"]
|
|
45
47
|
module_tests_runtime_test_ts["tests/runtime.test.ts"]
|
|
@@ -39,12 +39,15 @@ graph LR
|
|
|
39
39
|
module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"]
|
|
40
40
|
module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"]
|
|
41
41
|
module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"]
|
|
42
|
+
module_src_runtimeStateReactivity_test_tsx["src/runtimeStateReactivity.test.tsx"]
|
|
42
43
|
module_src_useRuntimeMediaProps_ts["src/useRuntimeMediaProps.ts"]
|
|
44
|
+
module_src_useRuntimeStateBindings_ts["src/useRuntimeStateBindings.ts"]
|
|
43
45
|
module_tests_reactNativeWebCompatibility_fixture_tsx["tests/reactNativeWebCompatibility.fixture.tsx"]
|
|
44
46
|
module_tests_reactNativeWebCompatibility_test_ts["tests/reactNativeWebCompatibility.test.ts"]
|
|
45
47
|
module_tests_runtime_test_ts["tests/runtime.test.ts"]
|
|
46
48
|
module_src_capabilities_resolveRuntimeContextCapability_test_ts --> module_src_capabilities_resolveRuntimeContextCapability_ts
|
|
47
49
|
module_src_capabilities_resolveRuntimeContextCapability_ts --> module_src_capabilities_index_ts
|
|
50
|
+
module_src_ManifestContext_tsx --> module_src_runtimeStateAdapter_ts
|
|
48
51
|
module_src_react19Compatibility_test_tsx --> module_src_ManifestContext_tsx
|
|
49
52
|
module_src_react19Compatibility_test_tsx --> module_src_RuntimeRendererConfig_tsx
|
|
50
53
|
module_src_registry_test_ts --> module_src_registry_tsx
|
|
@@ -59,8 +62,11 @@ graph LR
|
|
|
59
62
|
module_src_runtimeBindings_contracts26_test_ts --> module_src_runtimeBindings_ts
|
|
60
63
|
module_src_runtimeBindings_contracts26_test_ts --> module_src_runtimeRepeat_ts
|
|
61
64
|
module_src_runtimeBindings_contracts26_test_ts --> module_src_runtimeScreenLoaders_ts
|
|
65
|
+
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeActionRegistry_ts
|
|
62
66
|
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeCapabilityExecutor_ts
|
|
67
|
+
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeNodeProps_ts
|
|
63
68
|
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeScreenLoaders_ts
|
|
69
|
+
module_src_runtimeCapabilityExecutor_test_ts --> module_src_runtimeStateAdapter_ts
|
|
64
70
|
module_src_runtimeCapabilityExecutor_ts --> module_src_runtimeBindings_ts
|
|
65
71
|
module_src_runtimeEventExecution_ts --> module_src_runtimeActionRegistry_ts
|
|
66
72
|
module_src_runtimeImageMedia_test_ts --> module_src_runtimeMedia_ts
|
|
@@ -85,12 +91,14 @@ graph LR
|
|
|
85
91
|
module_src_RuntimeRenderer_tsx --> module_src_runtimeRepeatDiagnostics_ts
|
|
86
92
|
module_src_RuntimeRenderer_tsx --> module_src_runtimeRepeatEmptyState_ts
|
|
87
93
|
module_src_RuntimeRenderer_tsx --> module_src_useRuntimeMediaProps_ts
|
|
94
|
+
module_src_RuntimeRenderer_tsx --> module_src_useRuntimeStateBindings_ts
|
|
88
95
|
module_src_RuntimeRendererConfig_tsx --> module_src_registry_tsx
|
|
89
96
|
module_src_RuntimeRendererConfig_tsx --> module_src_runtimeActionRegistry_ts
|
|
90
97
|
module_src_RuntimeRendererConfig_tsx --> module_src_runtimeBindings_ts
|
|
91
98
|
module_src_RuntimeRendererConfig_tsx --> module_src_runtimeEventOperationLifecycle_ts
|
|
92
99
|
module_src_RuntimeRendererConfig_tsx --> module_src_runtimeMedia_ts
|
|
93
100
|
module_src_runtimeRepeat_ts --> module_src_runtimeBindings_ts
|
|
101
|
+
module_src_RuntimeScreen_tsx --> module_src_ManifestContext_tsx
|
|
94
102
|
module_src_RuntimeScreen_tsx --> module_src_registry_tsx
|
|
95
103
|
module_src_RuntimeScreen_tsx --> module_src_runtimeApiCapabilities_ts
|
|
96
104
|
module_src_RuntimeScreen_tsx --> module_src_runtimeCapabilityExecutor_ts
|
|
@@ -100,6 +108,9 @@ graph LR
|
|
|
100
108
|
module_src_RuntimeScreen_tsx --> module_src_runtimeStateAdapter_ts
|
|
101
109
|
module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeScreenLoaders_ts
|
|
102
110
|
module_src_runtimeScreenLoaders_ts --> module_src_runtimeBindings_ts
|
|
111
|
+
module_src_runtimeStateReactivity_test_tsx --> module_src_registry_tsx
|
|
112
|
+
module_src_runtimeStateReactivity_test_tsx --> module_src_runtimeBindings_ts
|
|
113
|
+
module_src_runtimeStateReactivity_test_tsx --> module_src_runtimeStateAdapter_ts
|
|
103
114
|
module_src_useRuntimeMediaProps_ts --> module_src_runtimeMedia_ts
|
|
104
115
|
module_tests_reactNativeWebCompatibility_fixture_tsx --> module_src_RuntimeRenderer_tsx
|
|
105
116
|
module_tests_runtime_test_ts --> module_src_capabilities_index_ts
|