@ankhorage/runtime 4.1.2 → 5.0.1

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 (86) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +6 -6
  3. package/dist/RuntimeRenderer.d.ts +7 -7
  4. package/dist/RuntimeRenderer.d.ts.map +1 -1
  5. package/dist/RuntimeRenderer.js +40 -80
  6. package/dist/RuntimeRenderer.js.map +1 -1
  7. package/dist/RuntimeRendererConfig.d.ts +7 -22
  8. package/dist/RuntimeRendererConfig.d.ts.map +1 -1
  9. package/dist/RuntimeRendererConfig.js +5 -8
  10. package/dist/RuntimeRendererConfig.js.map +1 -1
  11. package/dist/RuntimeScreen.d.ts.map +1 -1
  12. package/dist/RuntimeScreen.js +10 -5
  13. package/dist/RuntimeScreen.js.map +1 -1
  14. package/dist/bindings.d.ts +4 -8
  15. package/dist/bindings.d.ts.map +1 -1
  16. package/dist/bindings.js +2 -4
  17. package/dist/bindings.js.map +1 -1
  18. package/dist/index.d.ts +10 -12
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +5 -6
  21. package/dist/index.js.map +1 -1
  22. package/dist/runtimeActionRegistry.d.ts +19 -24
  23. package/dist/runtimeActionRegistry.d.ts.map +1 -1
  24. package/dist/runtimeActionRegistry.js +90 -306
  25. package/dist/runtimeActionRegistry.js.map +1 -1
  26. package/dist/runtimeApiCapabilities.d.ts +11 -0
  27. package/dist/runtimeApiCapabilities.d.ts.map +1 -0
  28. package/dist/runtimeApiCapabilities.js +67 -0
  29. package/dist/runtimeApiCapabilities.js.map +1 -0
  30. package/dist/runtimeBindings.d.ts +28 -17
  31. package/dist/runtimeBindings.d.ts.map +1 -1
  32. package/dist/runtimeBindings.js +157 -197
  33. package/dist/runtimeBindings.js.map +1 -1
  34. package/dist/runtimeCapabilityExecutor.d.ts +8 -0
  35. package/dist/runtimeCapabilityExecutor.d.ts.map +1 -0
  36. package/dist/runtimeCapabilityExecutor.js +21 -0
  37. package/dist/runtimeCapabilityExecutor.js.map +1 -0
  38. package/dist/runtimeEventExecution.d.ts +1 -4
  39. package/dist/runtimeEventExecution.d.ts.map +1 -1
  40. package/dist/runtimeEventExecution.js.map +1 -1
  41. package/dist/runtimeEventOperationLifecycle.d.ts +4 -3
  42. package/dist/runtimeEventOperationLifecycle.d.ts.map +1 -1
  43. package/dist/runtimeEventOperationLifecycle.js +5 -5
  44. package/dist/runtimeEventOperationLifecycle.js.map +1 -1
  45. package/dist/runtimeNodeProps.d.ts +12 -24
  46. package/dist/runtimeNodeProps.d.ts.map +1 -1
  47. package/dist/runtimeNodeProps.js +27 -121
  48. package/dist/runtimeNodeProps.js.map +1 -1
  49. package/dist/runtimeRepeat.d.ts +6 -2
  50. package/dist/runtimeRepeat.d.ts.map +1 -1
  51. package/dist/runtimeRepeat.js +29 -108
  52. package/dist/runtimeRepeat.js.map +1 -1
  53. package/dist/runtimeScreenLoaders.d.ts +27 -42
  54. package/dist/runtimeScreenLoaders.d.ts.map +1 -1
  55. package/dist/runtimeScreenLoaders.js +113 -273
  56. package/dist/runtimeScreenLoaders.js.map +1 -1
  57. package/package.json +9 -3
  58. package/paradox/badges/npm.svg +3 -3
  59. package/paradox/components.md +6 -7
  60. package/paradox/diagrams/architecture-overview.mmd +25 -79
  61. package/paradox/diagrams/export-graph.mmd +67 -105
  62. package/paradox/diagrams/module-relationships.mmd +19 -59
  63. package/paradox/diagrams/sequences/apply-runtime-binding-data-path.mmd +14 -0
  64. package/paradox/diagrams/sequences/create-component-event-from-handler-args.mmd +0 -13
  65. package/paradox/diagrams/sequences/create-runtime-screen-loader-request-key.mmd +5 -0
  66. package/paradox/diagrams/sequences/execute-runtime-binding-invocation.mmd +19 -0
  67. package/paradox/diagrams/sequences/resolve-binding-input-map-sync.mmd +5 -0
  68. package/paradox/diagrams/sequences/resolve-binding-input-map.mmd +5 -0
  69. package/paradox/diagrams/sequences/runtime-screen.mmd +6 -3
  70. package/paradox/diagrams/sequences/use-runtime-screen-operation-loaders.mmd +6 -3
  71. package/paradox/exports.json +610 -848
  72. package/paradox/exports.md +280 -308
  73. package/paradox/index.html +1120 -2266
  74. package/paradox/paradox.json +2724 -5528
  75. package/dist/runtimeApiOperations.d.ts +0 -8
  76. package/dist/runtimeApiOperations.d.ts.map +0 -1
  77. package/dist/runtimeApiOperations.js +0 -38
  78. package/dist/runtimeApiOperations.js.map +0 -1
  79. package/dist/runtimeApiSelection.d.ts +0 -8
  80. package/dist/runtimeApiSelection.d.ts.map +0 -1
  81. package/dist/runtimeApiSelection.js +0 -52
  82. package/dist/runtimeApiSelection.js.map +0 -1
  83. package/dist/runtimeDbPersist.d.ts +0 -34
  84. package/dist/runtimeDbPersist.d.ts.map +0 -1
  85. package/dist/runtimeDbPersist.js +0 -73
  86. package/dist/runtimeDbPersist.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"runtimeRepeat.js","sourceRoot":"","sources":["../src/runtimeRepeat.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n BindingValue,\n DataSourceDiagnostic,\n UiNode,\n UiNodeRepeatSpec,\n} from '@ankhorage/contracts';\n\nimport { resolveRuntimeBindingOperationSelection } from './runtimeApiSelection';\nimport {\n applyRuntimeBindingDataPath,\n createRuntimeBindingOperationKey,\n resolveRuntimeBindingValueSourceSync,\n type RuntimeBindingOperationResultWriter,\n type RuntimeBindingResolutionContext,\n} from './runtimeBindings';\n\nexport interface RuntimeRepeatResolutionContext extends RuntimeBindingResolutionContext {\n readonly node: UiNode;\n readonly writeOperationResult?: RuntimeBindingOperationResultWriter;\n}\n\nexport interface RuntimeRepeatItemsResult {\n readonly items: readonly BindingValue[];\n readonly diagnostics: readonly DataSourceDiagnostic[];\n}\n\nexport interface RuntimeRepeatItemsSyncResult extends RuntimeRepeatItemsResult {\n readonly status: 'ready' | 'pending';\n}\n\nexport function resolveRuntimeRepeatItemsSync(\n repeat: UiNodeRepeatSpec,\n context: RuntimeRepeatResolutionContext,\n): RuntimeRepeatItemsSyncResult {\n if (repeat.source.kind !== 'operation') {\n const diagnostics: DataSourceDiagnostic[] = [];\n const resolved = resolveRuntimeBindingValueSourceSync(repeat.source, context, diagnostics);\n return {\n status: 'ready',\n ...finalizeRuntimeRepeatItems(repeat, resolved, diagnostics),\n };\n }\n\n const operationKey = createRuntimeBindingOperationKey(repeat.source.operation);\n const cached = context.operationResults?.[operationKey];\n if (cached !== undefined) {\n return {\n status: 'ready',\n ...finalizeRuntimeRepeatItems(\n repeat,\n applyRuntimeBindingDataPath(cached, repeat.source.path),\n [],\n ),\n };\n }\n\n if (context.executeOperation !== undefined) {\n return {\n status: 'pending',\n items: [],\n diagnostics: [],\n };\n }\n\n return {\n status: 'ready',\n items: [],\n diagnostics: [\n createRepeatDiagnostic(\n repeat,\n 'missing-adapter',\n 'Repeat API operation source requires an injected operation executor.',\n ),\n ],\n };\n}\n\nexport async function resolveRuntimeRepeatItemsAsync(\n repeat: UiNodeRepeatSpec,\n context: RuntimeRepeatResolutionContext,\n): Promise<RuntimeRepeatItemsResult> {\n if (repeat.source.kind !== 'operation') {\n const diagnostics: DataSourceDiagnostic[] = [];\n const resolved = await Promise.resolve(\n resolveRuntimeBindingValueSourceSync(repeat.source, context, diagnostics),\n );\n return finalizeRuntimeRepeatItems(repeat, resolved, diagnostics);\n }\n\n const operationKey = createRuntimeBindingOperationKey(repeat.source.operation);\n const cached = context.operationResults?.[operationKey];\n if (cached !== undefined) {\n return finalizeRuntimeRepeatItems(\n repeat,\n applyRuntimeBindingDataPath(cached, repeat.source.path),\n [],\n );\n }\n\n if (context.executeOperation === undefined) {\n return {\n items: [],\n diagnostics: [\n createRepeatDiagnostic(\n repeat,\n 'missing-adapter',\n 'Repeat API operation source requires an injected operation executor.',\n ),\n ],\n };\n }\n\n const diagnostics: DataSourceDiagnostic[] = [];\n const selection = resolveRuntimeBindingOperationSelection(\n repeat.source.operation,\n context.apis,\n diagnostics,\n );\n if (selection === undefined) {\n return { items: [], diagnostics };\n }\n\n const result = await context.executeOperation({\n api: selection.api,\n endpoint: selection.endpoint,\n operation: repeat.source.operation,\n node: context.node,\n });\n diagnostics.push(...(result.diagnostics ?? []));\n\n if (!result.ok) {\n return { items: [], diagnostics };\n }\n\n context.writeOperationResult?.(operationKey, result.data);\n return finalizeRuntimeRepeatItems(\n repeat,\n applyRuntimeBindingDataPath(result.data, repeat.source.path),\n diagnostics,\n );\n}\n\nexport function createRuntimeRepeatBindingContext(args: {\n readonly baseContext?: Record<string, unknown>;\n readonly item: BindingValue;\n readonly itemAlias?: string;\n}): Record<string, unknown> {\n return {\n ...(args.baseContext ?? {}),\n [args.itemAlias ?? 'item']: args.item,\n };\n}\n\nexport function resolveRuntimeRepeatItemKey(args: {\n readonly item: BindingValue;\n readonly itemAlias?: string;\n readonly index: number;\n readonly keyPath?: string;\n}): string | number {\n const explicitKey = readRepeatPrimitive(args.item, args.keyPath ?? 'id');\n if (explicitKey !== undefined) {\n return explicitKey;\n }\n\n const fallbackId = readRepeatPrimitive(args.item, 'id');\n if (fallbackId !== undefined) {\n return fallbackId;\n }\n\n const fallbackItemId = readRepeatPrimitive(args.item, 'itemId');\n if (fallbackItemId !== undefined) {\n return fallbackItemId;\n }\n\n return args.index;\n}\n\nfunction finalizeRuntimeRepeatItems(\n repeat: UiNodeRepeatSpec,\n value: BindingValue | undefined,\n diagnostics: readonly DataSourceDiagnostic[],\n): RuntimeRepeatItemsResult {\n if (Array.isArray(value)) {\n return {\n items: value,\n diagnostics,\n };\n }\n\n return {\n items: [],\n diagnostics: [\n ...diagnostics,\n createRepeatDiagnostic(repeat, 'invalid-config', 'Repeat source must resolve to an array.'),\n ],\n };\n}\n\nfunction createRepeatDiagnostic(\n repeat: UiNodeRepeatSpec,\n code: DataSourceDiagnostic['code'],\n message: string,\n): DataSourceDiagnostic {\n return {\n apiId: repeat.source.kind === 'operation' ? repeat.source.operation.apiId : undefined,\n endpointId: repeat.source.kind === 'operation' ? repeat.source.operation.endpointId : undefined,\n operationId:\n repeat.source.kind === 'operation' ? repeat.source.operation.operationId : undefined,\n code,\n message,\n severity: 'error',\n };\n}\n\nfunction readRepeatPrimitive(value: BindingValue, path: string): string | number | undefined {\n const resolved = path.split('.').reduce<unknown>((currentValue, part) => {\n if (typeof currentValue !== 'object' || currentValue === null || Array.isArray(currentValue)) {\n return undefined;\n }\n\n return (currentValue as Record<string, unknown>)[part];\n }, value);\n\n if (typeof resolved === 'string' || typeof resolved === 'number') {\n return resolved;\n }\n\n return undefined;\n}\n"]}
