@ankhorage/runtime 0.1.0 → 0.2.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.
Files changed (117) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +20 -5
  3. package/dist/ManifestContext.d.ts +16 -0
  4. package/dist/ManifestContext.d.ts.map +1 -0
  5. package/dist/ManifestContext.js +26 -0
  6. package/dist/ManifestContext.js.map +1 -0
  7. package/dist/RuntimeRenderer.d.ts +24 -0
  8. package/dist/RuntimeRenderer.d.ts.map +1 -0
  9. package/dist/RuntimeRenderer.js +302 -0
  10. package/dist/RuntimeRenderer.js.map +1 -0
  11. package/dist/RuntimeRendererConfig.d.ts +54 -0
  12. package/dist/RuntimeRendererConfig.d.ts.map +1 -0
  13. package/dist/RuntimeRendererConfig.js +70 -0
  14. package/dist/RuntimeRendererConfig.js.map +1 -0
  15. package/dist/RuntimeScreen.d.ts +11 -0
  16. package/dist/RuntimeScreen.d.ts.map +1 -0
  17. package/dist/RuntimeScreen.js +59 -0
  18. package/dist/RuntimeScreen.js.map +1 -0
  19. package/dist/appExtensionRegistry.d.ts +3 -0
  20. package/dist/appExtensionRegistry.d.ts.map +1 -0
  21. package/dist/appExtensionRegistry.js +2 -0
  22. package/dist/appExtensionRegistry.js.map +1 -0
  23. package/dist/componentRegistry.d.ts +4 -0
  24. package/dist/componentRegistry.d.ts.map +1 -0
  25. package/dist/componentRegistry.js +6 -0
  26. package/dist/componentRegistry.js.map +1 -0
  27. package/dist/index.d.ts +27 -52
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +16 -30
  30. package/dist/index.js.map +1 -1
  31. package/dist/readme-usage.js +4 -4
  32. package/dist/readme-usage.js.map +1 -1
  33. package/dist/registry.d.ts +7 -0
  34. package/dist/registry.d.ts.map +1 -0
  35. package/dist/registry.js +49 -0
  36. package/dist/registry.js.map +1 -0
  37. package/dist/rendering.d.ts +17 -0
  38. package/dist/rendering.d.ts.map +1 -0
  39. package/dist/rendering.js +24 -0
  40. package/dist/rendering.js.map +1 -0
  41. package/dist/runtimeActionRegistry.d.ts +55 -0
  42. package/dist/runtimeActionRegistry.d.ts.map +1 -0
  43. package/dist/runtimeActionRegistry.js +323 -0
  44. package/dist/runtimeActionRegistry.js.map +1 -0
  45. package/dist/runtimeApiLoaders.d.ts +35 -0
  46. package/dist/runtimeApiLoaders.d.ts.map +1 -0
  47. package/dist/runtimeApiLoaders.js +218 -0
  48. package/dist/runtimeApiLoaders.js.map +1 -0
  49. package/dist/runtimeBindings.d.ts +52 -0
  50. package/dist/runtimeBindings.d.ts.map +1 -0
  51. package/dist/runtimeBindings.js +299 -0
  52. package/dist/runtimeBindings.js.map +1 -0
  53. package/dist/runtimeDataSourceOperations.d.ts +8 -0
  54. package/dist/runtimeDataSourceOperations.d.ts.map +1 -0
  55. package/dist/runtimeDataSourceOperations.js +58 -0
  56. package/dist/runtimeDataSourceOperations.js.map +1 -0
  57. package/dist/runtimeDbPersist.d.ts +34 -0
  58. package/dist/runtimeDbPersist.d.ts.map +1 -0
  59. package/dist/runtimeDbPersist.js +73 -0
  60. package/dist/runtimeDbPersist.js.map +1 -0
  61. package/dist/runtimeEventExecution.d.ts +11 -0
  62. package/dist/runtimeEventExecution.d.ts.map +1 -0
  63. package/dist/runtimeEventExecution.js +17 -0
  64. package/dist/runtimeEventExecution.js.map +1 -0
  65. package/dist/runtimeManifest.d.ts +53 -0
  66. package/dist/runtimeManifest.d.ts.map +1 -0
  67. package/dist/runtimeManifest.js +31 -0
  68. package/dist/runtimeManifest.js.map +1 -0
  69. package/dist/runtimeNodeProps.d.ts +22 -0
  70. package/dist/runtimeNodeProps.d.ts.map +1 -0
  71. package/dist/runtimeNodeProps.js +130 -0
  72. package/dist/runtimeNodeProps.js.map +1 -0
  73. package/dist/runtimeRepeat.d.ts +27 -0
  74. package/dist/runtimeRepeat.d.ts.map +1 -0
  75. package/dist/runtimeRepeat.js +129 -0
  76. package/dist/runtimeRepeat.js.map +1 -0
  77. package/dist/runtimeRepeatDiagnostics.d.ts +3 -0
  78. package/dist/runtimeRepeatDiagnostics.d.ts.map +1 -0
  79. package/dist/runtimeRepeatDiagnostics.js +14 -0
  80. package/dist/runtimeRepeatDiagnostics.js.map +1 -0
  81. package/dist/runtimeRepeatEmptyState.d.ts +7 -0
  82. package/dist/runtimeRepeatEmptyState.d.ts.map +1 -0
  83. package/dist/runtimeRepeatEmptyState.js +10 -0
  84. package/dist/runtimeRepeatEmptyState.js.map +1 -0
  85. package/dist/runtimeScreenLoaders.d.ts +71 -0
  86. package/dist/runtimeScreenLoaders.d.ts.map +1 -0
  87. package/dist/runtimeScreenLoaders.js +309 -0
  88. package/dist/runtimeScreenLoaders.js.map +1 -0
  89. package/dist/runtimeStateAdapter.d.ts +6 -0
  90. package/dist/runtimeStateAdapter.d.ts.map +1 -0
  91. package/dist/runtimeStateAdapter.js +162 -0
  92. package/dist/runtimeStateAdapter.js.map +1 -0
  93. package/package.json +19 -2
  94. package/paradox/badges/npm.svg +3 -3
  95. package/paradox/components.md +72 -0
  96. package/paradox/diagrams/architecture-overview.mmd +135 -1
  97. package/paradox/diagrams/export-graph.mmd +303 -18
  98. package/paradox/diagrams/module-relationships.mmd +98 -1
  99. package/paradox/diagrams/sequences/create-component-event-from-handler-args.mmd +24 -0
  100. package/paradox/diagrams/sequences/execute-db-persist-action.mmd +16 -0
  101. package/paradox/diagrams/sequences/merge-runtime-renderer-config.mmd +11 -0
  102. package/paradox/diagrams/sequences/resolve-db-persist-input.mmd +13 -0
  103. package/paradox/diagrams/sequences/resolve-runtime-action-payload.mmd +8 -0
  104. package/paradox/diagrams/sequences/resolve-runtime-action-value.mmd +5 -0
  105. package/paradox/diagrams/sequences/runtime-renderer-config-provider.mmd +17 -0
  106. package/paradox/diagrams/sequences/runtime-screen.mmd +17 -0
  107. package/paradox/diagrams/sequences/use-manifest-context.mmd +5 -0
  108. package/paradox/diagrams/sequences/use-manifest.mmd +5 -0
  109. package/paradox/diagrams/sequences/use-optional-manifest-context.mmd +5 -0
  110. package/paradox/diagrams/sequences/use-runtime-renderer-config.mmd +5 -0
  111. package/paradox/diagrams/sequences/use-runtime-screen-operation-loaders.mmd +5 -0
  112. package/paradox/diagrams/sequences/validate-runtime-binding-operation-ref.mmd +8 -0
  113. package/paradox/diagrams/sequences/wrap-runtime-event-props.mmd +5 -0
  114. package/paradox/exports.json +3385 -330
  115. package/paradox/exports.md +1051 -38
  116. package/paradox/index.html +8244 -413
  117. package/paradox/paradox.json +10013 -511