1
+ {"version":3,"file":"runtimeRepeat.js","sourceRoot":"","sources":["../src/runtimeRepeat.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,+BAA+B,EAC/B,mCAAmC,GAGpC,MAAM,mBAAmB,CAAC;AAgB3B,uFAAuF;AACvF,MAAM,UAAU,6BAA6B,CAC3C,MAAwB,EACxB,OAAuC;IAEvC,MAAM,WAAW,GAA2B,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,mCAAmC,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IACvF,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACnE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,0BAA0B,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC;IACxF,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AACvD,CAAC;AAED,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,MAAwB,EACxB,OAAuC;IAEvC,MAAM,WAAW,GAA2B,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,MAAM,+BAA+B,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IACzF,OAAO,0BAA0B,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;AAChE,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,iCAAiC,CAAC,IAIjD;IACC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;AAChF,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,2BAA2B,CAAC,IAK3C;IACC,OAAO,CACL,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;QACpD,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;QACpC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;QACxC,IAAI,CAAC,KAAK,CACX,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CACjC,MAAwB,EACxB,KAA+B,EAC/B,WAA4C;IAE5C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC/D,OAAO;QACL,WAAW,EAAE;YACX,GAAG,WAAW;YACd;gBACE,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,yCAAyC;gBAClD,QAAQ,EAAE,OAAO;aAClB;SACF;QACD,KAAK,EAAE,EAAE;KACV,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAmB,EAAE,IAAY;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAU,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;QACjE,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,OAAO,SAAS,CAAC;QAChG,OAAQ,OAAmC,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,OAAO,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7F,CAAC","sourcesContent":["import type {\n BindingValue,\n DataSourceDiagnostic,\n UiNode,\n UiNodeRepeatSpec,\n} from '@ankhorage/contracts';\n\nimport {\n resolveRuntimeBindingExpression,\n resolveRuntimeBindingExpressionSync,\n type RuntimeBindingResolutionContext,\n type RuntimeBindingResultWriter,\n} from './runtimeBindings';\n\nexport interface RuntimeRepeatResolutionContext extends RuntimeBindingResolutionContext {\n readonly node: UiNode;\n readonly writeResultSlot?: RuntimeBindingResultWriter;\n}\n\nexport interface RuntimeRepeatItemsResult {\n readonly items: readonly BindingValue[];\n readonly diagnostics: readonly DataSourceDiagnostic[];\n}\n\nexport interface RuntimeRepeatItemsSyncResult extends RuntimeRepeatItemsResult {\n readonly status: 'ready' | 'pending';\n}\n\n/*** Resolves an already materialized repeat expression for the current render pass. */\nexport function resolveRuntimeRepeatItemsSync(\n repeat: UiNodeRepeatSpec,\n context: RuntimeRepeatResolutionContext,\n): RuntimeRepeatItemsSyncResult {\n const diagnostics: DataSourceDiagnostic[] = [];\n const value = resolveRuntimeBindingExpressionSync(repeat.source, context, diagnostics);\n if (value !== undefined || context.executeCapability === undefined) {\n return { status: 'ready', ...finalizeRuntimeRepeatItems(repeat, value, diagnostics) };\n }\n return { status: 'pending', diagnostics, items: [] };\n}\n\n/*** Resolves a repeat expression asynchronously through the canonical capability executor. */\nexport async function resolveRuntimeRepeatItemsAsync(\n repeat: UiNodeRepeatSpec,\n context: RuntimeRepeatResolutionContext,\n): Promise<RuntimeRepeatItemsResult> {\n const diagnostics: DataSourceDiagnostic[] = [];\n const value = await resolveRuntimeBindingExpression(repeat.source, context, diagnostics);\n return finalizeRuntimeRepeatItems(repeat, value, diagnostics);\n}\n\n/*** Adds one repeat item under its configured alias without discarding outer context values. */\nexport function createRuntimeRepeatBindingContext(args: {\n readonly baseContext?: Record<string, unknown>;\n readonly item: BindingValue;\n readonly itemAlias?: string;\n}): Record<string, unknown> {\n return { ...(args.baseContext ?? {}), [args.itemAlias ?? 'item']: args.item };\n}\n\n/*** Selects a stable primitive key from the repeat item, falling back to its index. */\nexport function resolveRuntimeRepeatItemKey(args: {\n readonly item: BindingValue;\n readonly itemAlias?: string;\n readonly index: number;\n readonly keyPath?: string;\n}): string | number {\n return (\n readRepeatPrimitive(args.item, args.keyPath ?? 'id') ??\n readRepeatPrimitive(args.item, 'id') ??\n readRepeatPrimitive(args.item, 'itemId') ??\n args.index\n );\n}\n\nfunction finalizeRuntimeRepeatItems(\n repeat: UiNodeRepeatSpec,\n value: BindingValue | undefined,\n diagnostics: readonly DataSourceDiagnostic[],\n): RuntimeRepeatItemsResult {\n if (Array.isArray(value)) return { diagnostics, items: value };\n return {\n diagnostics: [\n ...diagnostics,\n {\n code: 'invalid-config',\n message: 'Repeat source must resolve to an array.',\n severity: 'error',\n },\n ],\n items: [],\n };\n}\n\nfunction readRepeatPrimitive(value: BindingValue, path: string): string | number | undefined {\n const resolved = path.split('.').reduce<unknown>((current, part) => {\n if (typeof current !== 'object' || current === null || Array.isArray(current)) return undefined;\n return (current as Record<string, unknown>)[part];\n }, value);\n return typeof resolved === 'string' || typeof resolved === 'number' ? resolved : undefined;\n}\n"]}
@@ -1,70 +1,55 @@
1
- import type { DataSourceDiagnostic, OperationScreenDataLoaderDefinition, ScreenSpec } from '@ankhorage/contracts';
2
- import { type RuntimeBindingOperationExecutor, type RuntimeBindingOperationResultCache, type RuntimeBindingResolutionContext } from './runtimeBindings';
1
+ import type { DataSourceDiagnostic, ScreenDataLoaderDefinition, ScreenSpec } from '@ankhorage/contracts';
2
+ import { type RuntimeBindingResultCache, type RuntimeCapabilityExecutor } from './runtimeBindings';
3
3
  export interface RuntimeScreenOperationLoaderState {
4
4
  readonly dependencyKey: string;
5
5
  readonly diagnostics: readonly DataSourceDiagnostic[];
6
- readonly operationResults: RuntimeBindingOperationResultCache;
6
+ readonly resultSlots: RuntimeBindingResultCache;
7
7
  readonly renderVersion: number;
8
8
  }
9
9
  export interface RuntimeScreenOperationLoaderExecutionResult {
10
10
  readonly dependencyKey: string;
11
11
  readonly diagnostics: readonly DataSourceDiagnostic[];
12
- readonly operationResults: RuntimeBindingOperationResultCache;
12
+ readonly resultSlots: RuntimeBindingResultCache;
13
13
  }
14
- export interface RuntimeScreenOperationLoaderLifecycle {
15
- readonly activeRequestId: number;
16
- readonly activeRequestKey: string | null;
14
+ interface RuntimeScreenOperationLoaderRequestLifecycle {
15
+ invalidate(): void;
16
+ start(dependencyKey: string): number | undefined;
17
+ isCurrent(args: {
18
+ readonly dependencyKey: string;
19
+ readonly requestId: number;
20
+ }): boolean;
17
21
  }
18
- export declare function resolveScreenOperationLoaders(screen: ScreenSpec): readonly OperationScreenDataLoaderDefinition[];
22
+ /*** Tracks one active screen-loader request per effective dependency key. */
23
+ export declare function createRuntimeScreenOperationLoaderRequestLifecycle(): RuntimeScreenOperationLoaderRequestLifecycle;
24
+ /*** Returns the portable capability invocations authored on a screen. */
25
+ export declare function resolveScreenOperationLoaders(screen: ScreenSpec): readonly ScreenDataLoaderDefinition[];
26
+ /*** Creates a deterministic loader request key from resolved inputs and declared result slots. */
19
27
  export declare function createRuntimeScreenLoaderRequestKey(args: {
20
28
  readonly screenId: string;
21
- readonly loaders: readonly OperationScreenDataLoaderDefinition[];
29
+ readonly loaders: readonly ScreenDataLoaderDefinition[];
22
30
  readonly bindingContext?: Record<string, unknown>;
23
- readonly operationResults?: RuntimeBindingOperationResultCache;
31
+ readonly resultSlots?: RuntimeBindingResultCache;
24
32
  }): string;
25
- export declare function createRuntimeScreenOperationLoaderLifecycle(): RuntimeScreenOperationLoaderLifecycle;
26
- export declare function createIdleRuntimeScreenOperationLoaderState(args: {
27
- readonly dependencyKey: string;
28
- readonly previousState?: RuntimeScreenOperationLoaderState;
29
- }): RuntimeScreenOperationLoaderState;
33
+ /*** Constructs a pending state for capability-backed screen loaders. */
30
34
  export declare function createPendingRuntimeScreenOperationLoaderState(args: {
31
35
  readonly dependencyKey: string;
32
36
  readonly previousState?: RuntimeScreenOperationLoaderState;
33
37
  }): RuntimeScreenOperationLoaderState;
34
- export declare function beginRuntimeScreenOperationLoaderRequest(args: {
35
- readonly hasLoaders: boolean;
36
- readonly lifecycle: RuntimeScreenOperationLoaderLifecycle;
37
- readonly requestKey: string;
38
- readonly state: RuntimeScreenOperationLoaderState;
39
- }): {
40
- readonly lifecycle: RuntimeScreenOperationLoaderLifecycle;
41
- readonly requestId?: number;
42
- readonly shouldExecute: boolean;
43
- readonly state: RuntimeScreenOperationLoaderState;
44
- };
45
- export declare function completeRuntimeScreenOperationLoaderRequest(args: {
46
- readonly lifecycle: RuntimeScreenOperationLoaderLifecycle;
47
- readonly requestId: number;
48
- readonly result: RuntimeScreenOperationLoaderExecutionResult;
49
- readonly state: RuntimeScreenOperationLoaderState;
50
- }): {
51
- readonly accepted: boolean;
52
- readonly state: RuntimeScreenOperationLoaderState;
53
- };
38
+ /*** Executes screen loaders through the same invocation and result-slot machinery as events. */
54
39
  export declare function executeRuntimeScreenOperationLoaders(args: {
55
40
  readonly bindingContext?: Record<string, unknown>;
56
- readonly apis?: RuntimeBindingResolutionContext['apis'];
57
- readonly executeOperation?: RuntimeBindingOperationExecutor;
58
- readonly operationResults?: RuntimeBindingOperationResultCache;
41
+ readonly executeCapability?: RuntimeCapabilityExecutor;
42
+ readonly resultSlots?: RuntimeBindingResultCache;
59
43
  readonly screen: ScreenSpec;
60
- readonly loaders: readonly OperationScreenDataLoaderDefinition[];
44
+ readonly loaders: readonly ScreenDataLoaderDefinition[];
61
45
  }): Promise<RuntimeScreenOperationLoaderExecutionResult>;
46
+ /*** Runs screen capability invocations when their serialized request input changes. */
62
47
  export declare function useRuntimeScreenOperationLoaders(args: {
63
48
  readonly bindingContext?: Record<string, unknown>;
64
- readonly apis?: RuntimeBindingResolutionContext['apis'];
65
- readonly executeOperation?: RuntimeBindingOperationExecutor;
66
- readonly operationResults?: RuntimeBindingOperationResultCache;
49
+ readonly executeCapability?: RuntimeCapabilityExecutor;
50
+ readonly resultSlots?: RuntimeBindingResultCache;
67
51
  readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void;
68
52
  readonly screen: ScreenSpec;
69
53
  }): RuntimeScreenOperationLoaderState;
54
+ export {};
70
55
  //# sourceMappingURL=runtimeScreenLoaders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtimeScreenLoaders.d.ts","sourceRoot":"","sources":["../src/runtimeScreenLoaders.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtimeScreenLoaders.d.ts","sourceRoot":"","sources":["../src/runtimeScreenLoaders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,oBAAoB,EACpB,0BAA0B,EAC1B,UAAU,EACX,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAGL,KAAK,yBAAyB,EAE9B,KAAK,yBAAyB,EAC/B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACtD,QAAQ,CAAC,WAAW,EAAE,yBAAyB,CAAC;IAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,2CAA2C;IAC1D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACtD,QAAQ,CAAC,WAAW,EAAE,yBAAyB,CAAC;CACjD;AAED,UAAU,4CAA4C;IACpD,UAAU,IAAI,IAAI,CAAC;IACnB,KAAK,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACjD,SAAS,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;CAC1F;AAED,6EAA6E;AAC7E,wBAAgB,kDAAkD,IAAI,4CAA4C,CAkBjH;AAED,yEAAyE;AACzE,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,UAAU,GACjB,SAAS,0BAA0B,EAAE,CAEvC;AAED,kGAAkG;AAClG,wBAAgB,mCAAmC,CAAC,IAAI,EAAE;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACxD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClD,QAAQ,CAAC,WAAW,CAAC,EAAE,yBAAyB,CAAC;CAClD,GAAG,MAAM,CAYT;AAED,wEAAwE;AACxE,wBAAgB,8CAA8C,CAAC,IAAI,EAAE;IACnE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,iCAAiC,CAAC;CAC5D,GAAG,iCAAiC,CAOpC;AAED,gGAAgG;AAChG,wBAAsB,oCAAoC,CAAC,IAAI,EAAE;IAC/D,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,yBAAyB,CAAC;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,0BAA0B,EAAE,CAAC;CACzD,GAAG,OAAO,CAAC,2CAA2C,CAAC,CAuCvD;AAED,uFAAuF;AACvF,wBAAgB,gCAAgC,CAAC,IAAI,EAAE;IACrD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,yBAAyB,CAAC;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACjD,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,KAAK,IAAI,CAAC;IAChF,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B,GAAG,iCAAiC,CAiEpC"}
@@ -1,303 +1,143 @@
1
1
  import React from 'react';
2
- import { resolveRuntimeBindingOperationSelection } from './runtimeApiSelection';
3
- import { createRuntimeBindingOperationKey, resolveBindingInputMapSync, } from './runtimeBindings';
4
- const EMPTY_RUNTIME_SCREEN_OPERATION_LOADER_DIAGNOSTICS = Object.freeze([]);
5
- const EMPTY_RUNTIME_SCREEN_OPERATION_RESULTS = Object.freeze({});
2
+ import { executeRuntimeBindingInvocation, resolveBindingInputMapSync, } from './runtimeBindings';
3
+ /*** Tracks one active screen-loader request per effective dependency key. */
4
+ export function createRuntimeScreenOperationLoaderRequestLifecycle() {
5
+ let dependencyKey;
6
+ let requestId = 0;
7
+ return {
8
+ invalidate() {
9
+ requestId += 1;
10
+ },
11
+ start(nextDependencyKey) {
12
+ if (nextDependencyKey === dependencyKey)
13
+ return undefined;
14
+ dependencyKey = nextDependencyKey;
15
+ requestId += 1;
16
+ return requestId;
17
+ },
18
+ isCurrent(args) {
19
+ return args.dependencyKey === dependencyKey && args.requestId === requestId;
20
+ },
21
+ };
22
+ }
23
+ /*** Returns the portable capability invocations authored on a screen. */
6
24
  export function resolveScreenOperationLoaders(screen) {
7
25
  return screen.dataLoaders ?? [];
8
26
  }
27
+ /*** Creates a deterministic loader request key from resolved inputs and declared result slots. */
9
28
  export function createRuntimeScreenLoaderRequestKey(args) {
10
- return createRuntimeScreenOperationLoaderPlan({
11
- bindingContext: args.bindingContext,
12
- loaders: args.loaders,
13
- operationResults: args.operationResults,
29
+ return stableSerialize({
30
+ loaders: args.loaders.map((loader) => ({
31
+ capability: loader.capability,
32
+ input: resolveBindingInputMapSync(loader.input, {
33
+ context: args.bindingContext,
34
+ resultSlots: args.resultSlots,
35
+ }),
36
+ result: loader.result,
37
+ })),
14
38
  screenId: args.screenId,
15
- }).requestKey;
16
- }
17
- export function createRuntimeScreenOperationLoaderLifecycle() {
18
- return {
19
- activeRequestId: 0,
20
- activeRequestKey: null,
21
- };
22
- }
23
- export function createIdleRuntimeScreenOperationLoaderState(args) {
24
- return {
25
- dependencyKey: args.dependencyKey,
26
- diagnostics: EMPTY_RUNTIME_SCREEN_OPERATION_LOADER_DIAGNOSTICS,
27
- operationResults: EMPTY_RUNTIME_SCREEN_OPERATION_RESULTS,
28
- renderVersion: args.previousState?.renderVersion ?? 0,
29
- };
39
+ });
30
40
  }
41
+ /*** Constructs a pending state for capability-backed screen loaders. */
31
42
  export function createPendingRuntimeScreenOperationLoaderState(args) {
32
43
  return {
33
44
  dependencyKey: args.dependencyKey,
34
45
  diagnostics: [],
35
- operationResults: {},
46
+ resultSlots: {},
36
47
  renderVersion: (args.previousState?.renderVersion ?? -1) + 1,
37
48
  };
38
49
  }
39
- export function beginRuntimeScreenOperationLoaderRequest(args) {
40
- if (!args.hasLoaders) {
41
- if (args.lifecycle.activeRequestKey === null) {
42
- return {
43
- lifecycle: args.lifecycle,
44
- shouldExecute: false,
45
- state: args.state,
46
- };
47
- }
48
- return {
49
- lifecycle: {
50
- activeRequestId: args.lifecycle.activeRequestId + 1,
51
- activeRequestKey: null,
52
- },
53
- shouldExecute: false,
54
- state: args.state,
55
- };
56
- }
57
- if (args.lifecycle.activeRequestKey === args.requestKey) {
58
- return {
59
- lifecycle: args.lifecycle,
60
- shouldExecute: false,
61
- state: args.state,
62
- };
63
- }
64
- const requestId = args.lifecycle.activeRequestId + 1;
65
- return {
66
- lifecycle: {
67
- activeRequestId: requestId,
68
- activeRequestKey: args.requestKey,
69
- },
70
- requestId,
71
- shouldExecute: true,
72
- state: args.state.dependencyKey === args.requestKey
73
- ? args.state
74
- : createPendingRuntimeScreenOperationLoaderState({
75
- dependencyKey: args.requestKey,
76
- previousState: args.state,
77
- }),
50
+ /*** Executes screen loaders through the same invocation and result-slot machinery as events. */
51
+ export async function executeRuntimeScreenOperationLoaders(args) {
52
+ const resultSlots = { ...(args.resultSlots ?? {}) };
53
+ const diagnostics = [];
54
+ const writeResultSlot = (slot, value) => {
55
+ resultSlots[slot] = value;
78
56
  };
79
- }
80
- export function completeRuntimeScreenOperationLoaderRequest(args) {
81
- if (args.lifecycle.activeRequestId !== args.requestId) {
82
- return {
83
- accepted: false,
84
- state: args.state,
85
- };
57
+ for (const loader of args.loaders) {
58
+ try {
59
+ await executeRuntimeBindingInvocation(loader, {
60
+ context: args.bindingContext,
61
+ executeCapability: args.executeCapability,
62
+ resultSlots,
63
+ writeResultSlot,
64
+ }, { node: args.screen.root }, diagnostics);
65
+ }
66
+ catch {
67
+ diagnostics.push({
68
+ code: 'adapter-error',
69
+ message: `Capability '${loader.capability}' could not be completed. Please try again.`,
70
+ severity: 'error',
71
+ });
72
+ }
86
73
  }
87
74
  return {
88
- accepted: true,
89
- state: {
90
- dependencyKey: args.result.dependencyKey,
91
- diagnostics: args.result.diagnostics,
92
- operationResults: args.result.operationResults,
93
- renderVersion: args.state.renderVersion,
94
- },
75
+ dependencyKey: createRuntimeScreenLoaderRequestKey({
76
+ bindingContext: args.bindingContext,
77
+ loaders: args.loaders,
78
+ resultSlots: args.resultSlots,
79
+ screenId: args.screen.id,
80
+ }),
81
+ diagnostics,
82
+ resultSlots,
95
83
  };
96
84
  }
97
- export async function executeRuntimeScreenOperationLoaders(args) {
98
- const plan = createRuntimeScreenOperationLoaderPlan({
99
- bindingContext: args.bindingContext,
100
- loaders: args.loaders,
101
- operationResults: args.operationResults,
102
- screenId: args.screen.id,
103
- });
104
- return executePreparedRuntimeScreenOperationLoaders({
105
- apis: args.apis,
106
- executeOperation: args.executeOperation,
107
- plan,
108
- screen: args.screen,
109
- });
110
- }
111
- function executePreparedRuntimeScreenOperationLoaders(args) {
112
- const diagnostics = [...args.plan.diagnostics];
113
- if (args.plan.loaders.length === 0) {
114
- return Promise.resolve({
115
- dependencyKey: args.plan.requestKey,
116
- diagnostics,
117
- operationResults: {},
118
- });
119
- }
120
- if (args.executeOperation === undefined) {
121
- diagnostics.push(...args.plan.loaders.map((preparedLoader) => createScreenOperationLoaderDiagnostic(preparedLoader.loader, 'missing-adapter', 'Screen API operation loader requires an injected operation executor.')));
122
- return Promise.resolve({
123
- dependencyKey: args.plan.requestKey,
124
- diagnostics,
125
- operationResults: {},
126
- });
127
- }
128
- const { executeOperation } = args;
129
- return (async () => {
130
- const operationResults = {};
131
- for (const preparedLoader of args.plan.loaders) {
132
- const selection = resolveRuntimeBindingOperationSelection(preparedLoader.loader.operation, args.apis, diagnostics);
133
- if (selection === undefined) {
134
- continue;
135
- }
136
- const result = await executeOperation({
137
- api: selection.api,
138
- endpoint: selection.endpoint,
139
- input: preparedLoader.input,
140
- node: args.screen.root,
141
- operation: preparedLoader.loader.operation,
142
- });
143
- diagnostics.push(...(result.diagnostics ?? []));
144
- if (!result.ok) {
145
- continue;
146
- }
147
- operationResults[preparedLoader.operationKey] = result.data;
148
- }
149
- return {
150
- dependencyKey: args.plan.requestKey,
151
- diagnostics,
152
- operationResults,
153
- };
154
- })();
155
- }
85
+ /*** Runs screen capability invocations when their serialized request input changes. */
156
86
  export function useRuntimeScreenOperationLoaders(args) {
157
- const { apis, bindingContext, executeOperation, onDiagnostics, operationResults, screen } = args;
158
- const loaders = React.useMemo(() => resolveScreenOperationLoaders(screen), [screen]);
159
- const hasLoaders = loaders.length > 0;
160
- const plan = React.useMemo(() => createRuntimeScreenOperationLoaderPlan({
161
- bindingContext,
87
+ const { onDiagnostics } = args;
88
+ const loaders = React.useMemo(() => resolveScreenOperationLoaders(args.screen), [args.screen]);
89
+ const dependencyKey = React.useMemo(() => createRuntimeScreenLoaderRequestKey({
90
+ bindingContext: args.bindingContext,
162
91
  loaders,
163
- operationResults,
164
- screenId: screen.id,
165
- }), [bindingContext, loaders, operationResults, screen.id]);
166
- const { requestKey } = plan;
167
- const emptyState = React.useMemo(() => createIdleRuntimeScreenOperationLoaderState({
168
- dependencyKey: requestKey,
169
- }), [requestKey]);
170
- const [state, setState] = React.useState(() => hasLoaders
171
- ? createPendingRuntimeScreenOperationLoaderState({ dependencyKey: requestKey })
172
- : emptyState);
173
- const pendingState = React.useMemo(() => state.dependencyKey === requestKey
174
- ? state
175
- : createPendingRuntimeScreenOperationLoaderState({
176
- dependencyKey: requestKey,
177
- previousState: state,
178
- }), [requestKey, state]);
179
- const effectiveState = hasLoaders ? pendingState : emptyState;
180
- const lastDiagnosticsKeyRef = React.useRef(null);
181
- const lifecycleRef = React.useRef(createRuntimeScreenOperationLoaderLifecycle());
182
- React.useEffect(() => {
183
- const request = beginRuntimeScreenOperationLoaderRequest({
184
- hasLoaders,
185
- lifecycle: lifecycleRef.current,
186
- requestKey,
187
- state,
188
- });
189
- lifecycleRef.current = request.lifecycle;
190
- if (!request.shouldExecute || request.requestId === undefined) {
191
- return;
192
- }
193
- const { requestId } = request;
194
- void (async () => {
195
- const result = await executePreparedRuntimeScreenOperationLoaders({
196
- apis,
197
- executeOperation,
198
- plan,
199
- screen,
200
- });
201
- setState((currentState) => {
202
- const completion = completeRuntimeScreenOperationLoaderRequest({
203
- lifecycle: lifecycleRef.current,
204
- requestId,
205
- result,
206
- state: currentState.dependencyKey === requestKey ? currentState : request.state,
207
- });
208
- return completion.accepted ? completion.state : currentState;
209
- });
210
- })();
211
- }, [apis, executeOperation, hasLoaders, plan, requestKey, screen, state]);
92
+ resultSlots: args.resultSlots,
93
+ screenId: args.screen.id,
94
+ }), [args.bindingContext, args.resultSlots, args.screen.id, loaders]);
95
+ const [state, setState] = React.useState(() => createPendingRuntimeScreenOperationLoaderState({ dependencyKey }));
96
+ const requestLifecycle = React.useRef(createRuntimeScreenOperationLoaderRequestLifecycle());
212
97
  React.useEffect(() => {
213
- if (effectiveState.diagnostics.length === 0) {
98
+ if (loaders.length === 0) {
99
+ requestLifecycle.current.invalidate();
214
100
  return;
215
101
  }
216
- const diagnosticsKey = stableSerialize(effectiveState.diagnostics);
217
- if (lastDiagnosticsKeyRef.current === diagnosticsKey) {
102
+ const requestId = requestLifecycle.current.start(dependencyKey);
103
+ if (requestId === undefined)
218
104
  return;
219
- }
220
- lastDiagnosticsKeyRef.current = diagnosticsKey;
221
- onDiagnostics?.(effectiveState.diagnostics);
222
- }, [effectiveState.diagnostics, onDiagnostics]);
223
- return effectiveState;
224
- }
225
- function createRuntimeScreenOperationLoaderPlan(args) {
226
- if (args.loaders.length === 0) {
227
- return {
228
- diagnostics: EMPTY_RUNTIME_SCREEN_OPERATION_LOADER_DIAGNOSTICS,
229
- loaders: [],
230
- requestKey: createRuntimeScreenOperationLoaderIdleKey(args.screenId),
231
- };
232
- }
233
- const diagnostics = [];
234
- const preparedLoaders = [];
235
- const operationKeys = new Set();
236
- for (const loader of args.loaders) {
237
- const input = resolveBindingInputMapSync(loader.input, {
238
- context: args.bindingContext,
239
- operationResults: args.operationResults,
240
- }, diagnostics);
241
- const operationKey = createRuntimeBindingOperationKey(loader.operation);
242
- if (operationKeys.has(operationKey)) {
243
- diagnostics.push(createScreenOperationLoaderDiagnostic(loader, 'duplicate-operation-id', `Screen operation loaders must not reuse operation key '${operationKey}' on the same screen.`));
244
- continue;
245
- }
246
- operationKeys.add(operationKey);
247
- preparedLoaders.push({
248
- input,
249
- loader,
250
- operationKey,
105
+ void executeRuntimeScreenOperationLoaders({
106
+ bindingContext: args.bindingContext,
107
+ executeCapability: args.executeCapability,
108
+ loaders,
109
+ resultSlots: args.resultSlots,
110
+ screen: args.screen,
111
+ }).then((result) => {
112
+ if (requestLifecycle.current.isCurrent({ dependencyKey, requestId })) {
113
+ setState((current) => ({
114
+ ...result,
115
+ renderVersion: current.dependencyKey === dependencyKey
116
+ ? current.renderVersion
117
+ : current.renderVersion + 1,
118
+ }));
119
+ }
251
120
  });
252
- }
253
- return {
254
- diagnostics,
255
- loaders: preparedLoaders,
256
- requestKey: createRuntimeScreenOperationLoaderPlanRequestKey({
257
- loaders: preparedLoaders,
258
- screenId: args.screenId,
259
- }),
260
- };
261
- }
262
- function createRuntimeScreenOperationLoaderPlanRequestKey(args) {
263
- return stableSerialize({
264
- loaders: args.loaders.map((loader) => ({
265
- id: loader.loader.id,
266
- input: loader.input,
267
- operation: loader.loader.operation,
268
- operationKey: loader.operationKey,
269
- })),
270
- screenId: args.screenId,
271
- });
272
- }
273
- function createScreenOperationLoaderDiagnostic(loader, code, message) {
274
- return {
275
- apiId: loader.operation.apiId,
276
- code,
277
- endpointId: loader.operation.endpointId,
278
- operationId: loader.operation.operationId,
279
- message,
280
- severity: 'error',
281
- };
282
- }
283
- function createRuntimeScreenOperationLoaderIdleKey(screenId) {
284
- return `screen:${screenId}:no-operation-loaders`;
121
+ }, [
122
+ args.bindingContext,
123
+ args.executeCapability,
124
+ args.resultSlots,
125
+ args.screen,
126
+ dependencyKey,
127
+ loaders,
128
+ ]);
129
+ React.useEffect(() => () => {
130
+ requestLifecycle.current.invalidate();
131
+ }, []);
132
+ React.useEffect(() => {
133
+ if (state.diagnostics.length > 0)
134
+ onDiagnostics?.(state.diagnostics);
135
+ }, [onDiagnostics, state.diagnostics]);
136
+ return state.dependencyKey === dependencyKey
137
+ ? state
138
+ : createPendingRuntimeScreenOperationLoaderState({ dependencyKey, previousState: state });
285
139
  }
286
140
  function stableSerialize(value) {
287
- return JSON.stringify(sortSerializableValue(value));
288
- }
289
- function sortSerializableValue(value) {
290
- if (Array.isArray(value)) {
291
- return value.map(sortSerializableValue);
292
- }
293
- if (typeof value !== 'object' || value === null) {
294
- return value;
295
- }
296
- return Object.keys(value)
297
- .sort((left, right) => left.localeCompare(right))
298
- .reduce((result, key) => {
299
- result[key] = sortSerializableValue(value[key]);
300
- return result;
301
- }, {});
141
+ return JSON.stringify(value);
302
142
  }
303
143
  //# sourceMappingURL=runtimeScreenLoaders.js.map