@@ -0,0 +1,7 @@
1
+ import type { BindingValue, DataSourceDiagnostic } from '@ankhorage/contracts';
2
+ export declare function shouldRenderRuntimeRepeatEmptyState(args: {
3
+ readonly diagnostics?: readonly DataSourceDiagnostic[];
4
+ readonly items?: readonly BindingValue[];
5
+ readonly status?: 'pending' | 'ready';
6
+ }): boolean;
7
+ //# sourceMappingURL=runtimeRepeatEmptyState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeRepeatEmptyState.d.ts","sourceRoot":"","sources":["../src/runtimeRepeatEmptyState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,wBAAgB,mCAAmC,CAAC,IAAI,EAAE;IACxD,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CACvC,GAAG,OAAO,CAUV"}
@@ -0,0 +1,10 @@
1
+ export function shouldRenderRuntimeRepeatEmptyState(args) {
2
+ if (args.status !== 'ready') {
3
+ return false;
4
+ }
5
+ if (!Array.isArray(args.items) || args.items.length > 0) {
6
+ return false;
7
+ }
8
+ return !(args.diagnostics ?? []).some((diagnostic) => diagnostic.severity === 'error');
9
+ }
10
+ //# sourceMappingURL=runtimeRepeatEmptyState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeRepeatEmptyState.js","sourceRoot":"","sources":["../src/runtimeRepeatEmptyState.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,mCAAmC,CAAC,IAInD;IACC,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;AACzF,CAAC","sourcesContent":["import type { BindingValue, DataSourceDiagnostic } from '@ankhorage/contracts';\n\nexport function shouldRenderRuntimeRepeatEmptyState(args: {\n readonly diagnostics?: readonly DataSourceDiagnostic[];\n readonly items?: readonly BindingValue[];\n readonly status?: 'pending' | 'ready';\n}): boolean {\n if (args.status !== 'ready') {\n return false;\n }\n\n if (!Array.isArray(args.items) || args.items.length > 0) {\n return false;\n }\n\n return !(args.diagnostics ?? []).some((diagnostic) => diagnostic.severity === 'error');\n}\n"]}
@@ -0,0 +1,71 @@
1
+ import type { ApiScreenDataLoaderDefinition, DataSourceDiagnostic, OperationScreenDataLoaderDefinition, ScreenSpec } from '@ankhorage/contracts';
2
+ import { type RuntimeBindingOperationExecutor, type RuntimeBindingOperationResultCache, type RuntimeBindingResolutionContext } from './runtimeBindings';
3
+ export interface RuntimeScreenOperationLoaderState {
4
+ readonly dependencyKey: string;
5
+ readonly diagnostics: readonly DataSourceDiagnostic[];
6
+ readonly operationResults: RuntimeBindingOperationResultCache;
7
+ readonly renderVersion: number;
8
+ }
9
+ export interface RuntimeScreenOperationLoaderExecutionResult {
10
+ readonly dependencyKey: string;
11
+ readonly diagnostics: readonly DataSourceDiagnostic[];
12
+ readonly operationResults: RuntimeBindingOperationResultCache;
13
+ }
14
+ export interface RuntimeScreenOperationLoaderLifecycle {
15
+ readonly activeRequestId: number;
16
+ readonly activeRequestKey: string | null;
17
+ }
18
+ export declare function resolveScreenApiLoaders(screen: ScreenSpec): readonly ApiScreenDataLoaderDefinition[];
19
+ export declare function resolveScreenOperationLoaders(screen: ScreenSpec): readonly OperationScreenDataLoaderDefinition[];
20
+ export declare function createRuntimeScreenLoaderRequestKey(args: {
21
+ readonly screenId: string;
22
+ readonly loaders: readonly OperationScreenDataLoaderDefinition[];
23
+ readonly bindingContext?: Record<string, unknown>;
24
+ readonly operationResults?: RuntimeBindingOperationResultCache;
25
+ }): string;
26
+ export declare function createRuntimeScreenOperationLoaderLifecycle(): RuntimeScreenOperationLoaderLifecycle;
27
+ export declare function createIdleRuntimeScreenOperationLoaderState(args: {
28
+ readonly dependencyKey: string;
29
+ readonly previousState?: RuntimeScreenOperationLoaderState;
30
+ }): RuntimeScreenOperationLoaderState;
31
+ export declare function createPendingRuntimeScreenOperationLoaderState(args: {
32
+ readonly dependencyKey: string;
33
+ readonly previousState?: RuntimeScreenOperationLoaderState;
34
+ }): RuntimeScreenOperationLoaderState;
35
+ export declare function beginRuntimeScreenOperationLoaderRequest(args: {
36
+ readonly hasLoaders: boolean;
37
+ readonly lifecycle: RuntimeScreenOperationLoaderLifecycle;
38
+ readonly requestKey: string;
39
+ readonly state: RuntimeScreenOperationLoaderState;
40
+ }): {
41
+ readonly lifecycle: RuntimeScreenOperationLoaderLifecycle;
42
+ readonly requestId?: number;
43
+ readonly shouldExecute: boolean;
44
+ readonly state: RuntimeScreenOperationLoaderState;
45
+ };
46
+ export declare function completeRuntimeScreenOperationLoaderRequest(args: {
47
+ readonly lifecycle: RuntimeScreenOperationLoaderLifecycle;
48
+ readonly requestId: number;
49
+ readonly result: RuntimeScreenOperationLoaderExecutionResult;
50
+ readonly state: RuntimeScreenOperationLoaderState;
51
+ }): {
52
+ readonly accepted: boolean;
53
+ readonly state: RuntimeScreenOperationLoaderState;
54
+ };
55
+ export declare function executeRuntimeScreenOperationLoaders(args: {
56
+ readonly bindingContext?: Record<string, unknown>;
57
+ readonly dataSources?: RuntimeBindingResolutionContext['dataSources'];
58
+ readonly executeOperation?: RuntimeBindingOperationExecutor;
59
+ readonly operationResults?: RuntimeBindingOperationResultCache;
60
+ readonly screen: ScreenSpec;
61
+ readonly loaders: readonly OperationScreenDataLoaderDefinition[];
62
+ }): Promise<RuntimeScreenOperationLoaderExecutionResult>;
63
+ export declare function useRuntimeScreenOperationLoaders(args: {
64
+ readonly bindingContext?: Record<string, unknown>;
65
+ readonly dataSources?: RuntimeBindingResolutionContext['dataSources'];
66
+ readonly executeOperation?: RuntimeBindingOperationExecutor;
67
+ readonly operationResults?: RuntimeBindingOperationResultCache;
68
+ readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void;
69
+ readonly screen: ScreenSpec;
70
+ }): RuntimeScreenOperationLoaderState;
71
+ //# sourceMappingURL=runtimeScreenLoaders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeScreenLoaders.d.ts","sourceRoot":"","sources":["../src/runtimeScreenLoaders.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,309 @@
1
+ import React from 'react';
2
+ import { createRuntimeBindingOperationKey, resolveBindingInputMapSync, resolveRuntimeBindingOperationSelection, } from './runtimeBindings';
3
+ const EMPTY_RUNTIME_SCREEN_OPERATION_LOADER_DIAGNOSTICS = Object.freeze([]);
4
+ const EMPTY_RUNTIME_SCREEN_OPERATION_RESULTS = Object.freeze({});
5
+ export function resolveScreenApiLoaders(screen) {
6
+ return (screen.dataLoaders ?? []).filter((loader) => loader.kind === 'api');
7
+ }
8
+ export function resolveScreenOperationLoaders(screen) {
9
+ return (screen.dataLoaders ?? []).filter((loader) => loader.kind === 'operation');
10
+ }
11
+ export function createRuntimeScreenLoaderRequestKey(args) {
12
+ return createRuntimeScreenOperationLoaderPlan({
13
+ bindingContext: args.bindingContext,
14
+ loaders: args.loaders,
15
+ operationResults: args.operationResults,
16
+ screenId: args.screenId,
17
+ }).requestKey;
18
+ }
19
+ export function createRuntimeScreenOperationLoaderLifecycle() {
20
+ return {
21
+ activeRequestId: 0,
22
+ activeRequestKey: null,
23
+ };
24
+ }
25
+ export function createIdleRuntimeScreenOperationLoaderState(args) {
26
+ return {
27
+ dependencyKey: args.dependencyKey,
28
+ diagnostics: EMPTY_RUNTIME_SCREEN_OPERATION_LOADER_DIAGNOSTICS,
29
+ operationResults: EMPTY_RUNTIME_SCREEN_OPERATION_RESULTS,
30
+ renderVersion: args.previousState?.renderVersion ?? 0,
31
+ };
32
+ }
33
+ export function createPendingRuntimeScreenOperationLoaderState(args) {
34
+ return {
35
+ dependencyKey: args.dependencyKey,
36
+ diagnostics: [],
37
+ operationResults: {},
38
+ renderVersion: (args.previousState?.renderVersion ?? -1) + 1,
39
+ };
40
+ }
41
+ export function beginRuntimeScreenOperationLoaderRequest(args) {
42
+ if (!args.hasLoaders) {
43
+ if (args.lifecycle.activeRequestKey === null) {
44
+ return {
45
+ lifecycle: args.lifecycle,
46
+ shouldExecute: false,
47
+ state: args.state,
48
+ };
49
+ }
50
+ return {
51
+ lifecycle: {
52
+ activeRequestId: args.lifecycle.activeRequestId + 1,
53
+ activeRequestKey: null,
54
+ },
55
+ shouldExecute: false,
56
+ state: args.state,
57
+ };
58
+ }
59
+ if (args.lifecycle.activeRequestKey === args.requestKey) {
60
+ return {
61
+ lifecycle: args.lifecycle,
62
+ shouldExecute: false,
63
+ state: args.state,
64
+ };
65
+ }
66
+ const requestId = args.lifecycle.activeRequestId + 1;
67
+ return {
68
+ lifecycle: {
69
+ activeRequestId: requestId,
70
+ activeRequestKey: args.requestKey,
71
+ },
72
+ requestId,
73
+ shouldExecute: true,
74
+ state: args.state.dependencyKey === args.requestKey
75
+ ? args.state
76
+ : createPendingRuntimeScreenOperationLoaderState({
77
+ dependencyKey: args.requestKey,
78
+ previousState: args.state,
79
+ }),
80
+ };
81
+ }
82
+ export function completeRuntimeScreenOperationLoaderRequest(args) {
83
+ if (args.lifecycle.activeRequestId !== args.requestId) {
84
+ return {
85
+ accepted: false,
86
+ state: args.state,
87
+ };
88
+ }
89
+ return {
90
+ accepted: true,
91
+ state: {
92
+ dependencyKey: args.result.dependencyKey,
93
+ diagnostics: args.result.diagnostics,
94
+ operationResults: args.result.operationResults,
95
+ renderVersion: args.state.renderVersion,
96
+ },
97
+ };
98
+ }
99
+ export async function executeRuntimeScreenOperationLoaders(args) {
100
+ const plan = createRuntimeScreenOperationLoaderPlan({
101
+ bindingContext: args.bindingContext,
102
+ loaders: args.loaders,
103
+ operationResults: args.operationResults,
104
+ screenId: args.screen.id,
105
+ });
106
+ return executePreparedRuntimeScreenOperationLoaders({
107
+ dataSources: args.dataSources,
108
+ executeOperation: args.executeOperation,
109
+ plan,
110
+ screen: args.screen,
111
+ });
112
+ }
113
+ function executePreparedRuntimeScreenOperationLoaders(args) {
114
+ const diagnostics = [...args.plan.diagnostics];
115
+ if (args.plan.loaders.length === 0) {
116
+ return Promise.resolve({
117
+ dependencyKey: args.plan.requestKey,
118
+ diagnostics,
119
+ operationResults: {},
120
+ });
121
+ }
122
+ if (args.executeOperation === undefined) {
123
+ diagnostics.push(...args.plan.loaders.map((preparedLoader) => createScreenOperationLoaderDiagnostic(preparedLoader.loader, 'missing-adapter', 'Screen operation loader requires an injected operation executor.')));
124
+ return Promise.resolve({
125
+ dependencyKey: args.plan.requestKey,
126
+ diagnostics,
127
+ operationResults: {},
128
+ });
129
+ }
130
+ const { executeOperation } = args;
131
+ return (async () => {
132
+ const operationResults = {};
133
+ for (const preparedLoader of args.plan.loaders) {
134
+ const selection = resolveRuntimeBindingOperationSelection(preparedLoader.loader.operation, args.dataSources, diagnostics);
135
+ if (selection === undefined) {
136
+ continue;
137
+ }
138
+ const result = await executeOperation({
139
+ dataSource: selection.dataSource,
140
+ endpoint: selection.endpoint,
141
+ input: preparedLoader.input,
142
+ node: args.screen.root,
143
+ operation: preparedLoader.loader.operation,
144
+ });
145
+ diagnostics.push(...(result.diagnostics ?? []));
146
+ if (!result.ok) {
147
+ continue;
148
+ }
149
+ operationResults[preparedLoader.operationKey] = result.data;
150
+ }
151
+ return {
152
+ dependencyKey: args.plan.requestKey,
153
+ diagnostics,
154
+ operationResults,
155
+ };
156
+ })();
157
+ }
158
+ export function useRuntimeScreenOperationLoaders(args) {
159
+ const loaders = React.useMemo(() => resolveScreenOperationLoaders(args.screen), [args.screen]);
160
+ const hasLoaders = loaders.length > 0;
161
+ const plan = React.useMemo(() => createRuntimeScreenOperationLoaderPlan({
162
+ bindingContext: args.bindingContext,
163
+ loaders,
164
+ operationResults: args.operationResults,
165
+ screenId: args.screen.id,
166
+ }), [args.bindingContext, args.operationResults, args.screen.id, loaders]);
167
+ const { requestKey } = plan;
168
+ const emptyState = React.useMemo(() => createIdleRuntimeScreenOperationLoaderState({
169
+ dependencyKey: requestKey,
170
+ }), [requestKey]);
171
+ const [state, setState] = React.useState(() => hasLoaders
172
+ ? createPendingRuntimeScreenOperationLoaderState({ dependencyKey: requestKey })
173
+ : emptyState);
174
+ const effectiveState = hasLoaders ? state : emptyState;
175
+ const lastDiagnosticsKeyRef = React.useRef(null);
176
+ const latestStateRef = React.useRef(state);
177
+ const lifecycleRef = React.useRef(createRuntimeScreenOperationLoaderLifecycle());
178
+ const executionArgsByRequestKeyRef = React.useRef({});
179
+ executionArgsByRequestKeyRef.current[requestKey] = {
180
+ dataSources: args.dataSources,
181
+ executeOperation: args.executeOperation,
182
+ plan,
183
+ screen: args.screen,
184
+ };
185
+ latestStateRef.current = state;
186
+ React.useEffect(() => {
187
+ const request = beginRuntimeScreenOperationLoaderRequest({
188
+ hasLoaders,
189
+ lifecycle: lifecycleRef.current,
190
+ requestKey,
191
+ state: latestStateRef.current,
192
+ });
193
+ lifecycleRef.current = request.lifecycle;
194
+ if (request.state !== latestStateRef.current) {
195
+ setState(request.state);
196
+ }
197
+ if (!request.shouldExecute || request.requestId === undefined) {
198
+ return;
199
+ }
200
+ const { requestId } = request;
201
+ void (async () => {
202
+ const executionArgs = executionArgsByRequestKeyRef.current[requestKey];
203
+ if (executionArgs === undefined) {
204
+ return;
205
+ }
206
+ const result = await executePreparedRuntimeScreenOperationLoaders(executionArgs);
207
+ setState((currentState) => {
208
+ const completion = completeRuntimeScreenOperationLoaderRequest({
209
+ lifecycle: lifecycleRef.current,
210
+ requestId,
211
+ result,
212
+ state: currentState,
213
+ });
214
+ return completion.accepted ? completion.state : currentState;
215
+ });
216
+ })();
217
+ }, [hasLoaders, requestKey]);
218
+ React.useEffect(() => {
219
+ if (effectiveState.diagnostics.length === 0) {
220
+ return;
221
+ }
222
+ const diagnosticsKey = stableSerialize(effectiveState.diagnostics);
223
+ if (lastDiagnosticsKeyRef.current === diagnosticsKey) {
224
+ return;
225
+ }
226
+ lastDiagnosticsKeyRef.current = diagnosticsKey;
227
+ args.onDiagnostics?.(effectiveState.diagnostics);
228
+ }, [args.onDiagnostics, effectiveState.diagnostics]);
229
+ return effectiveState;
230
+ }
231
+ function createRuntimeScreenOperationLoaderPlan(args) {
232
+ if (args.loaders.length === 0) {
233
+ return {
234
+ diagnostics: EMPTY_RUNTIME_SCREEN_OPERATION_LOADER_DIAGNOSTICS,
235
+ loaders: [],
236
+ requestKey: createRuntimeScreenOperationLoaderIdleKey(args.screenId),
237
+ };
238
+ }
239
+ const diagnostics = [];
240
+ const preparedLoaders = [];
241
+ const operationKeys = new Set();
242
+ for (const loader of args.loaders) {
243
+ const input = resolveBindingInputMapSync(loader.input, {
244
+ context: args.bindingContext,
245
+ operationResults: args.operationResults,
246
+ }, diagnostics);
247
+ const operationKey = createRuntimeBindingOperationKey(loader.operation);
248
+ if (operationKeys.has(operationKey)) {
249
+ diagnostics.push(createScreenOperationLoaderDiagnostic(loader, 'duplicate-operation-id', `Screen operation loaders must not reuse operation key '${operationKey}' on the same screen.`));
250
+ continue;
251
+ }
252
+ operationKeys.add(operationKey);
253
+ preparedLoaders.push({
254
+ input,
255
+ loader,
256
+ operationKey,
257
+ });
258
+ }
259
+ return {
260
+ diagnostics,
261
+ loaders: preparedLoaders,
262
+ requestKey: createRuntimeScreenOperationLoaderPlanRequestKey({
263
+ loaders: preparedLoaders,
264
+ screenId: args.screenId,
265
+ }),
266
+ };
267
+ }
268
+ function createRuntimeScreenOperationLoaderPlanRequestKey(args) {
269
+ return stableSerialize({
270
+ loaders: args.loaders.map((loader) => ({
271
+ id: loader.loader.id,
272
+ input: loader.input,
273
+ operation: loader.loader.operation,
274
+ operationKey: loader.operationKey,
275
+ })),
276
+ screenId: args.screenId,
277
+ });
278
+ }
279
+ function createScreenOperationLoaderDiagnostic(loader, code, message) {
280
+ return {
281
+ code,
282
+ dataSourceId: loader.operation.dataSourceId,
283
+ endpointId: loader.operation.endpointId,
284
+ operationId: loader.operation.operationId,
285
+ message,
286
+ severity: 'error',
287
+ };
288
+ }
289
+ function createRuntimeScreenOperationLoaderIdleKey(screenId) {
290
+ return `screen:${screenId}:no-operation-loaders`;
291
+ }
292
+ function stableSerialize(value) {
293
+ return JSON.stringify(sortSerializableValue(value));
294
+ }
295
+ function sortSerializableValue(value) {
296
+ if (Array.isArray(value)) {
297
+ return value.map(sortSerializableValue);
298
+ }
299
+ if (typeof value !== 'object' || value === null) {
300
+ return value;
301
+ }
302
+ return Object.keys(value)
303
+ .sort((left, right) => left.localeCompare(right))
304
+ .reduce((result, key) => {
305
+ result[key] = sortSerializableValue(value[key]);
306
+ return result;
307
+ }, {});
308
+ }
309
+ //# sourceMappingURL=runtimeScreenLoaders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeScreenLoaders.js","sourceRoot":"","sources":["../src/runtimeScreenLoaders.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ApiScreenDataLoaderDefinition,\n BindingValue,\n DataSourceDiagnostic,\n OperationScreenDataLoaderDefinition,\n ScreenSpec,\n} from '@ankhorage/contracts';\nimport React from 'react';\n\nimport {\n createRuntimeBindingOperationKey,\n resolveBindingInputMapSync,\n resolveRuntimeBindingOperationSelection,\n type RuntimeBindingOperationExecutor,\n type RuntimeBindingOperationResultCache,\n type RuntimeBindingResolutionContext,\n} from './runtimeBindings';\n\nexport interface RuntimeScreenOperationLoaderState {\n readonly dependencyKey: string;\n readonly diagnostics: readonly DataSourceDiagnostic[];\n readonly operationResults: RuntimeBindingOperationResultCache;\n readonly renderVersion: number;\n}\n\nexport interface RuntimeScreenOperationLoaderExecutionResult {\n readonly dependencyKey: string;\n readonly diagnostics: readonly DataSourceDiagnostic[];\n readonly operationResults: RuntimeBindingOperationResultCache;\n}\n\nexport interface RuntimeScreenOperationLoaderLifecycle {\n readonly activeRequestId: number;\n readonly activeRequestKey: string | null;\n}\n\nconst EMPTY_RUNTIME_SCREEN_OPERATION_LOADER_DIAGNOSTICS = Object.freeze(\n [],\n) as readonly DataSourceDiagnostic[];\nconst EMPTY_RUNTIME_SCREEN_OPERATION_RESULTS = Object.freeze(\n {},\n) as RuntimeBindingOperationResultCache;\n\nexport function resolveScreenApiLoaders(\n screen: ScreenSpec,\n): readonly ApiScreenDataLoaderDefinition[] {\n return (screen.dataLoaders ?? []).filter(\n (loader): loader is ApiScreenDataLoaderDefinition => loader.kind === 'api',\n );\n}\n\nexport function resolveScreenOperationLoaders(\n screen: ScreenSpec,\n): readonly OperationScreenDataLoaderDefinition[] {\n return (screen.dataLoaders ?? []).filter(\n (loader): loader is OperationScreenDataLoaderDefinition => loader.kind === 'operation',\n );\n}\n\nexport function createRuntimeScreenLoaderRequestKey(args: {\n readonly screenId: string;\n readonly loaders: readonly OperationScreenDataLoaderDefinition[];\n readonly bindingContext?: Record<string, unknown>;\n readonly operationResults?: RuntimeBindingOperationResultCache;\n}): string {\n return createRuntimeScreenOperationLoaderPlan({\n bindingContext: args.bindingContext,\n loaders: args.loaders,\n operationResults: args.operationResults,\n screenId: args.screenId,\n }).requestKey;\n}\n\nexport function createRuntimeScreenOperationLoaderLifecycle(): RuntimeScreenOperationLoaderLifecycle {\n return {\n activeRequestId: 0,\n activeRequestKey: null,\n };\n}\n\nexport function createIdleRuntimeScreenOperationLoaderState(args: {\n readonly dependencyKey: string;\n readonly previousState?: RuntimeScreenOperationLoaderState;\n}): RuntimeScreenOperationLoaderState {\n return {\n dependencyKey: args.dependencyKey,\n diagnostics: EMPTY_RUNTIME_SCREEN_OPERATION_LOADER_DIAGNOSTICS,\n operationResults: EMPTY_RUNTIME_SCREEN_OPERATION_RESULTS,\n renderVersion: args.previousState?.renderVersion ?? 0,\n };\n}\n\nexport function createPendingRuntimeScreenOperationLoaderState(args: {\n readonly dependencyKey: string;\n readonly previousState?: RuntimeScreenOperationLoaderState;\n}): RuntimeScreenOperationLoaderState {\n return {\n dependencyKey: args.dependencyKey,\n diagnostics: [],\n operationResults: {},\n renderVersion: (args.previousState?.renderVersion ?? -1) + 1,\n };\n}\n\nexport function beginRuntimeScreenOperationLoaderRequest(args: {\n readonly hasLoaders: boolean;\n readonly lifecycle: RuntimeScreenOperationLoaderLifecycle;\n readonly requestKey: string;\n readonly state: RuntimeScreenOperationLoaderState;\n}): {\n readonly lifecycle: RuntimeScreenOperationLoaderLifecycle;\n readonly requestId?: number;\n readonly shouldExecute: boolean;\n readonly state: RuntimeScreenOperationLoaderState;\n} {\n if (!args.hasLoaders) {\n if (args.lifecycle.activeRequestKey === null) {\n return {\n lifecycle: args.lifecycle,\n shouldExecute: false,\n state: args.state,\n };\n }\n\n return {\n lifecycle: {\n activeRequestId: args.lifecycle.activeRequestId + 1,\n activeRequestKey: null,\n },\n shouldExecute: false,\n state: args.state,\n };\n }\n\n if (args.lifecycle.activeRequestKey === args.requestKey) {\n return {\n lifecycle: args.lifecycle,\n shouldExecute: false,\n state: args.state,\n };\n }\n\n const requestId = args.lifecycle.activeRequestId + 1;\n\n return {\n lifecycle: {\n activeRequestId: requestId,\n activeRequestKey: args.requestKey,\n },\n requestId,\n shouldExecute: true,\n state:\n args.state.dependencyKey === args.requestKey\n ? args.state\n : createPendingRuntimeScreenOperationLoaderState({\n dependencyKey: args.requestKey,\n previousState: args.state,\n }),\n };\n}\n\nexport function completeRuntimeScreenOperationLoaderRequest(args: {\n readonly lifecycle: RuntimeScreenOperationLoaderLifecycle;\n readonly requestId: number;\n readonly result: RuntimeScreenOperationLoaderExecutionResult;\n readonly state: RuntimeScreenOperationLoaderState;\n}): {\n readonly accepted: boolean;\n readonly state: RuntimeScreenOperationLoaderState;\n} {\n if (args.lifecycle.activeRequestId !== args.requestId) {\n return {\n accepted: false,\n state: args.state,\n };\n }\n\n return {\n accepted: true,\n state: {\n dependencyKey: args.result.dependencyKey,\n diagnostics: args.result.diagnostics,\n operationResults: args.result.operationResults,\n renderVersion: args.state.renderVersion,\n },\n };\n}\n\nexport async function executeRuntimeScreenOperationLoaders(args: {\n readonly bindingContext?: Record<string, unknown>;\n readonly dataSources?: RuntimeBindingResolutionContext['dataSources'];\n readonly executeOperation?: RuntimeBindingOperationExecutor;\n readonly operationResults?: RuntimeBindingOperationResultCache;\n readonly screen: ScreenSpec;\n readonly loaders: readonly OperationScreenDataLoaderDefinition[];\n}): Promise<RuntimeScreenOperationLoaderExecutionResult> {\n const plan = createRuntimeScreenOperationLoaderPlan({\n bindingContext: args.bindingContext,\n loaders: args.loaders,\n operationResults: args.operationResults,\n screenId: args.screen.id,\n });\n\n return executePreparedRuntimeScreenOperationLoaders({\n dataSources: args.dataSources,\n executeOperation: args.executeOperation,\n plan,\n screen: args.screen,\n });\n}\n\nfunction executePreparedRuntimeScreenOperationLoaders(args: {\n readonly dataSources?: RuntimeBindingResolutionContext['dataSources'];\n readonly executeOperation?: RuntimeBindingOperationExecutor;\n readonly plan: RuntimeScreenOperationLoaderPlan;\n readonly screen: ScreenSpec;\n}): Promise<RuntimeScreenOperationLoaderExecutionResult> {\n const diagnostics: DataSourceDiagnostic[] = [...args.plan.diagnostics];\n\n if (args.plan.loaders.length === 0) {\n return Promise.resolve({\n dependencyKey: args.plan.requestKey,\n diagnostics,\n operationResults: {},\n });\n }\n\n if (args.executeOperation === undefined) {\n diagnostics.push(\n ...args.plan.loaders.map((preparedLoader) =>\n createScreenOperationLoaderDiagnostic(\n preparedLoader.loader,\n 'missing-adapter',\n 'Screen operation loader requires an injected operation executor.',\n ),\n ),\n );\n\n return Promise.resolve({\n dependencyKey: args.plan.requestKey,\n diagnostics,\n operationResults: {},\n });\n }\n const { executeOperation } = args;\n\n return (async () => {\n const operationResults: Record<string, BindingValue | undefined> = {};\n\n for (const preparedLoader of args.plan.loaders) {\n const selection = resolveRuntimeBindingOperationSelection(\n preparedLoader.loader.operation,\n args.dataSources,\n diagnostics,\n );\n if (selection === undefined) {\n continue;\n }\n\n const result = await executeOperation({\n dataSource: selection.dataSource,\n endpoint: selection.endpoint,\n input: preparedLoader.input,\n node: args.screen.root,\n operation: preparedLoader.loader.operation,\n });\n diagnostics.push(...(result.diagnostics ?? []));\n\n if (!result.ok) {\n continue;\n }\n\n operationResults[preparedLoader.operationKey] = result.data;\n }\n\n return {\n dependencyKey: args.plan.requestKey,\n diagnostics,\n operationResults,\n };\n })();\n}\n\nexport function useRuntimeScreenOperationLoaders(args: {\n readonly bindingContext?: Record<string, unknown>;\n readonly dataSources?: RuntimeBindingResolutionContext['dataSources'];\n readonly executeOperation?: RuntimeBindingOperationExecutor;\n readonly operationResults?: RuntimeBindingOperationResultCache;\n readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void;\n readonly screen: ScreenSpec;\n}): RuntimeScreenOperationLoaderState {\n const loaders = React.useMemo(() => resolveScreenOperationLoaders(args.screen), [args.screen]);\n const hasLoaders = loaders.length > 0;\n const plan = React.useMemo(\n () =>\n createRuntimeScreenOperationLoaderPlan({\n bindingContext: args.bindingContext,\n loaders,\n operationResults: args.operationResults,\n screenId: args.screen.id,\n }),\n [args.bindingContext, args.operationResults, args.screen.id, loaders],\n );\n const { requestKey } = plan;\n const emptyState = React.useMemo(\n () =>\n createIdleRuntimeScreenOperationLoaderState({\n dependencyKey: requestKey,\n }),\n [requestKey],\n );\n const [state, setState] = React.useState<RuntimeScreenOperationLoaderState>(() =>\n hasLoaders\n ? createPendingRuntimeScreenOperationLoaderState({ dependencyKey: requestKey })\n : emptyState,\n );\n const effectiveState = hasLoaders ? state : emptyState;\n const lastDiagnosticsKeyRef = React.useRef<string | null>(null);\n const latestStateRef = React.useRef(state);\n const lifecycleRef = React.useRef<RuntimeScreenOperationLoaderLifecycle>(\n createRuntimeScreenOperationLoaderLifecycle(),\n );\n const executionArgsByRequestKeyRef = React.useRef<\n Record<string, RuntimeScreenPreparedExecutionArgs>\n >({});\n\n executionArgsByRequestKeyRef.current[requestKey] = {\n dataSources: args.dataSources,\n executeOperation: args.executeOperation,\n plan,\n screen: args.screen,\n };\n latestStateRef.current = state;\n\n React.useEffect(() => {\n const request = beginRuntimeScreenOperationLoaderRequest({\n hasLoaders,\n lifecycle: lifecycleRef.current,\n requestKey,\n state: latestStateRef.current,\n });\n\n lifecycleRef.current = request.lifecycle;\n\n if (request.state !== latestStateRef.current) {\n setState(request.state);\n }\n\n if (!request.shouldExecute || request.requestId === undefined) {\n return;\n }\n const { requestId } = request;\n\n void (async () => {\n const executionArgs = executionArgsByRequestKeyRef.current[requestKey];\n if (executionArgs === undefined) {\n return;\n }\n\n const result = await executePreparedRuntimeScreenOperationLoaders(executionArgs);\n\n setState((currentState) => {\n const completion = completeRuntimeScreenOperationLoaderRequest({\n lifecycle: lifecycleRef.current,\n requestId,\n result,\n state: currentState,\n });\n\n return completion.accepted ? completion.state : currentState;\n });\n })();\n }, [hasLoaders, requestKey]);\n\n React.useEffect(() => {\n if (effectiveState.diagnostics.length === 0) {\n return;\n }\n\n const diagnosticsKey = stableSerialize(effectiveState.diagnostics);\n if (lastDiagnosticsKeyRef.current === diagnosticsKey) {\n return;\n }\n\n lastDiagnosticsKeyRef.current = diagnosticsKey;\n args.onDiagnostics?.(effectiveState.diagnostics);\n }, [args.onDiagnostics, effectiveState.diagnostics]);\n\n return effectiveState;\n}\n\ninterface PreparedRuntimeScreenOperationLoader {\n readonly input?: BindingValue;\n readonly loader: OperationScreenDataLoaderDefinition;\n readonly operationKey: string;\n}\n\ninterface RuntimeScreenOperationLoaderPlan {\n readonly diagnostics: readonly DataSourceDiagnostic[];\n readonly loaders: readonly PreparedRuntimeScreenOperationLoader[];\n readonly requestKey: string;\n}\n\ninterface RuntimeScreenPreparedExecutionArgs {\n readonly dataSources?: RuntimeBindingResolutionContext['dataSources'];\n readonly executeOperation?: RuntimeBindingOperationExecutor;\n readonly plan: RuntimeScreenOperationLoaderPlan;\n readonly screen: ScreenSpec;\n}\n\nfunction createRuntimeScreenOperationLoaderPlan(args: {\n readonly bindingContext?: Record<string, unknown>;\n readonly loaders: readonly OperationScreenDataLoaderDefinition[];\n readonly operationResults?: RuntimeBindingOperationResultCache;\n readonly screenId: string;\n}): RuntimeScreenOperationLoaderPlan {\n if (args.loaders.length === 0) {\n return {\n diagnostics: EMPTY_RUNTIME_SCREEN_OPERATION_LOADER_DIAGNOSTICS,\n loaders: [],\n requestKey: createRuntimeScreenOperationLoaderIdleKey(args.screenId),\n };\n }\n\n const diagnostics: DataSourceDiagnostic[] = [];\n const preparedLoaders: PreparedRuntimeScreenOperationLoader[] = [];\n const operationKeys = new Set<string>();\n\n for (const loader of args.loaders) {\n const input = resolveBindingInputMapSync(\n loader.input,\n {\n context: args.bindingContext,\n operationResults: args.operationResults,\n },\n diagnostics,\n );\n const operationKey = createRuntimeBindingOperationKey(loader.operation);\n if (operationKeys.has(operationKey)) {\n diagnostics.push(\n createScreenOperationLoaderDiagnostic(\n loader,\n 'duplicate-operation-id',\n `Screen operation loaders must not reuse operation key '${operationKey}' on the same screen.`,\n ),\n );\n continue;\n }\n\n operationKeys.add(operationKey);\n preparedLoaders.push({\n input,\n loader,\n operationKey,\n });\n }\n\n return {\n diagnostics,\n loaders: preparedLoaders,\n requestKey: createRuntimeScreenOperationLoaderPlanRequestKey({\n loaders: preparedLoaders,\n screenId: args.screenId,\n }),\n };\n}\n\nfunction createRuntimeScreenOperationLoaderPlanRequestKey(args: {\n readonly loaders: readonly PreparedRuntimeScreenOperationLoader[];\n readonly screenId: string;\n}): string {\n return stableSerialize({\n loaders: args.loaders.map((loader) => ({\n id: loader.loader.id,\n input: loader.input,\n operation: loader.loader.operation,\n operationKey: loader.operationKey,\n })),\n screenId: args.screenId,\n });\n}\n\nfunction createScreenOperationLoaderDiagnostic(\n loader: OperationScreenDataLoaderDefinition,\n code: DataSourceDiagnostic['code'],\n message: string,\n): DataSourceDiagnostic {\n return {\n code,\n dataSourceId: loader.operation.dataSourceId,\n endpointId: loader.operation.endpointId,\n operationId: loader.operation.operationId,\n message,\n severity: 'error',\n };\n}\n\nfunction createRuntimeScreenOperationLoaderIdleKey(screenId: string): string {\n return `screen:${screenId}:no-operation-loaders`;\n}\n\nfunction stableSerialize(value: unknown): string {\n return JSON.stringify(sortSerializableValue(value));\n}\n\nfunction sortSerializableValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortSerializableValue);\n }\n\n if (typeof value !== 'object' || value === null) {\n return value;\n }\n\n return Object.keys(value)\n .sort((left, right) => left.localeCompare(right))\n .reduce<Record<string, unknown>>((result, key) => {\n result[key] = sortSerializableValue((value as Record<string, unknown>)[key]);\n return result;\n }, {});\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { StateAdapter, StateValue } from '@ankhorage/contracts';
2
+ export interface RuntimeMemoryStateAdapterOptions {
3
+ readonly initialState?: Readonly<Record<string, StateValue>>;
4
+ }
5
+ export declare function createRuntimeMemoryStateAdapter(options?: RuntimeMemoryStateAdapterOptions): StateAdapter;
6
+ //# sourceMappingURL=runtimeStateAdapter.d.ts.map
@@ -0,0 +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;AAK9B,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,CA+Ed"}
@@ -0,0 +1,162 @@
1
+ export function createRuntimeMemoryStateAdapter(options = {}) {
2
+ let rootState = { ...(options.initialState ?? {}) };
3
+ const listeners = new Map();
4
+ const emit = (path, value) => {
5
+ const pathResult = normalizeStatePath(path);
6
+ if (!pathResult.ok)
7
+ return;
8
+ const listenersForPath = listeners.get(pathPartsToKey(pathResult.parts));
9
+ if (listenersForPath === undefined)
10
+ return;
11
+ for (const listener of listenersForPath) {
12
+ listener(value);
13
+ }
14
+ };
15
+ return {
16
+ capabilities: {
17
+ subscriptions: true,
18
+ computed: false,
19
+ persistence: false,
20
+ },
21
+ get(path) {
22
+ const pathResult = normalizeStatePath(path);
23
+ if (!pathResult.ok)
24
+ return pathResult;
25
+ return createStateDataResult(readStatePath(rootState, pathResult.parts));
26
+ },
27
+ set(path, value) {
28
+ const pathResult = normalizeStatePath(path);
29
+ if (!pathResult.ok)
30
+ return pathResult;
31
+ const nextStateResult = setStatePath(rootState, pathResult.parts, value);
32
+ if (!nextStateResult.ok)
33
+ return nextStateResult;
34
+ rootState = nextStateResult.data;
35
+ emit(path, value);
36
+ return { ok: true };
37
+ },
38
+ subscribe(path, listener) {
39
+ const pathResult = normalizeStatePath(path);
40
+ if (!pathResult.ok)
41
+ return pathResult;
42
+ const key = pathPartsToKey(pathResult.parts);
43
+ const listenersForPath = listeners.get(key) ?? new Set();
44
+ const wrappedListener = (value) => {
45
+ listener({ path, value: value });
46
+ };
47
+ listenersForPath.add(wrappedListener);
48
+ listeners.set(key, listenersForPath);
49
+ return createStateDataResult({
50
+ unsubscribe() {
51
+ listenersForPath.delete(wrappedListener);
52
+ if (listenersForPath.size === 0) {
53
+ listeners.delete(key);
54
+ }
55
+ },
56
+ });
57
+ },
58
+ delete(path) {
59
+ const pathResult = normalizeStatePath(path);
60
+ if (!pathResult.ok)
61
+ return pathResult;
62
+ const nextStateResult = deleteStatePath(rootState, pathResult.parts);
63
+ if (!nextStateResult.ok)
64
+ return nextStateResult;
65
+ rootState = nextStateResult.data;
66
+ emit(path, undefined);
67
+ return { ok: true };
68
+ },
69
+ };
70
+ }
71
+ function normalizeStatePath(path) {
72
+ const parts = typeof path === 'string' ? path.split('.') : [...path];
73
+ const normalized = parts.map((part) => part.trim()).filter(Boolean);
74
+ if (normalized.length === 0) {
75
+ return createStateError('invalid_path', 'State path must contain at least one segment.');
76
+ }
77
+ return {
78
+ ok: true,
79
+ parts: normalized,
80
+ };
81
+ }
82
+ function pathPartsToKey(parts) {
83
+ return parts.join('.');
84
+ }
85
+ function readStatePath(source, parts) {
86
+ let currentValue = source;
87
+ for (const part of parts) {
88
+ if (!isStateRecord(currentValue)) {
89
+ return undefined;
90
+ }
91
+ currentValue = currentValue[part];
92
+ }
93
+ return currentValue;
94
+ }
95
+ function setStatePath(source, parts, value) {
96
+ const [head, ...tail] = parts;
97
+ if (head === undefined) {
98
+ return createStateError('invalid_path', 'State path must contain at least one segment.');
99
+ }
100
+ if (tail.length === 0) {
101
+ return createStateDataResult({
102
+ ...source,
103
+ [head]: value,
104
+ });
105
+ }
106
+ const existing = source[head];
107
+ const child = existing === undefined ? {} : existing;
108
+ if (!isStateRecord(child)) {
109
+ return createStateError('path_conflict', `Cannot set nested state below non-object path segment "${head}".`);
110
+ }
111
+ const childResult = setStatePath(child, tail, value);
112
+ if (!childResult.ok)
113
+ return childResult;
114
+ return createStateDataResult({
115
+ ...source,
116
+ [head]: childResult.data,
117
+ });
118
+ }
119
+ function deleteStatePath(source, parts) {
120
+ const [head, ...tail] = parts;
121
+ if (head === undefined) {
122
+ return createStateError('invalid_path', 'State path must contain at least one segment.');
123
+ }
124
+ if (tail.length === 0) {
125
+ const nextState = {};
126
+ for (const [key, value] of Object.entries(source)) {
127
+ if (key !== head) {
128
+ nextState[key] = value;
129
+ }
130
+ }
131
+ return createStateDataResult(nextState);
132
+ }
133
+ const existing = source[head];
134
+ if (existing === undefined) {
135
+ return createStateDataResult(source);
136
+ }
137
+ if (!isStateRecord(existing)) {
138
+ return createStateError('path_conflict', `Cannot delete nested state below non-object path segment "${head}".`);
139
+ }
140
+ const childResult = deleteStatePath(existing, tail);
141
+ if (!childResult.ok)
142
+ return childResult;
143
+ return createStateDataResult({
144
+ ...source,
145
+ [head]: childResult.data,
146
+ });
147
+ }
148
+ function isStateRecord(value) {
149
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
150
+ }
151
+ function createStateError(code, message) {
152
+ const error = { code, message };
153
+ return { ok: false, error };
154
+ }
155
+ function createStateDataResult(data) {
156
+ const result = {
157
+ ok: true,
158
+ data,
159
+ };
160
+ return result;
161
+ }
162
+ //# sourceMappingURL=runtimeStateAdapter.js.map