From 24be013ae77edb45f1d5c1da26dcdaf6b5ed4102 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:37:26 +0200 Subject: [PATCH 01/43] chore: consume canonical API releases --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 91addf0..a52541d 100644 --- a/package.json +++ b/package.json @@ -60,8 +60,8 @@ "version-packages": "changeset version" }, "dependencies": { - "@ankhorage/contracts": "^7.4.0", - "@ankhorage/data-sources": "^1.0.0" + "@ankhorage/contracts": "^8.0.0", + "@ankhorage/data-sources": "^2.0.0" }, "peerDependencies": { "react": "19.1.0", From bf1d0fb584a94666154027bfaef1583c23efb6a4 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:37:39 +0200 Subject: [PATCH 02/43] feat: resolve canonical runtime APIs --- src/runtimeApiSelection.ts | 95 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/runtimeApiSelection.ts diff --git a/src/runtimeApiSelection.ts b/src/runtimeApiSelection.ts new file mode 100644 index 0000000..c101b71 --- /dev/null +++ b/src/runtimeApiSelection.ts @@ -0,0 +1,95 @@ +import type { + ApiDefinition, + ApiDefinitionList, + BindingOperationRef, + DataEndpointConfig, + DataSourceDiagnostic, +} from '@ankhorage/contracts'; + +export interface RuntimeApiOperationSelection { + readonly api: ApiDefinition; + readonly endpoint: DataEndpointConfig; +} + +export function validateRuntimeBindingOperationRef( + operation: BindingOperationRef, + apis: ApiDefinitionList | undefined, +): readonly DataSourceDiagnostic[] { + const api = findRuntimeApi(apis, operation.apiId); + if (api === undefined) { + return [createApiDiagnostic(operation, 'missing-api', `API '${operation.apiId}' could not be found.`)]; + } + + const endpoint = resolveRuntimeApiEndpoint(operation, api); + if (endpoint === undefined) { + return [ + createApiDiagnostic( + operation, + 'missing-endpoint', + `Endpoint '${operation.endpointId ?? ''}' could not be found.`, + ), + ]; + } + + if (endpoint.operations[operation.operationId] === undefined) { + return [ + createApiDiagnostic( + operation, + 'missing-operation', + `Operation '${operation.operationId}' could not be found.`, + endpoint.id, + ), + ]; + } + + return []; +} + +export function resolveRuntimeBindingOperationSelection( + operation: BindingOperationRef, + apis: ApiDefinitionList | undefined, + diagnostics: DataSourceDiagnostic[], +): RuntimeApiOperationSelection | undefined { + const validationDiagnostics = validateRuntimeBindingOperationRef(operation, apis); + diagnostics.push(...validationDiagnostics); + if (validationDiagnostics.length > 0) return undefined; + + const api = findRuntimeApi(apis, operation.apiId); + if (api === undefined) return undefined; + const endpoint = resolveRuntimeApiEndpoint(operation, api); + return endpoint === undefined ? undefined : { api, endpoint }; +} + +function findRuntimeApi( + apis: ApiDefinitionList | undefined, + apiId: string, +): ApiDefinition | undefined { + return apis?.find((api) => api.id === apiId); +} + +function resolveRuntimeApiEndpoint( + operation: BindingOperationRef, + api: ApiDefinition, +): DataEndpointConfig | undefined { + if (operation.endpointId !== undefined) return api.endpoints[operation.endpointId]; + + return Object.values(api.endpoints).find( + (endpoint) => endpoint.operations[operation.operationId] !== undefined, + ); +} + +function createApiDiagnostic( + operation: BindingOperationRef, + code: DataSourceDiagnostic['code'], + message: string, + endpointId = operation.endpointId, +): DataSourceDiagnostic { + return { + apiId: operation.apiId, + code, + endpointId, + message, + operationId: operation.operationId, + severity: 'error', + }; +} From 2388c64ebb4c0e00fbe104959aac3ac4d17acf40 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:37:50 +0200 Subject: [PATCH 03/43] feat: execute runtime API operations through data sources --- src/runtimeApiOperations.ts | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/runtimeApiOperations.ts diff --git a/src/runtimeApiOperations.ts b/src/runtimeApiOperations.ts new file mode 100644 index 0000000..a23b1da --- /dev/null +++ b/src/runtimeApiOperations.ts @@ -0,0 +1,58 @@ +import type { BindingValue, DataSourceDiagnostic } from '@ankhorage/contracts'; +import type { EndpointTestCredentialResolver, EndpointTestFetch } from '@ankhorage/data-sources'; +import { testEndpoint } from '@ankhorage/data-sources'; + +import type { RuntimeBindingOperationExecutor } from './runtimeBindings'; + +export interface RuntimeApiOperationExecutorOptions { + readonly fetch?: EndpointTestFetch; + readonly credentialResolver?: EndpointTestCredentialResolver; +} + +export function createRuntimeApiOperationExecutor( + options: RuntimeApiOperationExecutorOptions, +): RuntimeBindingOperationExecutor { + return async ({ api, endpoint, input, operation }) => { + const values = asBindingValueRecord(input); + if (input !== undefined && values === undefined) { + return invalidInput(operation.apiId, endpoint.id, operation.operationId); + } + + const result = await testEndpoint({ + api, + credentialResolver: options.credentialResolver, + endpointId: endpoint.id, + fetch: options.fetch, + operationId: operation.operationId, + values, + }); + + return result.ok + ? { ok: true, data: result.data ?? null, diagnostics: result.diagnostics } + : { ok: false, diagnostics: result.diagnostics }; + }; +} + +function invalidInput(apiId: string, endpointId: string, operationId: string) { + const diagnostic: DataSourceDiagnostic = { + apiId, + code: 'invalid-config', + endpointId, + message: 'API operation input must resolve to an object.', + operationId, + severity: 'error', + }; + return { ok: false as const, diagnostics: [diagnostic] }; +} + +function asBindingValueRecord( + value: BindingValue | undefined, +): Readonly> | undefined { + return isBindingValueRecord(value) ? value : undefined; +} + +function isBindingValueRecord( + value: BindingValue | undefined, +): value is Readonly> { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} From 06b8f39e21d5b8db88abe313605e1fd2661b6cb2 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:38:28 +0200 Subject: [PATCH 04/43] feat: bind runtime operations by canonical API --- src/runtimeBindings.ts | 131 ++++++++++------------------------------- 1 file changed, 30 insertions(+), 101 deletions(-) diff --git a/src/runtimeBindings.ts b/src/runtimeBindings.ts index 9b39332..ba6db23 100644 --- a/src/runtimeBindings.ts +++ b/src/runtimeBindings.ts @@ -1,4 +1,6 @@ import type { + ApiDefinition, + ApiDefinitionList, BindingFallback, BindingInputMap, BindingInputValue, @@ -9,20 +11,20 @@ import type { ComponentDataBindingRegistry, ComponentEventDto, DataEndpointConfig, - DataSourceConfig, DataSourceDiagnostic, - DataSourceRegistry, PropBinding, StateAdapter, UiNode, } from '@ankhorage/contracts'; +import { resolveRuntimeBindingOperationSelection } from './runtimeApiSelection'; + export type RuntimeBindingOperationKey = string; export interface RuntimeBindingOperationExecutionArgs { readonly operation: BindingOperationRef; - readonly dataSource: DataSourceConfig; - readonly endpoint?: DataEndpointConfig; + readonly api: ApiDefinition; + readonly endpoint: DataEndpointConfig; readonly input?: BindingValue; readonly node?: UiNode; } @@ -55,7 +57,7 @@ export interface RuntimeBindingResolutionContext { readonly context?: Record; readonly event?: ComponentEventDto; readonly stateAdapter?: StateAdapter; - readonly dataSources?: DataSourceRegistry; + readonly apis?: ApiDefinitionList; readonly dataBindings?: ComponentDataBindingRegistry; readonly operationResults?: RuntimeBindingOperationResultCache; readonly executeOperation?: RuntimeBindingOperationExecutor; @@ -163,49 +165,7 @@ export function resolveBindingInputMapSync( export function createRuntimeBindingOperationKey( operation: BindingOperationRef, ): RuntimeBindingOperationKey { - return [operation.dataSourceId, operation.endpointId ?? '', operation.operationId].join(':'); -} - -export function validateRuntimeBindingOperationRef( - operation: BindingOperationRef, - dataSources: DataSourceRegistry | undefined, -): readonly DataSourceDiagnostic[] { - const dataSource = dataSources?.[operation.dataSourceId]; - if (dataSource === undefined) { - return [ - createRuntimeBindingDiagnostic({ - code: 'missing-data-source', - message: `Data source '${operation.dataSourceId}' could not be found.`, - operation, - }), - ]; - } - - const endpoint = resolveRuntimeBindingEndpoint(operation, dataSource); - if (endpoint === undefined) { - return [ - createRuntimeBindingDiagnostic({ - code: 'missing-endpoint', - dataSourceId: operation.dataSourceId, - message: `Endpoint '${operation.endpointId ?? ''}' could not be found.`, - operation, - }), - ]; - } - - if (endpoint.operations[operation.operationId] === undefined) { - return [ - createRuntimeBindingDiagnostic({ - code: 'missing-operation', - dataSourceId: operation.dataSourceId, - endpointId: endpoint.id, - message: `Operation '${operation.operationId}' could not be found.`, - operation, - }), - ]; - } - - return []; + return [operation.apiId, operation.endpointId ?? '', operation.operationId].join(':'); } async function resolveRuntimeBindingValueSource( @@ -222,26 +182,26 @@ async function resolveRuntimeBindingValueSource( if (context.executeOperation === undefined) { diagnostics.push( - createRuntimeBindingDiagnostic({ - code: 'missing-adapter', - message: 'Operation binding requires an injected operation executor.', - operation: source.operation, - }), + createRuntimeBindingDiagnostic( + source.operation, + 'missing-adapter', + 'API operation binding requires an injected operation executor.', + ), ); return undefined; } const selection = resolveRuntimeBindingOperationSelection( source.operation, - context.dataSources, + context.apis, diagnostics, ); if (selection === undefined) return undefined; const result = await context.executeOperation({ - operation: source.operation, - dataSource: selection.dataSource, + api: selection.api, endpoint: selection.endpoint, + operation: source.operation, }); diagnostics.push(...(result.diagnostics ?? [])); @@ -266,11 +226,11 @@ export function resolveRuntimeBindingValueSourceSync( const cached = resolveCachedOperationValue(source, context); if (cached !== undefined) return cached; diagnostics.push( - createRuntimeBindingDiagnostic({ - code: 'missing-adapter', - message: 'Synchronous operation bindings require preloaded operation results.', - operation: source.operation, - }), + createRuntimeBindingDiagnostic( + source.operation, + 'missing-adapter', + 'Synchronous API operation bindings require preloaded operation results.', + ), ); return undefined; } @@ -379,48 +339,17 @@ function resolveBindingInputValueSync( return fields; } -export function resolveRuntimeBindingOperationSelection( +function createRuntimeBindingDiagnostic( operation: BindingOperationRef, - dataSources: DataSourceRegistry | undefined, - diagnostics: DataSourceDiagnostic[], -): { readonly dataSource: DataSourceConfig; readonly endpoint?: DataEndpointConfig } | undefined { - const validationDiagnostics = validateRuntimeBindingOperationRef(operation, dataSources); - diagnostics.push(...validationDiagnostics); - if (validationDiagnostics.length > 0) return undefined; - - const dataSource = dataSources?.[operation.dataSourceId]; - if (dataSource === undefined) return undefined; - - return { - dataSource, - endpoint: resolveRuntimeBindingEndpoint(operation, dataSource), - }; -} - -function resolveRuntimeBindingEndpoint( - operation: BindingOperationRef, - dataSource: DataSourceConfig, -): DataEndpointConfig | undefined { - if (operation.endpointId !== undefined) return dataSource.endpoints[operation.endpointId]; - - return Object.values(dataSource.endpoints).find( - (endpoint) => endpoint.operations[operation.operationId] !== undefined, - ); -} - -function createRuntimeBindingDiagnostic(args: { - readonly code: DataSourceDiagnostic['code']; - readonly message: string; - readonly operation: BindingOperationRef; - readonly dataSourceId?: string; - readonly endpointId?: string; -}): DataSourceDiagnostic { + code: DataSourceDiagnostic['code'], + message: string, +): DataSourceDiagnostic { return { - code: args.code, - dataSourceId: args.dataSourceId ?? args.operation.dataSourceId, - endpointId: args.endpointId ?? args.operation.endpointId, - operationId: args.operation.operationId, - message: args.message, + apiId: operation.apiId, + code, + endpointId: operation.endpointId, + message, + operationId: operation.operationId, severity: 'error', }; } From 7f609e540a27ac6d1913934025ea5824e2b3239d Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:38:47 +0200 Subject: [PATCH 05/43] refactor: pass canonical APIs to node bindings --- src/runtimeNodeProps.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtimeNodeProps.ts b/src/runtimeNodeProps.ts index 5af2f58..8bacb47 100644 --- a/src/runtimeNodeProps.ts +++ b/src/runtimeNodeProps.ts @@ -1,6 +1,6 @@ import type { + ApiDefinitionList, ComponentDataBindingRegistry, - DataSourceRegistry, DbAdapter, DbRealtimeAdapter, StateAdapter, @@ -86,7 +86,7 @@ export function resolveRuntimeNodeProps(args: { dbAdapter?: DbAdapter; dbRealtimeAdapter?: DbRealtimeAdapter; bindingContext?: Record; - dataSources?: DataSourceRegistry; + apis?: ApiDefinitionList; dataBindings?: ComponentDataBindingRegistry; operationResults?: RuntimeBindingOperationResultCache; }): Record { @@ -108,9 +108,9 @@ export function resolveRuntimeNodeProps(args: { } const bindingResult = resolveRuntimeBindings({ + apis: args.apis, context: args.bindingContext, dataBindings: args.dataBindings, - dataSources: args.dataSources, node, operationResults: args.operationResults, props: baseProps, From 6e22d60d31d454085ed8f382fb36ea4e97e93281 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:39:03 +0200 Subject: [PATCH 06/43] refactor: resolve repeat operations through APIs --- src/runtimeRepeat.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/runtimeRepeat.ts b/src/runtimeRepeat.ts index 0a9a6d6..1ddd822 100644 --- a/src/runtimeRepeat.ts +++ b/src/runtimeRepeat.ts @@ -5,10 +5,10 @@ import type { UiNodeRepeatSpec, } from '@ankhorage/contracts'; +import { resolveRuntimeBindingOperationSelection } from './runtimeApiSelection'; import { applyRuntimeBindingDataPath, createRuntimeBindingOperationKey, - resolveRuntimeBindingOperationSelection, resolveRuntimeBindingValueSourceSync, type RuntimeBindingOperationResultWriter, type RuntimeBindingResolutionContext, @@ -69,7 +69,7 @@ export function resolveRuntimeRepeatItemsSync( createRepeatDiagnostic( repeat, 'missing-adapter', - 'Repeat operation source requires an injected operation executor.', + 'Repeat API operation source requires an injected operation executor.', ), ], }; @@ -104,7 +104,7 @@ export async function resolveRuntimeRepeatItemsAsync( createRepeatDiagnostic( repeat, 'missing-adapter', - 'Repeat operation source requires an injected operation executor.', + 'Repeat API operation source requires an injected operation executor.', ), ], }; @@ -113,7 +113,7 @@ export async function resolveRuntimeRepeatItemsAsync( const diagnostics: DataSourceDiagnostic[] = []; const selection = resolveRuntimeBindingOperationSelection( repeat.source.operation, - context.dataSources, + context.apis, diagnostics, ); if (selection === undefined) { @@ -121,9 +121,9 @@ export async function resolveRuntimeRepeatItemsAsync( } const result = await context.executeOperation({ - operation: repeat.source.operation, - dataSource: selection.dataSource, + api: selection.api, endpoint: selection.endpoint, + operation: repeat.source.operation, node: context.node, }); diagnostics.push(...(result.diagnostics ?? [])); @@ -202,12 +202,11 @@ function createRepeatDiagnostic( message: string, ): DataSourceDiagnostic { return { - code, - dataSourceId: - repeat.source.kind === 'operation' ? repeat.source.operation.dataSourceId : undefined, + apiId: repeat.source.kind === 'operation' ? repeat.source.operation.apiId : undefined, endpointId: repeat.source.kind === 'operation' ? repeat.source.operation.endpointId : undefined, operationId: repeat.source.kind === 'operation' ? repeat.source.operation.operationId : undefined, + code, message, severity: 'error', }; From b1571e9a601b6d4f98eb33eb5e4256263239e326 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:39:41 +0200 Subject: [PATCH 07/43] refactor: resolve event bindings through canonical APIs --- src/runtimeActionRegistry.ts | 53 +++++++++++------------------------- 1 file changed, 16 insertions(+), 37 deletions(-) diff --git a/src/runtimeActionRegistry.ts b/src/runtimeActionRegistry.ts index 79bac35..fc67904 100644 --- a/src/runtimeActionRegistry.ts +++ b/src/runtimeActionRegistry.ts @@ -1,18 +1,17 @@ import type { + ApiDefinitionList, BindingCondition, BindingInputMap, BindingValue, ComponentDataBindingRegistry, ComponentEventDto, - DataEndpointConfig, - DataSourceConfig, DataSourceDiagnostic, - DataSourceRegistry, EventBinding, EventBindingTarget, UiNode, } from '@ankhorage/contracts'; +import { resolveRuntimeBindingOperationSelection } from './runtimeApiSelection'; import { createRuntimeBindingOperationKey, resolveBindingInputMap, @@ -48,7 +47,7 @@ export interface RuntimeComponentEventDispatchArgs extends RuntimeActionResoluti readonly event: ComponentEventDto; readonly eventName?: string; readonly executeAction?: RuntimeActionHandler; - readonly dataSources?: DataSourceRegistry; + readonly apis?: ApiDefinitionList; readonly dataBindings?: ComponentDataBindingRegistry; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly writeOperationResult?: RuntimeBindingOperationResultWriter; @@ -67,7 +66,7 @@ export interface RuntimeEventPropWrapArgs extends RuntimeActionResolutionScope { export function createRuntimeActionRegistry( options: { actionHandlers?: RuntimeActionHandlers; - dataSources?: DataSourceRegistry; + apis?: ApiDefinitionList; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; @@ -82,8 +81,8 @@ export function createRuntimeActionRegistry( await dispatchRuntimeComponentEvent({ ...args, actionHandlers, + apis: args.apis ?? options.apis, dataBindings: args.dataBindings ?? options.dataBindings, - dataSources: args.dataSources ?? options.dataSources, executeAction: args.executeAction ?? options.executeAction, executeOperation: args.executeOperation ?? options.executeOperation, operationResults: args.operationResults ?? options.operationResults, @@ -261,33 +260,26 @@ async function dispatchRuntimeOperationEventBinding(args: { if (args.args.executeOperation === undefined) { diagnostics.push({ + apiId: target.operation.apiId, code: 'missing-adapter', - dataSourceId: target.operation.dataSourceId, endpointId: target.operation.endpointId, operationId: target.operation.operationId, - message: 'Event operation binding requires an injected operation executor.', + message: 'Event API operation binding requires an injected operation executor.', severity: 'error', }); return false; } - const dataSource = args.args.dataSources?.[target.operation.dataSourceId]; - if (dataSource === undefined) { - diagnostics.push({ - code: 'missing-data-source', - dataSourceId: target.operation.dataSourceId, - endpointId: target.operation.endpointId, - operationId: target.operation.operationId, - message: `Data source '${target.operation.dataSourceId}' could not be found.`, - severity: 'error', - }); - return false; - } + const selection = resolveRuntimeBindingOperationSelection( + target.operation, + args.args.apis, + diagnostics, + ); + if (selection === undefined) return false; - const endpoint = resolveEventOperationEndpoint(target, dataSource); const result = await args.args.executeOperation({ - dataSource, - endpoint, + api: selection.api, + endpoint: selection.endpoint, input: await resolveEventBindingInput(binding.input, args.args, diagnostics), node: args.args.node, operation: target.operation, @@ -339,9 +331,9 @@ async function resolveEventBindingInput( return resolveBindingInputMap( input, { + apis: args.apis, context: args.context, dataBindings: args.dataBindings, - dataSources: args.dataSources, event: args.event, executeOperation: args.executeOperation, operationResults: args.operationResults, @@ -393,19 +385,6 @@ function readBindingConditionSource( } } -function resolveEventOperationEndpoint( - target: RuntimeOperationEventTarget, - dataSource: DataSourceConfig, -): DataEndpointConfig | undefined { - if (target.operation.endpointId !== undefined) { - return dataSource.endpoints[target.operation.endpointId]; - } - - return Object.values(dataSource.endpoints).find( - (endpoint) => endpoint.operations[target.operation.operationId] !== undefined, - ); -} - function createPayloadForEvent( eventName: string, handlerArgs: readonly unknown[], From 8b8f806c9086f280de3cbd35af274d25fc559e39 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:39:58 +0200 Subject: [PATCH 08/43] refactor: expose canonical APIs in runtime config --- src/RuntimeRendererConfig.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/RuntimeRendererConfig.tsx b/src/RuntimeRendererConfig.tsx index 5cf070c..2b89b56 100644 --- a/src/RuntimeRendererConfig.tsx +++ b/src/RuntimeRendererConfig.tsx @@ -1,9 +1,9 @@ import type { Action, + ApiDefinitionList, ComponentDataBindingRegistry, ComponentEventDto, DataSourceDiagnostic, - DataSourceRegistry, DbAdapter, DbRealtimeAdapter, MediaAssetRegistry, @@ -59,7 +59,7 @@ export interface RuntimeRendererConfig { dbRealtimeAdapter?: DbRealtimeAdapter; stateAdapter?: StateAdapter; bindingContext?: Record; - dataSources?: DataSourceRegistry; + apis?: ApiDefinitionList; dataBindings?: ComponentDataBindingRegistry; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; @@ -144,7 +144,7 @@ export function mergeRuntimeRendererConfig( dbRealtimeAdapter: localConfig?.dbRealtimeAdapter ?? inheritedConfig?.dbRealtimeAdapter, stateAdapter: localConfig?.stateAdapter ?? inheritedConfig?.stateAdapter, bindingContext, - dataSources: localConfig?.dataSources ?? inheritedConfig?.dataSources, + apis: localConfig?.apis ?? inheritedConfig?.apis, dataBindings: localConfig?.dataBindings ?? inheritedConfig?.dataBindings, operationResults, writeOperationResult: From ce7b39e94d9e07601a332c8d5cfe2f35a779796b Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:40:09 +0200 Subject: [PATCH 09/43] feat: source runtime APIs from manifest infra --- src/RuntimeScreen.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/RuntimeScreen.tsx b/src/RuntimeScreen.tsx index c32b03c..f2275e4 100644 --- a/src/RuntimeScreen.tsx +++ b/src/RuntimeScreen.tsx @@ -19,9 +19,10 @@ export function RuntimeScreen(props: RuntimeScreenProps) { const runtimeConfig = useRuntimeRendererConfig(); const fallbackStateAdapter = React.useMemo(() => createRuntimeMemoryStateAdapter(), []); const stateAdapter = injectedStateAdapter ?? fallbackStateAdapter; + const apis = manifest.infra?.apis; const screenOperationLoaders = useRuntimeScreenOperationLoaders({ + apis, bindingContext: runtimeConfig.bindingContext, - dataSources: manifest.dataSources, executeOperation: runtimeConfig.executeOperation, operationResults: runtimeConfig.operationResults, onDiagnostics: runtimeConfig.onDiagnostics, @@ -35,8 +36,8 @@ export function RuntimeScreen(props: RuntimeScreenProps) { isRoot registry={registry} stateAdapter={stateAdapter} + apis={apis} dataBindings={manifest.dataBindings} - dataSources={manifest.dataSources} mediaAssets={manifest.media?.assets} operationResults={screenOperationLoaders.operationResults} /> From 148d7634178a262abbeab081177f54f8b6d61f08 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:40:44 +0200 Subject: [PATCH 10/43] refactor: execute screen loaders through APIs --- src/runtimeScreenLoaders.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/runtimeScreenLoaders.ts b/src/runtimeScreenLoaders.ts index 1ccfd65..faa8c2b 100644 --- a/src/runtimeScreenLoaders.ts +++ b/src/runtimeScreenLoaders.ts @@ -6,10 +6,10 @@ import type { } from '@ankhorage/contracts'; import React from 'react'; +import { resolveRuntimeBindingOperationSelection } from './runtimeApiSelection'; import { createRuntimeBindingOperationKey, resolveBindingInputMapSync, - resolveRuntimeBindingOperationSelection, type RuntimeBindingOperationExecutor, type RuntimeBindingOperationResultCache, type RuntimeBindingResolutionContext, @@ -177,7 +177,7 @@ export function completeRuntimeScreenOperationLoaderRequest(args: { export async function executeRuntimeScreenOperationLoaders(args: { readonly bindingContext?: Record; - readonly dataSources?: RuntimeBindingResolutionContext['dataSources']; + readonly apis?: RuntimeBindingResolutionContext['apis']; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; @@ -191,7 +191,7 @@ export async function executeRuntimeScreenOperationLoaders(args: { }); return executePreparedRuntimeScreenOperationLoaders({ - dataSources: args.dataSources, + apis: args.apis, executeOperation: args.executeOperation, plan, screen: args.screen, @@ -199,7 +199,7 @@ export async function executeRuntimeScreenOperationLoaders(args: { } function executePreparedRuntimeScreenOperationLoaders(args: { - readonly dataSources?: RuntimeBindingResolutionContext['dataSources']; + readonly apis?: RuntimeBindingResolutionContext['apis']; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly plan: RuntimeScreenOperationLoaderPlan; readonly screen: ScreenSpec; @@ -220,7 +220,7 @@ function executePreparedRuntimeScreenOperationLoaders(args: { createScreenOperationLoaderDiagnostic( preparedLoader.loader, 'missing-adapter', - 'Screen operation loader requires an injected operation executor.', + 'Screen API operation loader requires an injected operation executor.', ), ), ); @@ -239,7 +239,7 @@ function executePreparedRuntimeScreenOperationLoaders(args: { for (const preparedLoader of args.plan.loaders) { const selection = resolveRuntimeBindingOperationSelection( preparedLoader.loader.operation, - args.dataSources, + args.apis, diagnostics, ); if (selection === undefined) { @@ -247,7 +247,7 @@ function executePreparedRuntimeScreenOperationLoaders(args: { } const result = await executeOperation({ - dataSource: selection.dataSource, + api: selection.api, endpoint: selection.endpoint, input: preparedLoader.input, node: args.screen.root, @@ -272,7 +272,7 @@ function executePreparedRuntimeScreenOperationLoaders(args: { export function useRuntimeScreenOperationLoaders(args: { readonly bindingContext?: Record; - readonly dataSources?: RuntimeBindingResolutionContext['dataSources']; + readonly apis?: RuntimeBindingResolutionContext['apis']; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; @@ -314,7 +314,7 @@ export function useRuntimeScreenOperationLoaders(args: { >({}); executionArgsByRequestKeyRef.current[requestKey] = { - dataSources: args.dataSources, + apis: args.apis, executeOperation: args.executeOperation, plan, screen: args.screen, @@ -391,7 +391,7 @@ interface RuntimeScreenOperationLoaderPlan { } interface RuntimeScreenPreparedExecutionArgs { - readonly dataSources?: RuntimeBindingResolutionContext['dataSources']; + readonly apis?: RuntimeBindingResolutionContext['apis']; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly plan: RuntimeScreenOperationLoaderPlan; readonly screen: ScreenSpec; @@ -475,8 +475,8 @@ function createScreenOperationLoaderDiagnostic( message: string, ): DataSourceDiagnostic { return { + apiId: loader.operation.apiId, code, - dataSourceId: loader.operation.dataSourceId, endpointId: loader.operation.endpointId, operationId: loader.operation.operationId, message, From 53fa3f6298394ba3fd1e9216c2265892ec4798d5 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:42:15 +0200 Subject: [PATCH 11/43] refactor: render with canonical APIs --- src/RuntimeRenderer.tsx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/RuntimeRenderer.tsx b/src/RuntimeRenderer.tsx index f762dcc..b141ddb 100644 --- a/src/RuntimeRenderer.tsx +++ b/src/RuntimeRenderer.tsx @@ -1,8 +1,8 @@ import type { + ApiDefinitionList, BindingValue, ComponentDataBindingRegistry, DataSourceDiagnostic, - DataSourceRegistry, DbAdapter, DbRealtimeAdapter, MediaAssetRegistry, @@ -63,7 +63,7 @@ export interface RuntimeRendererProps { dbRealtimeAdapter?: DbRealtimeAdapter; stateAdapter?: StateAdapter; bindingContext?: Record; - dataSources?: DataSourceRegistry; + apis?: ApiDefinitionList; dataBindings?: ComponentDataBindingRegistry; mediaAssets?: MediaAssetRegistry; resolveMediaAsset?: RuntimeMediaAssetResolver; @@ -84,7 +84,7 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { dbRealtimeAdapter, stateAdapter, bindingContext, - dataSources, + apis, dataBindings, mediaAssets, resolveMediaAsset, @@ -121,9 +121,9 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { ); const explicitConfig = React.useMemo( () => ({ + apis, bindingContext, dataBindings, - dataSources, dbAdapter, dbRealtimeAdapter, disableActions, @@ -139,9 +139,9 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { writeOperationResult: inheritedConfig.writeOperationResult ?? writeLocalOperationResult, }), [ + apis, bindingContext, dataBindings, - dataSources, dbAdapter, dbRealtimeAdapter, disableActions, @@ -191,8 +191,8 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { await dispatchRuntimeComponentEventWithReporting({ ...eventArgs, actionHandlers: effectiveActionHandlers, + apis: eventArgs.apis ?? effectiveConfig.apis, dataBindings: eventArgs.dataBindings ?? effectiveConfig.dataBindings, - dataSources: eventArgs.dataSources ?? effectiveConfig.dataSources, executeAction: effectiveConfig.executeAction ?? executeRuntimeAction, executeOperation: eventArgs.executeOperation ?? effectiveConfig.executeOperation, onDiagnostics: effectiveConfig.onDiagnostics, @@ -203,8 +203,8 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { }, [ effectiveActionHandlers, + effectiveConfig.apis, effectiveConfig.dataBindings, - effectiveConfig.dataSources, effectiveConfig.executeAction, effectiveConfig.executeOperation, effectiveConfig.onDiagnostics, @@ -240,9 +240,9 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { } return resolveRuntimeRepeatItemsSync(repeat, { + apis: effectiveConfig.apis, context: effectiveConfig.bindingContext, dataBindings: effectiveConfig.dataBindings, - dataSources: effectiveConfig.dataSources, executeOperation: effectiveConfig.executeOperation, node, operationResults: effectiveConfig.operationResults, @@ -250,9 +250,9 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { writeOperationResult: effectiveConfig.writeOperationResult, }); }, [ + effectiveConfig.apis, effectiveConfig.bindingContext, effectiveConfig.dataBindings, - effectiveConfig.dataSources, effectiveConfig.executeOperation, effectiveConfig.operationResults, effectiveConfig.stateAdapter, @@ -278,9 +278,9 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { void (async () => { const result = await resolveRuntimeRepeatItemsAsync(repeat, { + apis: effectiveConfig.apis, context: effectiveConfig.bindingContext, dataBindings: effectiveConfig.dataBindings, - dataSources: effectiveConfig.dataSources, executeOperation: effectiveConfig.executeOperation, node, operationResults: effectiveConfig.operationResults, @@ -299,9 +299,9 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { repeatRequestIdRef.current += 1; }; }, [ + effectiveConfig.apis, effectiveConfig.bindingContext, effectiveConfig.dataBindings, - effectiveConfig.dataSources, effectiveConfig.executeOperation, effectiveConfig.operationResults, effectiveConfig.stateAdapter, @@ -329,9 +329,9 @@ export function RuntimeRenderer(props: RuntimeRendererProps) { }, [effectiveConfig.onDiagnostics, node.repeat, repeatDiagnostics]); const bindingResolvedProps = resolveRuntimeNodeProps({ + apis: effectiveConfig.apis, bindingContext: effectiveConfig.bindingContext, dataBindings: effectiveConfig.dataBindings, - dataSources: effectiveConfig.dataSources, dbAdapter: effectiveConfig.dbAdapter, dbRealtimeAdapter: effectiveConfig.dbRealtimeAdapter, node, From 5685dfa3c55d28609ac8a9ddf658d7de565f69f4 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:42:37 +0200 Subject: [PATCH 12/43] refactor: expose canonical runtime API surface --- src/index.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/index.ts b/src/index.ts index c2b2ce9..0109f92 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,6 +22,10 @@ export { resolveRuntimeActionValue, wrapRuntimeEventProps, } from './runtimeActionRegistry'; +export type { RuntimeApiOperationExecutorOptions } from './runtimeApiOperations'; +export { createRuntimeApiOperationExecutor } from './runtimeApiOperations'; +export type { RuntimeApiOperationSelection } from './runtimeApiSelection'; +export { validateRuntimeBindingOperationRef } from './runtimeApiSelection'; export type { RuntimeBindingOperationExecutionArgs, RuntimeBindingOperationExecutionResult, @@ -40,10 +44,7 @@ export { resolveRuntimeBindingsAsync, resolveRuntimeBindingValue, resolveRuntimeBindingValueSync, - validateRuntimeBindingOperationRef, } from './runtimeBindings'; -export type { RuntimeDataSourceOperationExecutorOptions } from './runtimeDataSourceOperations'; -export { createRuntimeDataSourceOperationExecutor } from './runtimeDataSourceOperations'; export type { RuntimeDbPersistError, RuntimeDbPersistExecutionResult, From 6c8d82f0b68b8266117268ac13c526d73b2c99ce Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:42:54 +0200 Subject: [PATCH 13/43] refactor: remove data source operation executor --- src/runtimeDataSourceOperations.ts | 118 ----------------------------- 1 file changed, 118 deletions(-) delete mode 100644 src/runtimeDataSourceOperations.ts diff --git a/src/runtimeDataSourceOperations.ts b/src/runtimeDataSourceOperations.ts deleted file mode 100644 index d53673a..0000000 --- a/src/runtimeDataSourceOperations.ts +++ /dev/null @@ -1,118 +0,0 @@ -import type { BindingValue, DataSourceDiagnostic, DbAdapter } from '@ankhorage/contracts'; -import type { EndpointTestCredentialResolver, EndpointTestFetch } from '@ankhorage/data-sources'; -import { testEndpoint } from '@ankhorage/data-sources'; - -import type { RuntimeBindingOperationExecutor } from './runtimeBindings'; -import { executeRuntimeDatabaseOperation } from './runtimeDatabaseOperationExecutor'; - -export interface RuntimeDataSourceOperationExecutorOptions { - readonly fetch?: EndpointTestFetch; - readonly credentialResolver?: EndpointTestCredentialResolver; - readonly databaseAdapters?: Readonly>; -} - -export function createRuntimeDataSourceOperationExecutor( - options: RuntimeDataSourceOperationExecutorOptions, -): RuntimeBindingOperationExecutor { - return async ({ dataSource, endpoint, input, operation }) => { - if (endpoint === undefined) { - return missingEndpoint(operation.dataSourceId, operation.endpointId, operation.operationId); - } - - const operationConfig = endpoint.operations[operation.operationId]; - if (operationConfig === undefined) { - return missingOperation(operation.dataSourceId, endpoint.id, operation.operationId); - } - - const values = asBindingValueRecord(input); - if (input !== undefined && values === undefined) { - return invalidInput(operation.dataSourceId, endpoint.id, operation.operationId); - } - - if (operationConfig.protocol === 'database') { - return executeRuntimeDatabaseOperation({ - dataSource, - operation: operationConfig, - input: values, - databaseAdapters: options.databaseAdapters, - }); - } - - const result = await testEndpoint({ - credentialResolver: options.credentialResolver, - dataSource, - endpointId: endpoint.id, - fetch: options.fetch, - operationId: operation.operationId, - values, - }); - - return result.ok - ? { ok: true, data: result.data ?? null, diagnostics: result.diagnostics } - : { ok: false, diagnostics: result.diagnostics }; - }; -} - -function missingEndpoint( - dataSourceId: string, - endpointId: string | undefined, - operationId: string, -) { - return failure( - dataSourceId, - endpointId, - operationId, - 'missing-endpoint', - `Endpoint '${endpointId ?? ''}' could not be found.`, - ); -} - -function missingOperation(dataSourceId: string, endpointId: string, operationId: string) { - return failure( - dataSourceId, - endpointId, - operationId, - 'missing-operation', - `Operation '${operationId}' could not be found.`, - ); -} - -function invalidInput(dataSourceId: string, endpointId: string, operationId: string) { - return failure( - dataSourceId, - endpointId, - operationId, - 'invalid-config', - 'Operation input must resolve to an object.', - ); -} - -function failure( - dataSourceId: string, - endpointId: string | undefined, - operationId: string, - code: string, - message: string, -) { - const diagnostic: DataSourceDiagnostic = { - code, - dataSourceId, - endpointId, - operationId, - message, - severity: 'error', - }; - return { ok: false as const, diagnostics: [diagnostic] }; -} - -function asBindingValueRecord( - value: BindingValue | undefined, -): Readonly> | undefined { - return isBindingValueRecord(value) ? value : undefined; -} - -function isBindingValueRecord( - value: BindingValue | undefined, -): value is Readonly> { - return typeof value === 'object' && value !== null && !Array.isArray(value); -} From 2e6191737743fab2f6130b73094bebfe41387e66 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:43:02 +0200 Subject: [PATCH 14/43] refactor: remove API database operation shortcut --- src/runtimeDatabaseOperationExecutor.ts | 369 ------------------------ 1 file changed, 369 deletions(-) delete mode 100644 src/runtimeDatabaseOperationExecutor.ts diff --git a/src/runtimeDatabaseOperationExecutor.ts b/src/runtimeDatabaseOperationExecutor.ts deleted file mode 100644 index da1e466..0000000 --- a/src/runtimeDatabaseOperationExecutor.ts +++ /dev/null @@ -1,369 +0,0 @@ -import type { - BindingValue, - DataOperationConfig, - DataSourceConfig, - DataSourceDiagnostic, - DbAdapter, - DbFilter, - DbRecord, -} from '@ankhorage/contracts'; - -import type { RuntimeBindingOperationExecutionResult } from './runtimeBindings'; - -export async function executeRuntimeDatabaseOperation(args: { - readonly dataSource: DataSourceConfig; - readonly operation: DataOperationConfig; - readonly input: Readonly> | undefined; - readonly databaseAdapters: Readonly> | undefined; -}): Promise { - const plan = resolveOperationPlan(args.dataSource, args.operation); - if (!plan.ok) return plan.result; - - const adapter = args.databaseAdapters?.[plan.adapterId]; - if (adapter === undefined) { - return failure( - args, - 'missing-adapter', - `Database adapter '${plan.adapterId}' is not available.`, - ); - } - - const input = args.input ?? {}; - switch (plan.operation) { - case 'list': - return executeList(adapter, plan, input, args); - case 'read': - return executeRead(adapter, plan, input, args); - case 'create': - return executeCreate(adapter, plan, input, args); - case 'update': - return executeUpdate(adapter, plan, input, args); - case 'delete': - return executeDelete(adapter, plan, input, args); - } -} - -type GeneratedCrudOperation = 'list' | 'read' | 'create' | 'update' | 'delete'; - -interface DatabaseOperationPlan { - readonly adapterId: string; - readonly collection: string; - readonly schema?: string; - readonly operation: GeneratedCrudOperation; - readonly primaryKey?: string; -} - -type OperationPlanResult = - | { - readonly ok: true; - readonly adapterId: string; - readonly collection: string; - readonly schema?: string; - readonly operation: GeneratedCrudOperation; - readonly primaryKey?: string; - } - | { readonly ok: false; readonly result: RuntimeBindingOperationExecutionResult }; - -function resolveOperationPlan( - dataSource: DataSourceConfig, - operation: DataOperationConfig, -): OperationPlanResult { - const metadata = asRecord(operation.metadata); - const adapterId = resolveAdapterId(dataSource); - const collection = metadata?.collection; - const operationKind = metadata?.operation; - const schema = metadata?.schema; - - if (adapterId === undefined) { - return invalidPlan( - dataSource, - operation, - 'Database operation source does not reference an adapter.', - ); - } - if (typeof collection !== 'string' || collection.trim().length === 0) { - return invalidPlan(dataSource, operation, 'Database operation metadata requires a collection.'); - } - if (!isGeneratedCrudOperation(operationKind)) { - return invalidPlan( - dataSource, - operation, - 'Database operation metadata requires a generated CRUD operation.', - ); - } - if (schema !== undefined && schema !== null && typeof schema !== 'string') { - return invalidPlan( - dataSource, - operation, - 'Database operation schema metadata must be a string or null.', - ); - } - - const metadataAdapterId = metadata?.adapterId; - if (metadataAdapterId !== undefined && metadataAdapterId !== adapterId) { - return invalidPlan( - dataSource, - operation, - 'Database operation adapter metadata does not match its data source.', - ); - } - - return { - ok: true, - adapterId, - collection, - schema: typeof schema === 'string' ? schema : undefined, - operation: operationKind, - primaryKey: resolvePrimaryKey(operation), - }; -} - -async function executeList( - adapter: DbAdapter, - plan: DatabaseOperationPlan, - input: Readonly>, - args: DatabaseExecutionArgs, -): Promise { - const page = resolvePage(input); - if (!page.ok) return failure(args, 'invalid-config', page.message); - - const result = await adapter.select({ - table: plan.collection, - schema: plan.schema, - page: page.value, - }); - return resolveDbResult(args, result, (records) => records); -} - -async function executeRead( - adapter: DbAdapter, - plan: DatabaseOperationPlan, - input: Readonly>, - args: DatabaseExecutionArgs, -): Promise { - const identity = resolveIdentity(plan, input); - if (!identity.ok) return failure(args, 'invalid-config', identity.message); - - const result = await adapter.findById({ - table: plan.collection, - schema: plan.schema, - id: identity.value, - idField: plan.primaryKey, - }); - return resolveDbResult(args, result, (record) => record); -} - -async function executeCreate( - adapter: DbAdapter, - plan: DatabaseOperationPlan, - input: Readonly>, - args: DatabaseExecutionArgs, -): Promise { - const result = await adapter.insert({ - table: plan.collection, - schema: plan.schema, - values: { ...input }, - }); - return resolveDbResult(args, result, (records) => records[0] ?? null); -} - -async function executeUpdate( - adapter: DbAdapter, - plan: DatabaseOperationPlan, - input: Readonly>, - args: DatabaseExecutionArgs, -): Promise { - const identity = resolveIdentity(plan, input); - if (!identity.ok) return failure(args, 'invalid-config', identity.message); - - const values = omitKey(input, plan.primaryKey); - if (Object.keys(values).length === 0) { - return failure( - args, - 'invalid-config', - 'Generated update operation requires at least one value to update.', - ); - } - - const result = await adapter.update({ - table: plan.collection, - schema: plan.schema, - values, - filters: [createIdentityFilter(plan.primaryKey, identity.value)], - }); - return resolveDbResult(args, result, (records) => records[0] ?? null); -} - -async function executeDelete( - adapter: DbAdapter, - plan: DatabaseOperationPlan, - input: Readonly>, - args: DatabaseExecutionArgs, -): Promise { - const identity = resolveIdentity(plan, input); - if (!identity.ok) return failure(args, 'invalid-config', identity.message); - - const result = await adapter.delete({ - table: plan.collection, - schema: plan.schema, - filters: [createIdentityFilter(plan.primaryKey, identity.value)], - }); - return resolveDbResult(args, result, (records) => ({ deleted: records.length > 0 })); -} - -type DatabaseExecutionArgs = Pick< - Parameters[0], - 'dataSource' | 'operation' ->; - -function resolveDbResult( - args: DatabaseExecutionArgs, - result: - | { readonly ok: true; readonly data: TData } - | { readonly ok: false; readonly error: { readonly message: string } }, - select: (data: TData) => unknown, -): RuntimeBindingOperationExecutionResult { - if (!result.ok) return failure(args, 'database-operation-failed', result.error.message); - - const value = toBindingValue(select(result.data)); - if (value === undefined) { - return failure( - args, - 'invalid-config', - 'Database adapter returned a non-serializable binding value.', - ); - } - return { ok: true, data: value, diagnostics: [] }; -} - -function resolveAdapterId(dataSource: DataSourceConfig): string | undefined { - if (dataSource.kind === 'database') return dataSource.adapter.id; - if (dataSource.origin === 'generated') return dataSource.adapter.id; - return undefined; -} - -function resolvePrimaryKey(operation: DataOperationConfig): string | undefined { - return operation.request?.parameters?.find((parameter) => parameter.location === 'path')?.name; -} - -function resolveIdentity( - plan: DatabaseOperationPlan, - input: Readonly>, -): - | { readonly ok: true; readonly value: string | number } - | { readonly ok: false; readonly message: string } { - if (plan.primaryKey === undefined) { - return { - ok: false, - message: 'Generated read/update/delete operation requires primary-key metadata.', - }; - } - const value = input[plan.primaryKey]; - return typeof value === 'string' || (typeof value === 'number' && Number.isFinite(value)) - ? { ok: true, value } - : { - ok: false, - message: `Generated operation requires '${plan.primaryKey}' as a string or number.`, - }; -} - -function resolvePage(input: Readonly>): - | { - readonly ok: true; - readonly value: { readonly limit?: number; readonly offset?: number } | undefined; - } - | { readonly ok: false; readonly message: string } { - const { limit, offset } = input; - if (!isOptionalPageNumber(limit) || !isOptionalPageNumber(offset)) { - return { - ok: false, - message: 'Generated list operation limit/offset must be non-negative integers.', - }; - } - if (limit === undefined && offset === undefined) return { ok: true, value: undefined }; - return { ok: true, value: { limit, offset } }; -} - -function isOptionalPageNumber(value: BindingValue | undefined): value is number | undefined { - return ( - value === undefined || (typeof value === 'number' && Number.isInteger(value) && value >= 0) - ); -} - -function createIdentityFilter(field: string | undefined, value: string | number): DbFilter { - return { field: field ?? 'id', operator: 'eq', value }; -} - -function omitKey(input: Readonly>, key: string | undefined): DbRecord { - const values: DbRecord = {}; - for (const [field, value] of Object.entries(input)) { - if (field !== key) values[field] = value; - } - return values; -} - -function isGeneratedCrudOperation(value: unknown): value is GeneratedCrudOperation { - return ( - value === 'list' || - value === 'read' || - value === 'create' || - value === 'update' || - value === 'delete' - ); -} - -function invalidPlan( - dataSource: DataSourceConfig, - operation: DataOperationConfig, - message: string, -): OperationPlanResult { - return { - ok: false, - result: failure({ dataSource, operation }, 'invalid-config', message), - }; -} - -function failure( - args: DatabaseExecutionArgs, - code: string, - message: string, -): RuntimeBindingOperationExecutionResult { - const diagnostic: DataSourceDiagnostic = { - code, - dataSourceId: args.dataSource.id, - endpointId: args.operation.endpointId, - operationId: args.operation.id, - message, - severity: 'error', - }; - return { ok: false, diagnostics: [diagnostic] }; -} - -function asRecord(value: unknown): Readonly> | undefined { - return typeof value === 'object' && value !== null && !Array.isArray(value) - ? (value as Readonly>) - : undefined; -} - -function toBindingValue(value: unknown): BindingValue | undefined { - if (value === null || typeof value === 'string' || typeof value === 'boolean') return value; - if (typeof value === 'number') return Number.isFinite(value) ? value : undefined; - if (Array.isArray(value)) { - const items: BindingValue[] = []; - for (const item of value) { - const converted = toBindingValue(item); - if (converted === undefined) return undefined; - items.push(converted); - } - return items; - } - const record = asRecord(value); - if (record === undefined) return undefined; - const converted: Record = {}; - for (const [key, item] of Object.entries(record)) { - const bindingValue = toBindingValue(item); - if (bindingValue === undefined) return undefined; - converted[key] = bindingValue; - } - return converted; -} From be91179d22b0930560c170080e67a3739de9d5c4 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:45:05 +0200 Subject: [PATCH 15/43] chore: add canonical runtime API changeset --- .changeset/canonical-runtime-api-bindings.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/canonical-runtime-api-bindings.md diff --git a/.changeset/canonical-runtime-api-bindings.md b/.changeset/canonical-runtime-api-bindings.md new file mode 100644 index 0000000..c16f2ce --- /dev/null +++ b/.changeset/canonical-runtime-api-bindings.md @@ -0,0 +1,5 @@ +--- +'@ankhorage/runtime': major +--- + +Resolve operation bindings through canonical `infra.apis[]` API identities, delegate API execution to `@ankhorage/data-sources`, and remove the API-to-database operation shortcut while preserving explicit database actions separately. From 1f8cc6569c5dd8683067f6bed6b51a0e3ec9356f Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:46:13 +0200 Subject: [PATCH 16/43] ci: inspect dependency migration --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a16025d..b4f0ed1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,10 @@ jobs: bun-version: '1.3.13' - name: Install dependencies - run: bun install --frozen-lockfile + run: bun install + + - name: Show lockfile changes + run: git diff -- bun.lock - name: Run build run: bun run build From 1c6d1e35dab0cc39f804975b56b35c550c2c1a8d Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:47:33 +0200 Subject: [PATCH 17/43] test: migrate runtime bindings to canonical APIs --- src/runtimeBindings.test.ts | 97 ++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/src/runtimeBindings.test.ts b/src/runtimeBindings.test.ts index 479a8b2..b640786 100644 --- a/src/runtimeBindings.test.ts +++ b/src/runtimeBindings.test.ts @@ -1,8 +1,8 @@ import type { + ApiDefinitionList, BindingInputMap, ComponentDataBindingRegistry, DataSourceDiagnostic, - DataSourceRegistry, StateAdapter, StatePath, StateResult, @@ -12,53 +12,20 @@ import type { } from '@ankhorage/contracts'; import { describe, expect, it } from 'bun:test'; +import { validateRuntimeBindingOperationRef } from './runtimeApiSelection'; import { createRuntimeBindingOperationKey, resolveBindingInputMapSync, resolveRuntimeBindings, resolveRuntimeBindingsAsync, resolveRuntimeBindingValue, - validateRuntimeBindingOperationRef, } from './runtimeBindings'; import { resolveRuntimeNodeProps } from './runtimeNodeProps'; -function createFakeStateAdapter(values: Record): StateAdapter { - return { - capabilities: { - subscriptions: true, - computed: false, - persistence: false, - }, - get(path: StatePath): StateResult { - const key = typeof path === 'string' ? path : path.join('.'); - return { ok: true, data: values[key] as TValue | undefined } as StateResult< - TValue | undefined - >; - }, - set(): StateResult { - return { ok: true }; - }, - subscribe(): StateResult { - return { - ok: true, - data: { - unsubscribe() { - return undefined; - }, - }, - }; - }, - delete(): StateResult { - return { ok: true }; - }, - }; -} - -function createDataSources(): DataSourceRegistry { - return { - cms: { +function createApis(): ApiDefinitionList { + return [ + { id: 'cms', - kind: 'api', origin: 'external', protocol: 'rest', baseUrl: 'https://cms.example.com', @@ -87,6 +54,38 @@ function createDataSources(): DataSourceRegistry { }, }, }, + ]; +} + +function createFakeStateAdapter(values: Record): StateAdapter { + return { + capabilities: { + subscriptions: true, + computed: false, + persistence: false, + }, + get(path: StatePath): StateResult { + const key = typeof path === 'string' ? path : path.join('.'); + return { ok: true, data: values[key] as TValue | undefined } as StateResult< + TValue | undefined + >; + }, + set(): StateResult { + return { ok: true }; + }, + subscribe(): StateResult { + return { + ok: true, + data: { + unsubscribe() { + return undefined; + }, + }, + }; + }, + delete(): StateResult { + return { ok: true }; + }, }; } @@ -217,7 +216,7 @@ describe('resolveRuntimeBindings', () => { type: 'List', }; const operation = { - dataSourceId: 'cms', + apiId: 'cms', endpointId: 'posts', operationId: 'posts.list', }; @@ -226,7 +225,7 @@ describe('resolveRuntimeBindings', () => { resolveRuntimeBindings({ node, props: {}, - dataSources: createDataSources(), + apis: createApis(), dataBindings: { 'posts-list': { componentId: 'posts-list', @@ -255,7 +254,7 @@ describe('resolveRuntimeBindings', () => { const result = resolveRuntimeBindings({ node, props: {}, - dataSources: createDataSources(), + apis: createApis(), dataBindings: { 'posts-list': { componentId: 'posts-list', @@ -264,7 +263,7 @@ describe('resolveRuntimeBindings', () => { source: { kind: 'operation', operation: { - dataSourceId: 'cms', + apiId: 'cms', endpointId: 'posts', operationId: 'posts.list', }, @@ -292,7 +291,7 @@ describe('resolveRuntimeBindingsAsync', () => { const result = await resolveRuntimeBindingsAsync({ node, props: {}, - dataSources: createDataSources(), + apis: createApis(), dataBindings: { 'posts-list': { componentId: 'posts-list', @@ -301,7 +300,7 @@ describe('resolveRuntimeBindingsAsync', () => { source: { kind: 'operation', operation: { - dataSourceId: 'cms', + apiId: 'cms', endpointId: 'posts', operationId: 'posts.list', }, @@ -348,16 +347,16 @@ describe('validateRuntimeBindingOperationRef', () => { expect( validateRuntimeBindingOperationRef( { - dataSourceId: 'cms', + apiId: 'cms', endpointId: 'posts', operationId: 'posts.missing', }, - createDataSources(), + createApis(), ), ).toEqual([ { + apiId: 'cms', code: 'missing-operation', - dataSourceId: 'cms', endpointId: 'posts', operationId: 'posts.missing', message: "Operation 'posts.missing' could not be found.", @@ -370,7 +369,7 @@ describe('validateRuntimeBindingOperationRef', () => { describe('resolveBindingInputMapSync', () => { it('resolves nested input values synchronously without executing operations', () => { const operation = { - dataSourceId: 'cms', + apiId: 'cms', endpointId: 'posts', operationId: 'posts.list', }; @@ -459,7 +458,7 @@ describe('resolveBindingInputMapSync', () => { source: { kind: 'operation', operation: { - dataSourceId: 'cms', + apiId: 'cms', endpointId: 'posts', operationId: 'posts.list', }, From dfbf3f455e7ec09a7c9bcf0a63e01f8fd3d9e87d Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:48:10 +0200 Subject: [PATCH 18/43] test: prove canonical runtime API execution --- src/runtimeApiOperations.test.ts | 138 +++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/runtimeApiOperations.test.ts diff --git a/src/runtimeApiOperations.test.ts b/src/runtimeApiOperations.test.ts new file mode 100644 index 0000000..eff9567 --- /dev/null +++ b/src/runtimeApiOperations.test.ts @@ -0,0 +1,138 @@ +import type { ApiDefinition, DataEndpointConfig } from '@ankhorage/contracts'; +import { describe, expect, it } from 'bun:test'; + +import { createRuntimeApiOperationExecutor } from './runtimeApiOperations'; + +function createNutritionApi(): ApiDefinition { + return { + id: 'nutrition', + origin: 'external', + protocol: 'rest', + baseUrl: 'https://api.ankhorage.com/v1/nutrition', + endpoints: { + products: createProductsEndpoint(), + }, + }; +} + +function createProductsEndpoint(): DataEndpointConfig { + return { + id: 'products', + kind: 'http', + operations: { + 'products.list': { + id: 'products.list', + endpointId: 'products', + protocol: 'http', + intent: 'read', + method: 'GET', + path: '/products', + }, + }, + }; +} + +function getProductsEndpoint(api: ApiDefinition): DataEndpointConfig { + const endpoint = api.endpoints.products; + if (endpoint === undefined) throw new Error('Expected products endpoint fixture.'); + return endpoint; +} + +describe('createRuntimeApiOperationExecutor', () => { + it('executes Nutrition products over canonical external HTTP', async () => { + const api = createNutritionApi(); + const endpoint = getProductsEndpoint(api); + const calls: string[] = []; + const executor = createRuntimeApiOperationExecutor({ + fetch: (url, init) => { + calls.push(`${init.method} ${url}`); + return Promise.resolve({ + status: 200, + headers: { 'content-type': 'application/json' }, + text: () => Promise.resolve('{"products":[{"id":"apple"}]}'), + }); + }, + }); + + const result = await executor({ + api, + endpoint, + operation: { + apiId: 'nutrition', + endpointId: 'products', + operationId: 'products.list', + }, + }); + + expect(calls).toEqual(['GET https://api.ankhorage.com/v1/nutrition/products']); + expect(calls.some((call) => call.includes('/rest/v1/'))).toBe(false); + expect(result).toEqual({ + ok: true, + data: { products: [{ id: 'apple' }] }, + diagnostics: [], + }); + }); + + it('rejects non-object API operation input before execution', async () => { + const api = createNutritionApi(); + const result = await createRuntimeApiOperationExecutor({})({ + api, + endpoint: getProductsEndpoint(api), + input: 'not-an-object', + operation: { + apiId: 'nutrition', + endpointId: 'products', + operationId: 'products.list', + }, + }); + + expect(result).toEqual({ + ok: false, + diagnostics: [ + { + apiId: 'nutrition', + code: 'invalid-config', + endpointId: 'products', + message: 'API operation input must resolve to an object.', + operationId: 'products.list', + severity: 'error', + }, + ], + }); + }); + + it('keeps internal APIs unsupported and never falls back to another transport', async () => { + const calls: string[] = []; + const api: ApiDefinition = { + id: 'internal-products', + origin: 'internal', + protocol: 'rest', + basePath: '/v1/products', + endpoints: { + products: createProductsEndpoint(), + }, + }; + const result = await createRuntimeApiOperationExecutor({ + fetch: (url) => { + calls.push(url); + throw new Error('Internal API phase-1 execution must not reach fetch.'); + }, + })({ + api, + endpoint: getProductsEndpoint(api), + operation: { + apiId: 'internal-products', + endpointId: 'products', + operationId: 'products.list', + }, + }); + + expect(result.ok).toBe(false); + expect(calls).toEqual([]); + if (!result.ok) { + expect(result.diagnostics.map((diagnostic) => diagnostic.message).join('\n')).toContain( + 'Internal APIs are not executable in API phase 1.', + ); + } + }); +}); From d600990a3135f75e925b8b1a1eac66a80473b873 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:48:18 +0200 Subject: [PATCH 19/43] test: remove generated API database operation coverage --- src/runtimeDataSourceOperations.test.ts | 308 ------------------------ 1 file changed, 308 deletions(-) delete mode 100644 src/runtimeDataSourceOperations.test.ts diff --git a/src/runtimeDataSourceOperations.test.ts b/src/runtimeDataSourceOperations.test.ts deleted file mode 100644 index 47d3106..0000000 --- a/src/runtimeDataSourceOperations.test.ts +++ /dev/null @@ -1,308 +0,0 @@ -import type { - DataEndpointConfig, - DataSourceConfig, - DataSourceRegistry, - DbAdapter, - DbDeleteInput, - DbFindByIdInput, - DbInsertInput, - DbRecord, - DbResult, - DbSelectInput, - DbUpdateInput, -} from '@ankhorage/contracts'; -import { createGeneratedApiDataSource } from '@ankhorage/data-sources'; -import { describe, expect, it } from 'bun:test'; - -import { createRuntimeDataSourceOperationExecutor } from './runtimeDataSourceOperations'; - -function createExternalDataSources(): DataSourceRegistry { - return { - chess: { - id: 'chess', - kind: 'api', - origin: 'external', - protocol: 'rest', - baseUrl: 'https://api.ankhorage.com', - endpoints: { - opening: { - id: 'opening', - kind: 'http', - operations: { - 'opening.moves': { - id: 'opening.moves', - endpointId: 'opening', - protocol: 'http', - intent: 'read', - method: 'GET', - path: '/v1/chess/opening', - request: { - parameters: [ - { - name: 'fen', - location: 'query', - required: true, - schema: { type: 'string' }, - }, - ], - }, - }, - }, - }, - }, - }, - }; -} - -function createGeneratedDataSource(): DataSourceConfig { - const result = createGeneratedApiDataSource({ - id: 'posts-api', - protocol: 'rest', - basePath: '/api', - database: { id: 'primary-db', kind: 'database' }, - resources: [ - { - id: 'posts', - path: '/posts', - operations: ['list', 'read', 'create', 'update', 'delete'], - collection: { - name: 'posts', - schema: 'public', - primaryKey: 'id', - fields: [ - { name: 'id', type: 'uuid', required: true, unique: true }, - { name: 'title', type: 'text', required: true }, - ], - }, - }, - ], - }); - if (!result.ok) throw new Error('Expected generated API fixture to normalize.'); - return result.data; -} - -function getFixtureDataSource(registry: DataSourceRegistry): DataSourceConfig { - const dataSource = registry.chess; - if (dataSource === undefined) throw new Error('Expected chess data-source fixture to exist.'); - return dataSource; -} - -function getFixtureEndpoint( - dataSource: DataSourceConfig, - endpointId = 'opening', -): DataEndpointConfig { - const endpoint = dataSource.endpoints[endpointId]; - if (endpoint === undefined) - throw new Error(`Expected '${endpointId}' endpoint fixture to exist.`); - return endpoint; -} - -interface DatabaseCalls { - readonly select: DbSelectInput[]; - readonly findById: DbFindByIdInput[]; - readonly insert: DbInsertInput[]; - readonly update: DbUpdateInput[]; - readonly delete: DbDeleteInput[]; -} - -function createDatabaseFixture(): { readonly adapter: DbAdapter; readonly calls: DatabaseCalls } { - const calls: DatabaseCalls = { select: [], findById: [], insert: [], update: [], delete: [] }; - const adapter: DbAdapter = { - capabilities: { transactions: false, returning: true, realtime: false }, - select(input: DbSelectInput): Promise> { - calls.select.push(input); - return Promise.resolve({ ok: true, data: [{ id: 'post-1', title: 'First' } as TRecord] }); - }, - findById( - input: DbFindByIdInput, - ): Promise> { - calls.findById.push(input); - return Promise.resolve({ ok: true, data: { id: input.id, title: 'First' } as TRecord }); - }, - insert( - input: DbInsertInput, - ): Promise> { - calls.insert.push(input); - return Promise.resolve({ - ok: true, - data: [{ id: 'post-2', title: 'Created' } as TRecord], - }); - }, - update( - input: DbUpdateInput, - ): Promise> { - calls.update.push(input); - return Promise.resolve({ - ok: true, - data: [{ id: 'post-1', title: 'Updated' } as TRecord], - }); - }, - delete(input: DbDeleteInput): Promise> { - calls.delete.push(input); - return Promise.resolve({ ok: true, data: [{ id: 'post-1', title: 'First' } as TRecord] }); - }, - }; - return { adapter, calls }; -} - -function createGeneratedExecutor(adapter?: DbAdapter) { - return createRuntimeDataSourceOperationExecutor({ - databaseAdapters: adapter === undefined ? undefined : { 'primary-db': adapter }, - }); -} - -async function executeGeneratedOperation( - operationId: string, - input?: Readonly>, - adapter?: DbAdapter, -) { - const dataSource = createGeneratedDataSource(); - return createGeneratedExecutor(adapter)({ - dataSource, - endpoint: getFixtureEndpoint(dataSource, 'posts'), - input, - operation: { dataSourceId: 'posts-api', endpointId: 'posts', operationId }, - }); -} - -describe('createRuntimeDataSourceOperationExecutor', () => { - it('executes external REST operations through the data-sources test runner', async () => { - const dataSource = getFixtureDataSource(createExternalDataSources()); - const endpoint = getFixtureEndpoint(dataSource); - const calls: string[] = []; - const executor = createRuntimeDataSourceOperationExecutor({ - fetch: (url, init) => { - calls.push(`${init.method} ${url}`); - return Promise.resolve({ - status: 200, - headers: { 'content-type': 'application/json' }, - text: () => Promise.resolve('{"moves":[{"san":"e4"}]}'), - }); - }, - }); - - const result = await executor({ - dataSource, - endpoint, - input: { fen: 'start' }, - operation: { - dataSourceId: 'chess', - endpointId: 'opening', - operationId: 'opening.moves', - }, - }); - - expect(calls).toEqual(['GET https://api.ankhorage.com/v1/chess/opening?fen=start']); - expect(result).toEqual({ ok: true, data: { moves: [{ san: 'e4' }] }, diagnostics: [] }); - }); - - it('routes generated list/read operations through the referenced database adapter', async () => { - const { adapter, calls } = createDatabaseFixture(); - - expect( - await executeGeneratedOperation('posts.list', { limit: 10, offset: 2 }, adapter), - ).toEqual({ - ok: true, - data: [{ id: 'post-1', title: 'First' }], - diagnostics: [], - }); - expect(await executeGeneratedOperation('posts.read', { id: 'post-1' }, adapter)).toEqual({ - ok: true, - data: { id: 'post-1', title: 'First' }, - diagnostics: [], - }); - - expect(calls.select).toEqual([ - { table: 'posts', schema: 'public', page: { limit: 10, offset: 2 } }, - ]); - expect(calls.findById).toEqual([ - { table: 'posts', schema: 'public', id: 'post-1', idField: 'id' }, - ]); - }); - - it('routes generated create/update/delete operations with canonical result shapes', async () => { - const { adapter, calls } = createDatabaseFixture(); - - expect(await executeGeneratedOperation('posts.create', { title: 'Created' }, adapter)).toEqual({ - ok: true, - data: { id: 'post-2', title: 'Created' }, - diagnostics: [], - }); - expect( - await executeGeneratedOperation('posts.update', { id: 'post-1', title: 'Updated' }, adapter), - ).toEqual({ - ok: true, - data: { id: 'post-1', title: 'Updated' }, - diagnostics: [], - }); - expect(await executeGeneratedOperation('posts.delete', { id: 'post-1' }, adapter)).toEqual({ - ok: true, - data: { deleted: true }, - diagnostics: [], - }); - - expect(calls.insert).toEqual([ - { table: 'posts', schema: 'public', values: { title: 'Created' } }, - ]); - expect(calls.update).toEqual([ - { - table: 'posts', - schema: 'public', - values: { title: 'Updated' }, - filters: [{ field: 'id', operator: 'eq', value: 'post-1' }], - }, - ]); - expect(calls.delete).toEqual([ - { - table: 'posts', - schema: 'public', - filters: [{ field: 'id', operator: 'eq', value: 'post-1' }], - }, - ]); - }); - - it('returns a missing-adapter diagnostic instead of falling through to HTTP', async () => { - const result = await executeGeneratedOperation('posts.list'); - - expect(result.ok).toBe(false); - if (!result.ok) { - expect(result.diagnostics[0]).toMatchObject({ - code: 'missing-adapter', - dataSourceId: 'posts-api', - endpointId: 'posts', - operationId: 'posts.list', - }); - } - }); - - it('returns diagnostics when operation input does not resolve to an object', async () => { - const dataSource = getFixtureDataSource(createExternalDataSources()); - const endpoint = getFixtureEndpoint(dataSource); - const executor = createRuntimeDataSourceOperationExecutor({}); - - const result = await executor({ - dataSource, - endpoint, - input: 'not-an-object', - operation: { - dataSourceId: 'chess', - endpointId: 'opening', - operationId: 'opening.moves', - }, - }); - - expect(result.ok).toBe(false); - if (!result.ok) { - expect(result.diagnostics).toEqual([ - { - code: 'invalid-config', - dataSourceId: 'chess', - endpointId: 'opening', - operationId: 'opening.moves', - message: 'Operation input must resolve to an object.', - severity: 'error', - }, - ]); - } - }); -}); From a2701ed0438671f0fa086e8f7bdc02ce9d64eee1 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:48:48 +0200 Subject: [PATCH 20/43] test: migrate repeat bindings to canonical APIs --- src/runtimeRepeat.test.ts | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/runtimeRepeat.test.ts b/src/runtimeRepeat.test.ts index e43e2e3..67582bb 100644 --- a/src/runtimeRepeat.test.ts +++ b/src/runtimeRepeat.test.ts @@ -1,7 +1,7 @@ import type { + ApiDefinitionList, BindingValue, ComponentDataBindingRegistry, - DataSourceRegistry, UiNode, } from '@ankhorage/contracts'; import { describe, expect, it } from 'bun:test'; @@ -15,11 +15,10 @@ import { resolveRuntimeRepeatItemsSync, } from './runtimeRepeat'; -function createDataSources(): DataSourceRegistry { - return { - 'nutrition-api': { +function createApis(): ApiDefinitionList { + return [ + { id: 'nutrition-api', - kind: 'api', origin: 'external', protocol: 'rest', baseUrl: 'https://nutrition.example.com', @@ -40,7 +39,7 @@ function createDataSources(): DataSourceRegistry { }, }, }, - }; + ]; } function createRepeatedGridNode(): UiNode { @@ -51,7 +50,7 @@ function createRepeatedGridNode(): UiNode { source: { kind: 'operation', operation: { - dataSourceId: 'nutrition-api', + apiId: 'nutrition-api', endpointId: 'products', operationId: 'products.list', }, @@ -137,7 +136,7 @@ describe('runtime repeat resolution', () => { } const repeatResult = await resolveRuntimeRepeatItemsAsync(repeat, { - dataSources: createDataSources(), + apis: createApis(), executeOperation: () => Promise.resolve({ ok: true, @@ -198,7 +197,7 @@ describe('runtime repeat resolution', () => { } const result = resolveRuntimeRepeatItemsSync(repeat, { - dataSources: createDataSources(), + apis: createApis(), node, operationResults: { 'nutrition-api:products:products.list': { @@ -220,7 +219,7 @@ describe('runtime repeat resolution', () => { } const result = await resolveRuntimeRepeatItemsAsync(repeat, { - dataSources: createDataSources(), + apis: createApis(), executeOperation: () => Promise.resolve({ ok: true, @@ -234,8 +233,8 @@ describe('runtime repeat resolution', () => { expect(result.items).toEqual([]); expect(result.diagnostics).toEqual([ { + apiId: 'nutrition-api', code: 'invalid-config', - dataSourceId: 'nutrition-api', endpointId: 'products', operationId: 'products.list', message: 'Repeat source must resolve to an array.', @@ -252,7 +251,7 @@ describe('runtime repeat resolution', () => { } const result = await resolveRuntimeRepeatItemsAsync(repeat, { - dataSources: createDataSources(), + apis: createApis(), executeOperation: () => Promise.resolve({ ok: true, From f5d38106c018a6b983a0847975dd1f05a41ee359 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:49:07 +0200 Subject: [PATCH 21/43] test: bind screen loader cache keys by API --- src/runtimeScreenLoaders.arrayPath.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtimeScreenLoaders.arrayPath.test.ts b/src/runtimeScreenLoaders.arrayPath.test.ts index 767a067..1b08f10 100644 --- a/src/runtimeScreenLoaders.arrayPath.test.ts +++ b/src/runtimeScreenLoaders.arrayPath.test.ts @@ -8,13 +8,13 @@ import { createRuntimeBindingOperationKey } from './runtimeBindings'; import { createRuntimeScreenLoaderRequestKey } from './runtimeScreenLoaders'; const productListOperation: BindingOperationRef = { - dataSourceId: 'nutrition-api', + apiId: 'nutrition-api', endpointId: 'products', operationId: 'nutrition.products.list', }; const productDetailOperation: BindingOperationRef = { - dataSourceId: 'nutrition-api', + apiId: 'nutrition-api', endpointId: 'products', operationId: 'nutrition.products.getById', }; From df2a0cd6df84b0221c44897136bfbe416393d5a8 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:51:01 +0200 Subject: [PATCH 22/43] test: cover canonical screen loader execution --- src/runtimeScreenLoaders.execution.test.ts | 184 +++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/runtimeScreenLoaders.execution.test.ts diff --git a/src/runtimeScreenLoaders.execution.test.ts b/src/runtimeScreenLoaders.execution.test.ts new file mode 100644 index 0000000..5401f8c --- /dev/null +++ b/src/runtimeScreenLoaders.execution.test.ts @@ -0,0 +1,184 @@ +import type { + ApiDefinitionList, + BindingOperationRef, + BindingValue, + ComponentDataBindingRegistry, + OperationScreenDataLoaderDefinition, + ScreenSpec, +} from '@ankhorage/contracts'; +import { describe, expect, it } from 'bun:test'; + +import { createRuntimeBindingOperationKey, resolveRuntimeBindings } from './runtimeBindings'; +import { + createRuntimeScreenLoaderRequestKey, + executeRuntimeScreenOperationLoaders, + resolveScreenOperationLoaders, +} from './runtimeScreenLoaders'; + +const productDetailOperation: BindingOperationRef = { + apiId: 'nutrition', + endpointId: 'products', + operationId: 'products.getById', +}; + +function createApis(): ApiDefinitionList { + return [ + { + id: 'nutrition', + origin: 'external', + protocol: 'rest', + baseUrl: 'https://api.ankhorage.com/v1/nutrition', + endpoints: { + products: { + id: 'products', + kind: 'http', + operations: { + 'products.getById': { + id: 'products.getById', + endpointId: 'products', + protocol: 'http', + intent: 'read', + method: 'GET', + path: '/products/{id}', + }, + }, + }, + }, + }, + ]; +} + +function createLoader(id = 'product-detail'): OperationScreenDataLoaderDefinition { + return { + kind: 'operation', + id, + operation: productDetailOperation, + input: { + id: { + kind: 'source', + source: { kind: 'context', path: 'route.params.id' }, + }, + }, + }; +} + +function createScreen( + dataLoaders: readonly OperationScreenDataLoaderDefinition[] = [createLoader()], +): ScreenSpec { + return { + id: 'product-detail', + name: 'Product Detail', + root: { id: 'product-header', type: 'ProductHeader' }, + dataLoaders, + }; +} + +function createBindings(): ComponentDataBindingRegistry { + return { + 'product-header': { + componentId: 'product-header', + props: { + title: { + source: { + kind: 'operation', + operation: productDetailOperation, + path: 'product.name', + }, + }, + }, + }, + }; +} + +function routeContext(id: string): Record { + return { route: { params: { id } } }; +} + +describe('runtime screen loader execution', () => { + it('resolves input, executes the selected API operation, and caches its result', async () => { + const screen = createScreen(); + const calls: { readonly input?: BindingValue; readonly operationId: string }[] = []; + const result = await executeRuntimeScreenOperationLoaders({ + apis: createApis(), + bindingContext: routeContext('product-1'), + executeOperation: ({ input, operation }) => { + calls.push({ input, operationId: operation.operationId }); + return Promise.resolve({ + ok: true, + data: { product: { id: 'product-1', name: 'Bio Greek Yogurt' } }, + }); + }, + loaders: resolveScreenOperationLoaders(screen), + screen, + }); + + expect(calls).toEqual([{ input: { id: 'product-1' }, operationId: 'products.getById' }]); + expect(result.diagnostics).toEqual([]); + expect(result.operationResults).toEqual({ + [createRuntimeBindingOperationKey(productDetailOperation)]: { + product: { id: 'product-1', name: 'Bio Greek Yogurt' }, + }, + }); + expect( + resolveRuntimeBindings({ + apis: createApis(), + dataBindings: createBindings(), + node: screen.root, + operationResults: result.operationResults, + props: {}, + }).props, + ).toEqual({ title: 'Bio Greek Yogurt' }); + }); + + it('keys requests by resolved loader input rather than surrounding context identity', () => { + const loaders = [createLoader()]; + const first = createRuntimeScreenLoaderRequestKey({ + bindingContext: routeContext('product-1'), + loaders, + screenId: 'product-detail', + }); + const equivalent = createRuntimeScreenLoaderRequestKey({ + bindingContext: { ...routeContext('product-1'), session: { locale: 'de-CH' } }, + loaders, + screenId: 'product-detail', + }); + const changed = createRuntimeScreenLoaderRequestKey({ + bindingContext: routeContext('product-2'), + loaders, + screenId: 'product-detail', + }); + + expect(equivalent).toBe(first); + expect(changed).not.toBe(first); + }); + + it('reports duplicate API operation loaders and a missing executor deterministically', async () => { + const screen = createScreen([createLoader('first'), createLoader('second')]); + const result = await executeRuntimeScreenOperationLoaders({ + apis: createApis(), + bindingContext: routeContext('product-1'), + loaders: resolveScreenOperationLoaders(screen), + screen, + }); + + expect(result.diagnostics).toEqual([ + { + apiId: 'nutrition', + code: 'duplicate-operation-id', + endpointId: 'products', + message: + "Screen operation loaders must not reuse operation key 'nutrition:products:products.getById' on the same screen.", + operationId: 'products.getById', + severity: 'error', + }, + { + apiId: 'nutrition', + code: 'missing-adapter', + endpointId: 'products', + message: 'Screen API operation loader requires an injected operation executor.', + operationId: 'products.getById', + severity: 'error', + }, + ]); + }); +}); From 29198d08bd9ba5645d50b71ba93e5ef3d7a4445a Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:51:13 +0200 Subject: [PATCH 23/43] test: preserve screen loader lifecycle semantics --- src/runtimeScreenLoaders.lifecycle.test.ts | 119 +++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/runtimeScreenLoaders.lifecycle.test.ts diff --git a/src/runtimeScreenLoaders.lifecycle.test.ts b/src/runtimeScreenLoaders.lifecycle.test.ts new file mode 100644 index 0000000..1ec54f2 --- /dev/null +++ b/src/runtimeScreenLoaders.lifecycle.test.ts @@ -0,0 +1,119 @@ +import type { BindingOperationRef } from '@ankhorage/contracts'; +import { describe, expect, it } from 'bun:test'; + +import { createRuntimeBindingOperationKey } from './runtimeBindings'; +import { + beginRuntimeScreenOperationLoaderRequest, + completeRuntimeScreenOperationLoaderRequest, + createIdleRuntimeScreenOperationLoaderState, + createPendingRuntimeScreenOperationLoaderState, + createRuntimeScreenOperationLoaderLifecycle, +} from './runtimeScreenLoaders'; + +const operation: BindingOperationRef = { + apiId: 'nutrition', + endpointId: 'products', + operationId: 'products.getById', +}; + +function loadedResult(productId: string) { + return { + dependencyKey: `resolved:${productId}`, + diagnostics: [], + operationResults: { + [createRuntimeBindingOperationKey(operation)]: { + product: { id: productId }, + }, + }, + }; +} + +describe('runtime screen loader lifecycle', () => { + it('keeps screens without loaders as a stable no-op', () => { + const state = createIdleRuntimeScreenOperationLoaderState({ + dependencyKey: 'screen:detail:no-operation-loaders', + }); + const result = beginRuntimeScreenOperationLoaderRequest({ + hasLoaders: false, + lifecycle: createRuntimeScreenOperationLoaderLifecycle(), + requestKey: 'screen:detail:no-operation-loaders', + state, + }); + + expect(result.shouldExecute).toBe(false); + expect(result.state).toBe(state); + expect(result.state.operationResults).toEqual({}); + }); + + it('does not execute again when the request key is unchanged', () => { + const requestKey = 'request:product-1'; + const initial = createPendingRuntimeScreenOperationLoaderState({ dependencyKey: requestKey }); + const first = beginRuntimeScreenOperationLoaderRequest({ + hasLoaders: true, + lifecycle: createRuntimeScreenOperationLoaderLifecycle(), + requestKey, + state: initial, + }); + const completed = completeRuntimeScreenOperationLoaderRequest({ + lifecycle: first.lifecycle, + requestId: first.requestId ?? 0, + result: loadedResult('product-1'), + state: first.state, + }); + const equivalent = beginRuntimeScreenOperationLoaderRequest({ + hasLoaders: true, + lifecycle: first.lifecycle, + requestKey, + state: completed.state, + }); + + expect(first.shouldExecute).toBe(true); + expect(completed.accepted).toBe(true); + expect(equivalent.shouldExecute).toBe(false); + expect(equivalent.state).toBe(completed.state); + }); + + it('clears stale results and rejects completion from an older request', () => { + const firstKey = 'request:product-1'; + const secondKey = 'request:product-2'; + const initial = createPendingRuntimeScreenOperationLoaderState({ dependencyKey: firstKey }); + const first = beginRuntimeScreenOperationLoaderRequest({ + hasLoaders: true, + lifecycle: createRuntimeScreenOperationLoaderLifecycle(), + requestKey: firstKey, + state: initial, + }); + const completedFirst = completeRuntimeScreenOperationLoaderRequest({ + lifecycle: first.lifecycle, + requestId: first.requestId ?? 0, + result: loadedResult('product-1'), + state: first.state, + }); + const second = beginRuntimeScreenOperationLoaderRequest({ + hasLoaders: true, + lifecycle: first.lifecycle, + requestKey: secondKey, + state: completedFirst.state, + }); + const stale = completeRuntimeScreenOperationLoaderRequest({ + lifecycle: second.lifecycle, + requestId: first.requestId ?? 0, + result: loadedResult('stale'), + state: second.state, + }); + const fresh = completeRuntimeScreenOperationLoaderRequest({ + lifecycle: second.lifecycle, + requestId: second.requestId ?? 0, + result: loadedResult('product-2'), + state: second.state, + }); + + expect(second.shouldExecute).toBe(true); + expect(second.state.operationResults).toEqual({}); + expect(second.state.renderVersion).toBe(1); + expect(stale.accepted).toBe(false); + expect(stale.state).toBe(second.state); + expect(fresh.accepted).toBe(true); + expect(fresh.state.operationResults).toEqual(loadedResult('product-2').operationResults); + }); +}); From 3b74f89e475b5c6094d612b71640c0aaaccc2ba1 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:51:22 +0200 Subject: [PATCH 24/43] test: split screen loader coverage by concern --- src/runtimeScreenLoaders.test.ts | 645 ------------------------------- 1 file changed, 645 deletions(-) delete mode 100644 src/runtimeScreenLoaders.test.ts diff --git a/src/runtimeScreenLoaders.test.ts b/src/runtimeScreenLoaders.test.ts deleted file mode 100644 index c96a835..0000000 --- a/src/runtimeScreenLoaders.test.ts +++ /dev/null @@ -1,645 +0,0 @@ -import type { - BindingOperationRef, - BindingValue, - ComponentDataBindingRegistry, - DataSourceRegistry, - OperationScreenDataLoaderDefinition, - ScreenSpec, - UiNode, -} from '@ankhorage/contracts'; -import { describe, expect, it } from 'bun:test'; - -import { createRuntimeBindingOperationKey, resolveRuntimeBindings } from './runtimeBindings'; -import { - beginRuntimeScreenOperationLoaderRequest, - completeRuntimeScreenOperationLoaderRequest, - createIdleRuntimeScreenOperationLoaderState, - createPendingRuntimeScreenOperationLoaderState, - createRuntimeScreenLoaderRequestKey, - createRuntimeScreenOperationLoaderLifecycle, - executeRuntimeScreenOperationLoaders, - resolveScreenOperationLoaders, -} from './runtimeScreenLoaders'; - -const productDetailOperation: BindingOperationRef = { - dataSourceId: 'nutrition-api', - endpointId: 'products', - operationId: 'nutrition.products.getById', -}; - -const productListOperation: BindingOperationRef = { - dataSourceId: 'nutrition-api', - endpointId: 'products', - operationId: 'nutrition.products.list', -}; - -function createDataSources(): DataSourceRegistry { - return { - 'nutrition-api': { - id: 'nutrition-api', - kind: 'api', - origin: 'external', - protocol: 'rest', - baseUrl: 'https://nutrition.example.com', - endpoints: { - products: { - id: 'products', - kind: 'http', - operations: { - 'nutrition.products.getById': { - id: 'nutrition.products.getById', - endpointId: 'products', - protocol: 'http', - intent: 'read', - method: 'GET', - path: '/products/{id}', - }, - }, - }, - }, - }, - }; -} - -function createDetailScreenRoot(): UiNode { - return { - id: 'product-header', - type: 'ProductHeader', - }; -} - -function createDetailLoader(id = 'product-detail'): OperationScreenDataLoaderDefinition { - return { - kind: 'operation', - id, - operation: productDetailOperation, - input: { - id: { - kind: 'source', - source: { - kind: 'context', - path: 'route.params.id', - }, - }, - }, - }; -} - -function createCachedOperationInputLoader( - id = 'product-from-cache', -): OperationScreenDataLoaderDefinition { - return { - kind: 'operation', - id, - operation: productDetailOperation, - input: { - id: { - kind: 'source', - source: { - kind: 'operation', - operation: productListOperation, - path: 'products.0.id', - }, - }, - }, - }; -} - -function createDetailScreen(args?: { - readonly dataLoaders?: readonly OperationScreenDataLoaderDefinition[]; -}): ScreenSpec { - return { - id: 'product-detail', - name: 'Product Detail', - root: createDetailScreenRoot(), - dataLoaders: args?.dataLoaders ?? [createDetailLoader()], - }; -} - -function createDetailBindings(): ComponentDataBindingRegistry { - return { - 'product-header': { - componentId: 'product-header', - componentType: 'ProductHeader', - props: { - title: { - source: { - kind: 'operation', - operation: productDetailOperation, - path: 'product.name', - }, - }, - subtitle: { - source: { - kind: 'operation', - operation: productDetailOperation, - path: 'product.brand', - }, - }, - caption: { - source: { - kind: 'operation', - operation: productDetailOperation, - path: 'product.barcode', - }, - }, - }, - }, - }; -} - -function createRouteBindingContext(id: string): Record { - return { - route: { - params: { - id, - }, - }, - }; -} - -describe('runtime screen operation loaders', () => { - it('resolves loader input from route params, executes the operation, and caches the result under the standard operation key', async () => { - const screen = createDetailScreen(); - const calls: { readonly input?: BindingValue; readonly operationId: string }[] = []; - - const result = await executeRuntimeScreenOperationLoaders({ - bindingContext: { - route: { - params: { - id: 'product-1', - }, - }, - }, - dataSources: createDataSources(), - executeOperation: ({ input, operation }) => { - calls.push({ - input, - operationId: operation.operationId, - }); - - return Promise.resolve({ - ok: true as const, - data: { - product: { - name: 'Bio Greek Yogurt 250 g', - brand: 'Migros', - barcode: '7612345678901', - }, - }, - }); - }, - loaders: resolveScreenOperationLoaders(screen), - screen, - }); - - expect(calls).toEqual([ - { - input: { id: 'product-1' }, - operationId: 'nutrition.products.getById', - }, - ]); - expect(result.diagnostics).toEqual([]); - expect(result.operationResults).toEqual({ - [createRuntimeBindingOperationKey(productDetailOperation)]: { - product: { - name: 'Bio Greek Yogurt 250 g', - brand: 'Migros', - barcode: '7612345678901', - }, - }, - }); - - expect( - resolveRuntimeBindings({ - dataBindings: createDetailBindings(), - dataSources: createDataSources(), - node: createDetailScreenRoot(), - operationResults: result.operationResults, - props: {}, - }).props, - ).toEqual({ - caption: '7612345678901', - subtitle: 'Migros', - title: 'Bio Greek Yogurt 250 g', - }); - }); - - it('changes both the request key and resolved dependency key when the route-param input changes', async () => { - const screen = createDetailScreen(); - const loaders = resolveScreenOperationLoaders(screen); - - const firstRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: createRouteBindingContext('product-1'), - loaders, - screenId: screen.id, - }); - const secondRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: createRouteBindingContext('product-2'), - loaders, - screenId: screen.id, - }); - - expect(firstRequestKey).not.toBe(secondRequestKey); - - const firstResult = await executeRuntimeScreenOperationLoaders({ - bindingContext: { - route: { - params: { - id: 'product-1', - }, - }, - }, - dataSources: createDataSources(), - executeOperation: () => - Promise.resolve({ - ok: true as const, - data: { - product: { - id: 'product-1', - }, - }, - }), - loaders, - screen, - }); - const secondResult = await executeRuntimeScreenOperationLoaders({ - bindingContext: { - route: { - params: { - id: 'product-2', - }, - }, - }, - dataSources: createDataSources(), - executeOperation: () => - Promise.resolve({ - ok: true as const, - data: { - product: { - id: 'product-2', - }, - }, - }), - loaders, - screen, - }); - - expect(firstResult.dependencyKey).not.toBe(secondResult.dependencyKey); - }); - - it('keeps the same request key when surrounding binding-context identity changes but the resolved input does not', () => { - const screen = createDetailScreen(); - const loaders = resolveScreenOperationLoaders(screen); - - const firstRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: createRouteBindingContext('product-1'), - loaders, - screenId: screen.id, - }); - const secondRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: { - route: { - params: { - id: 'product-1', - }, - }, - session: { - locale: 'de-CH', - }, - }, - loaders, - screenId: screen.id, - }); - - expect(firstRequestKey).toBe(secondRequestKey); - }); - - it('keeps the same request key when unrelated inherited operation results change', () => { - const loaders = [createCachedOperationInputLoader()]; - const firstRequestKey = createRuntimeScreenLoaderRequestKey({ - loaders, - operationResults: { - [createRuntimeBindingOperationKey(productListOperation)]: { - products: [{ id: 'product-1' }], - }, - }, - screenId: 'product-detail', - }); - const secondRequestKey = createRuntimeScreenLoaderRequestKey({ - loaders, - operationResults: { - [createRuntimeBindingOperationKey(productListOperation)]: { - products: [{ id: 'product-1' }], - }, - unrelated: { - ignored: true, - }, - }, - screenId: 'product-detail', - }); - - expect(firstRequestKey).toBe(secondRequestKey); - }); - - it('changes the request key when the loader definition or operation reference changes', () => { - const screenId = 'product-detail'; - const routeBindingContext = createRouteBindingContext('product-1'); - const defaultRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: routeBindingContext, - loaders: [createDetailLoader()], - screenId, - }); - const changedLoaderRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: routeBindingContext, - loaders: [createDetailLoader('product-detail-alt')], - screenId, - }); - const changedOperationRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: routeBindingContext, - loaders: [ - { - ...createDetailLoader(), - operation: { - ...productDetailOperation, - operationId: 'nutrition.products.getBySlug', - }, - }, - ], - screenId, - }); - - expect(changedLoaderRequestKey).not.toBe(defaultRequestKey); - expect(changedOperationRequestKey).not.toBe(defaultRequestKey); - }); - - it('treats screens without operation loaders as a stable no-op lifecycle', () => { - const screen = createDetailScreen({ - dataLoaders: [], - }); - const loaders = resolveScreenOperationLoaders(screen); - const firstRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: createRouteBindingContext('product-1'), - loaders, - screenId: screen.id, - }); - const secondRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: createRouteBindingContext('product-2'), - loaders, - screenId: screen.id, - }); - const emptyState = createIdleRuntimeScreenOperationLoaderState({ - dependencyKey: firstRequestKey, - }); - - expect(firstRequestKey).toBe(secondRequestKey); - - const firstRender = beginRuntimeScreenOperationLoaderRequest({ - hasLoaders: false, - lifecycle: createRuntimeScreenOperationLoaderLifecycle(), - requestKey: firstRequestKey, - state: emptyState, - }); - const secondRender = beginRuntimeScreenOperationLoaderRequest({ - hasLoaders: false, - lifecycle: firstRender.lifecycle, - requestKey: secondRequestKey, - state: firstRender.state, - }); - - expect(firstRender.shouldExecute).toBe(false); - expect(secondRender.shouldExecute).toBe(false); - expect(firstRender.state).toBe(emptyState); - expect(secondRender.state).toBe(emptyState); - expect(emptyState.renderVersion).toBe(0); - expect(emptyState.operationResults).toEqual({}); - expect(emptyState.diagnostics).toEqual([]); - }); - - it('does not re-execute or clear results when route params are semantically unchanged', () => { - const screen = createDetailScreen(); - const loaders = resolveScreenOperationLoaders(screen); - const firstRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: createRouteBindingContext('product-1'), - loaders, - screenId: screen.id, - }); - const equivalentRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: createRouteBindingContext('product-1'), - loaders, - screenId: screen.id, - }); - const initialState = createPendingRuntimeScreenOperationLoaderState({ - dependencyKey: firstRequestKey, - }); - const firstRequest = beginRuntimeScreenOperationLoaderRequest({ - hasLoaders: true, - lifecycle: createRuntimeScreenOperationLoaderLifecycle(), - requestKey: firstRequestKey, - state: initialState, - }); - const completed = completeRuntimeScreenOperationLoaderRequest({ - lifecycle: firstRequest.lifecycle, - requestId: firstRequest.requestId ?? 0, - result: { - dependencyKey: 'resolved:product-1', - diagnostics: [], - operationResults: { - [createRuntimeBindingOperationKey(productDetailOperation)]: { - product: { - id: 'product-1', - name: 'Loaded Product', - }, - }, - }, - }, - state: firstRequest.state, - }); - const equivalentRender = beginRuntimeScreenOperationLoaderRequest({ - hasLoaders: true, - lifecycle: firstRequest.lifecycle, - requestKey: equivalentRequestKey, - state: completed.state, - }); - - expect(firstRequestKey).toBe(equivalentRequestKey); - expect(firstRequest.shouldExecute).toBe(true); - expect(completed.accepted).toBe(true); - expect(equivalentRender.shouldExecute).toBe(false); - expect(equivalentRender.state).toBe(completed.state); - expect(equivalentRender.state.operationResults).toEqual(completed.state.operationResults); - expect(equivalentRender.state.renderVersion).toBe(0); - }); - - it('clears stale results, re-executes, and ignores stale async completion when route params change', () => { - const screen = createDetailScreen(); - const loaders = resolveScreenOperationLoaders(screen); - const firstRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: createRouteBindingContext('product-1'), - loaders, - screenId: screen.id, - }); - const secondRequestKey = createRuntimeScreenLoaderRequestKey({ - bindingContext: createRouteBindingContext('product-2'), - loaders, - screenId: screen.id, - }); - const initialState = createPendingRuntimeScreenOperationLoaderState({ - dependencyKey: firstRequestKey, - }); - const firstRequest = beginRuntimeScreenOperationLoaderRequest({ - hasLoaders: true, - lifecycle: createRuntimeScreenOperationLoaderLifecycle(), - requestKey: firstRequestKey, - state: initialState, - }); - const completedFirstRequest = completeRuntimeScreenOperationLoaderRequest({ - lifecycle: firstRequest.lifecycle, - requestId: firstRequest.requestId ?? 0, - result: { - dependencyKey: 'resolved:product-1', - diagnostics: [], - operationResults: { - [createRuntimeBindingOperationKey(productDetailOperation)]: { - product: { - id: 'product-1', - name: 'Old Product', - }, - }, - }, - }, - state: firstRequest.state, - }); - const secondRequest = beginRuntimeScreenOperationLoaderRequest({ - hasLoaders: true, - lifecycle: firstRequest.lifecycle, - requestKey: secondRequestKey, - state: completedFirstRequest.state, - }); - const staleCompletion = completeRuntimeScreenOperationLoaderRequest({ - lifecycle: secondRequest.lifecycle, - requestId: firstRequest.requestId ?? 0, - result: { - dependencyKey: 'resolved:stale', - diagnostics: [], - operationResults: { - [createRuntimeBindingOperationKey(productDetailOperation)]: { - product: { - id: 'product-1', - name: 'Stale Product', - }, - }, - }, - }, - state: secondRequest.state, - }); - const acceptedCompletion = completeRuntimeScreenOperationLoaderRequest({ - lifecycle: secondRequest.lifecycle, - requestId: secondRequest.requestId ?? 0, - result: { - dependencyKey: 'resolved:product-2', - diagnostics: [], - operationResults: { - [createRuntimeBindingOperationKey(productDetailOperation)]: { - product: { - id: 'product-2', - name: 'Fresh Product', - }, - }, - }, - }, - state: secondRequest.state, - }); - - expect(secondRequest.shouldExecute).toBe(true); - expect(secondRequest.state).toEqual({ - dependencyKey: secondRequestKey, - diagnostics: [], - operationResults: {}, - renderVersion: 1, - }); - expect(staleCompletion.accepted).toBe(false); - expect(staleCompletion.state).toBe(secondRequest.state); - expect(acceptedCompletion.accepted).toBe(true); - expect(acceptedCompletion.state.operationResults).toEqual({ - [createRuntimeBindingOperationKey(productDetailOperation)]: { - product: { - id: 'product-2', - name: 'Fresh Product', - }, - }, - }); - }); - - it('includes planning diagnostics alongside execution diagnostics', async () => { - const screen = createDetailScreen({ - dataLoaders: [createDetailLoader('product-detail-a'), createDetailLoader('product-detail-b')], - }); - - const result = await executeRuntimeScreenOperationLoaders({ - bindingContext: createRouteBindingContext('product-1'), - loaders: resolveScreenOperationLoaders(screen), - screen, - }); - - expect(result.diagnostics).toEqual([ - { - code: 'duplicate-operation-id', - dataSourceId: 'nutrition-api', - endpointId: 'products', - operationId: 'nutrition.products.getById', - message: - "Screen operation loaders must not reuse operation key 'nutrition-api:products:nutrition.products.getById' on the same screen.", - severity: 'error', - }, - { - code: 'missing-adapter', - dataSourceId: 'nutrition-api', - endpointId: 'products', - operationId: 'nutrition.products.getById', - message: 'Screen operation loader requires an injected operation executor.', - severity: 'error', - }, - ]); - }); - - it('reports one duplicate operation-loader diagnostic per duplicated operation key', async () => { - const screen = createDetailScreen({ - dataLoaders: [createDetailLoader('product-detail-a'), createDetailLoader('product-detail-b')], - }); - - const result = await executeRuntimeScreenOperationLoaders({ - bindingContext: { - route: { - params: { - id: 'product-1', - }, - }, - }, - dataSources: createDataSources(), - executeOperation: () => - Promise.resolve({ - ok: true as const, - data: { - product: { - id: 'product-1', - }, - }, - }), - loaders: resolveScreenOperationLoaders(screen), - screen, - }); - - expect(result.diagnostics).toEqual([ - { - code: 'duplicate-operation-id', - dataSourceId: 'nutrition-api', - endpointId: 'products', - operationId: 'nutrition.products.getById', - message: - "Screen operation loaders must not reuse operation key 'nutrition-api:products:nutrition.products.getById' on the same screen.", - severity: 'error', - }, - ]); - }); -}); From e98aba7e74d2c50faf0c84d3751fc37d1f56de6c Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:52:03 +0200 Subject: [PATCH 25/43] test: split runtime action event coverage --- src/runtimeActionRegistry.actions.test.ts | 156 ++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/runtimeActionRegistry.actions.test.ts diff --git a/src/runtimeActionRegistry.actions.test.ts b/src/runtimeActionRegistry.actions.test.ts new file mode 100644 index 0000000..3f3ea26 --- /dev/null +++ b/src/runtimeActionRegistry.actions.test.ts @@ -0,0 +1,156 @@ +import type { ComponentDataBindingRegistry, UiNode } from '@ankhorage/contracts'; +import { describe, expect, it } from 'bun:test'; + +import { + createComponentEventFromHandlerArgs, + createRuntimeActionRegistry, + dispatchRuntimeComponentEvent, + wrapRuntimeEventProps, +} from './runtimeActionRegistry'; + +function isNoArgFunction(value: unknown): value is () => unknown { + return typeof value === 'function'; +} + +function createActionBindings(): ComponentDataBindingRegistry { + return { + 'save-button': { + componentId: 'save-button', + events: { + press: [{ target: { kind: 'action', type: 'console' } }], + }, + }, + }; +} + +describe('runtime action registry actions', () => { + it('dispatches component event bindings to registered action handlers', async () => { + const handled: object[] = []; + const diagnostics = await dispatchRuntimeComponentEvent({ + node: { id: 'contact-form', type: 'Form' }, + eventName: 'submit', + event: { + type: 'form.submit', + sourceNodeId: 'contact-form', + payload: { values: { message: ' Hello ' } }, + }, + dataBindings: { + 'contact-form': { + componentId: 'contact-form', + events: { + submit: [ + { + target: { kind: 'action', type: 'email.send' }, + input: { + message: { + kind: 'source', + source: { kind: 'event', path: 'payload.values.message' }, + transforms: ['trim'], + }, + }, + }, + ], + }, + }, + }, + actionHandlers: { + 'email.send': ({ resolvedPayload }) => { + if (resolvedPayload !== undefined) handled.push(resolvedPayload); + }, + }, + }); + + expect(diagnostics).toEqual([]); + expect(handled).toEqual([{ message: 'Hello' }]); + }); + + it('reports an action binding without an executor or handler', async () => { + const diagnostics = await dispatchRuntimeComponentEvent({ + node: { id: 'save-button', type: 'Button' }, + eventName: 'press', + event: { type: 'button.press', sourceNodeId: 'save-button', payload: {} }, + dataBindings: { + 'save-button': { + componentId: 'save-button', + events: { + press: [{ target: { kind: 'action', type: 'missing.action' } }], + }, + }, + }, + }); + + expect(diagnostics).toEqual([ + { + code: 'missing-action-handler', + message: + "Action 'missing.action' could not be executed because no runtime executor or handler is registered.", + severity: 'error', + }, + ]); + }); + + it('creates canonical form and scanner events from handler args', () => { + const formNode: UiNode = { id: 'contact-form', type: 'Form' }; + const scannerNode: UiNode = { id: 'scanner', type: 'BarcodeScannerView' }; + + expect( + createComponentEventFromHandlerArgs({ + node: formNode, + eventName: 'submit', + handlerArgs: [{ message: 'Hello' }], + }), + ).toEqual({ + type: 'form.submit', + sourceNodeId: 'contact-form', + payload: { values: { message: 'Hello' } }, + }); + expect( + createComponentEventFromHandlerArgs({ + node: scannerNode, + eventName: 'barcodeScanned', + handlerArgs: [{ value: '7612345678901', type: 'ean13' }], + }), + ).toEqual({ + type: 'barcodeScanned', + sourceNodeId: 'scanner', + payload: { value: '7612345678901', type: 'ean13' }, + }); + }); + + it('wraps bound event props while preserving existing handlers', () => { + const calls: string[] = []; + const props = wrapRuntimeEventProps({ + node: { id: 'save-button', type: 'Button' }, + dataBindings: createActionBindings(), + props: { + onPress: () => { + calls.push('existing'); + }, + }, + disableActions: false, + dispatchComponentEvent: ({ event }) => { + calls.push(event.type); + }, + }); + + if (!isNoArgFunction(props.onPress)) throw new TypeError('Expected onPress handler.'); + props.onPress(); + expect(calls).toEqual(['existing', 'button.press']); + }); + + it('supports imperative action handler registration and unregistration', async () => { + const handled: string[] = []; + const registry = createRuntimeActionRegistry({ dataBindings: createActionBindings() }); + const unregister = registry.registerActionHandler('console', ({ action }) => { + handled.push(action.type); + }); + const event = { type: 'button.press', sourceNodeId: 'save-button', payload: {} }; + const node: UiNode = { id: 'save-button', type: 'Button' }; + + await registry.dispatchComponentEvent({ node, eventName: 'press', event }); + unregister(); + await registry.dispatchComponentEvent({ node, eventName: 'press', event }); + + expect(handled).toEqual(['console']); + }); +}); From 1d42cc99c3c5d6b2c16a668db65086b54bacd4cc Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:52:26 +0200 Subject: [PATCH 26/43] test: cover canonical API event operations --- src/runtimeActionRegistry.operations.test.ts | 218 +++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 src/runtimeActionRegistry.operations.test.ts diff --git a/src/runtimeActionRegistry.operations.test.ts b/src/runtimeActionRegistry.operations.test.ts new file mode 100644 index 0000000..6fbf57e --- /dev/null +++ b/src/runtimeActionRegistry.operations.test.ts @@ -0,0 +1,218 @@ +import type { + ApiDefinitionList, + BindingOperationRef, + BindingValue, + ComponentDataBindingRegistry, + RuntimeBindingOperationResultCache, + UiNode, +} from '@ankhorage/contracts'; +import { describe, expect, it } from 'bun:test'; + +import { dispatchRuntimeComponentEvent } from './runtimeActionRegistry'; +import { createRuntimeBindingOperationKey, resolveRuntimeBindings } from './runtimeBindings'; + +const postsOperation: BindingOperationRef = { + apiId: 'cms', + endpointId: 'posts', + operationId: 'posts.list', +}; + +function createApis(): ApiDefinitionList { + return [ + { + id: 'cms', + origin: 'external', + protocol: 'rest', + baseUrl: 'https://cms.example.com', + endpoints: { + posts: { + id: 'posts', + kind: 'http', + operations: { + 'posts.list': { + id: 'posts.list', + endpointId: 'posts', + protocol: 'http', + intent: 'read', + method: 'GET', + path: '/posts', + }, + 'posts.create': { + id: 'posts.create', + endpointId: 'posts', + protocol: 'http', + intent: 'create', + method: 'POST', + path: '/posts', + }, + }, + }, + }, + }, + ]; +} + +function createOperationBindings(operation = postsOperation): ComponentDataBindingRegistry { + return { + 'refresh-posts-button': { + componentId: 'refresh-posts-button', + events: { + press: [{ target: { kind: 'operation', operation } }], + }, + }, + 'posts-list': { + componentId: 'posts-list', + props: { + items: { + source: { kind: 'operation', operation, path: 'items' }, + fallback: { value: [] }, + }, + }, + }, + }; +} + +function refreshEventArgs() { + const node: UiNode = { id: 'refresh-posts-button', type: 'Button' }; + return { + node, + eventName: 'press', + event: { type: 'button.press', sourceNodeId: node.id, payload: {} }, + } as const; +} + +describe('runtime action registry API operations', () => { + it('selects the canonical API operation before invoking the executor', async () => { + const calls: object[] = []; + const operation: BindingOperationRef = { + apiId: 'cms', + endpointId: 'posts', + operationId: 'posts.create', + }; + const diagnostics = await dispatchRuntimeComponentEvent({ + ...refreshEventArgs(), + apis: createApis(), + dataBindings: { + 'refresh-posts-button': { + componentId: 'refresh-posts-button', + events: { + press: [ + { + target: { kind: 'operation', operation }, + input: { title: { kind: 'literal', value: 'Hello' } }, + }, + ], + }, + }, + }, + executeOperation: ({ api, endpoint, input, operation: selectedOperation }) => { + calls.push({ + apiId: api.id, + endpointId: endpoint.id, + input, + operationId: selectedOperation.operationId, + }); + return Promise.resolve({ ok: true, data: { id: 'post-1' } }); + }, + }); + + expect(diagnostics).toEqual([]); + expect(calls).toEqual([ + { + apiId: 'cms', + endpointId: 'posts', + input: { title: 'Hello' }, + operationId: 'posts.create', + }, + ]); + }); + + it('writes successful API results so synchronous prop bindings can reuse them', async () => { + const operationResults: Record = {}; + const dataBindings = createOperationBindings(); + const diagnostics = await dispatchRuntimeComponentEvent({ + ...refreshEventArgs(), + apis: createApis(), + dataBindings, + executeOperation: () => + Promise.resolve({ + ok: true, + data: { items: [{ id: 'post-1', title: 'Hello' }] }, + }), + writeOperationResult: (key, value) => { + operationResults[key] = value; + }, + }); + + const bound = resolveRuntimeBindings({ + apis: createApis(), + dataBindings, + node: { id: 'posts-list', type: 'List' }, + operationResults, + props: {}, + }); + + expect(diagnostics).toEqual([]); + expect(bound.props).toEqual({ items: [{ id: 'post-1', title: 'Hello' }] }); + }); + + it('does not replace cached API results when execution fails', async () => { + const operationKey = createRuntimeBindingOperationKey(postsOperation); + const operationResults: RuntimeBindingOperationResultCache = { + [operationKey]: { items: [{ id: 'existing-post' }] }, + }; + const written: Record = {}; + const diagnostics = await dispatchRuntimeComponentEvent({ + ...refreshEventArgs(), + apis: createApis(), + dataBindings: createOperationBindings(), + operationResults, + executeOperation: () => + Promise.resolve({ + ok: false, + diagnostics: [ + { + apiId: 'cms', + code: 'adapter-error', + endpointId: 'posts', + message: 'Network failed.', + operationId: 'posts.list', + severity: 'error', + }, + ], + }), + writeOperationResult: (key, value) => { + written[key] = value; + }, + }); + + expect(diagnostics.map((diagnostic) => diagnostic.code)).toEqual(['adapter-error']); + expect(written).toEqual({}); + expect(operationResults[operationKey]).toEqual({ items: [{ id: 'existing-post' }] }); + }); + + it('returns missing-api before an operation executor can run', async () => { + let executorCalls = 0; + const diagnostics = await dispatchRuntimeComponentEvent({ + ...refreshEventArgs(), + apis: [], + dataBindings: createOperationBindings(), + executeOperation: () => { + executorCalls += 1; + return Promise.resolve({ ok: true, data: null }); + }, + }); + + expect(executorCalls).toBe(0); + expect(diagnostics).toEqual([ + { + apiId: 'cms', + code: 'missing-api', + endpointId: 'posts', + message: "API 'cms' could not be found.", + operationId: 'posts.list', + severity: 'error', + }, + ]); + }); +}); From e9bcd46e2d98fa18aa6e6eb43b2e404c49639428 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:52:45 +0200 Subject: [PATCH 27/43] test: preserve chained API event bindings --- src/runtimeActionRegistry.chains.test.ts | 198 +++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/runtimeActionRegistry.chains.test.ts diff --git a/src/runtimeActionRegistry.chains.test.ts b/src/runtimeActionRegistry.chains.test.ts new file mode 100644 index 0000000..869cecb --- /dev/null +++ b/src/runtimeActionRegistry.chains.test.ts @@ -0,0 +1,198 @@ +import type { + ApiDefinitionList, + BindingOperationRef, + BindingValue, + ComponentDataBindingRegistry, +} from '@ankhorage/contracts'; +import { describe, expect, it } from 'bun:test'; + +import { dispatchRuntimeComponentEvent } from './runtimeActionRegistry'; + +const lookupOperation: BindingOperationRef = { + apiId: 'nutrition', + endpointId: 'products', + operationId: 'products.byBarcode', +}; + +function createApis(): ApiDefinitionList { + return [ + { + id: 'nutrition', + origin: 'external', + protocol: 'rest', + baseUrl: 'https://api.ankhorage.com/v1/nutrition', + endpoints: { + products: { + id: 'products', + kind: 'http', + operations: { + 'products.byBarcode': { + id: 'products.byBarcode', + endpointId: 'products', + protocol: 'http', + intent: 'read', + method: 'GET', + path: '/products/by-barcode/{barcode}', + }, + }, + }, + }, + }, + ]; +} + +function createScannerBindings(): ComponentDataBindingRegistry { + return { + scanner: { + componentId: 'scanner', + events: { + barcodeScanned: [ + { + target: { kind: 'operation', operation: lookupOperation }, + input: { + barcode: { + kind: 'source', + source: { kind: 'event', path: 'payload.value' }, + }, + }, + }, + { + target: { kind: 'action', type: 'navigate' }, + when: { + source: { kind: 'operation', operation: lookupOperation, path: 'product.id' }, + operator: 'exists', + }, + input: { + route: { kind: 'literal', value: '/products/[id]' }, + params: { + kind: 'object', + fields: { + id: { + kind: 'source', + source: { + kind: 'operation', + operation: lookupOperation, + path: 'product.id', + }, + }, + }, + }, + }, + }, + { + target: { kind: 'action', type: 'navigate' }, + when: { + source: { kind: 'operation', operation: lookupOperation, path: 'product.id' }, + operator: 'notExists', + }, + input: { + route: { kind: 'literal', value: '/products/create' }, + params: { + kind: 'object', + fields: { + barcode: { + kind: 'source', + source: { kind: 'event', path: 'payload.value' }, + }, + }, + }, + }, + }, + ], + }, + }, + }; +} + +function scannerEvent() { + return { + node: { id: 'scanner', type: 'BarcodeScannerView' }, + eventName: 'barcodeScanned', + event: { + type: 'barcodeScanned', + sourceNodeId: 'scanner', + payload: { value: '7612345678901', type: 'ean13' }, + }, + } as const; +} + +describe('runtime chained API event bindings', () => { + it('uses the operation result in a subsequent conditional action binding', async () => { + const actions: { type: string; payload?: object }[] = []; + const inputs: (BindingValue | undefined)[] = []; + const diagnostics = await dispatchRuntimeComponentEvent({ + ...scannerEvent(), + apis: createApis(), + dataBindings: createScannerBindings(), + executeAction: ({ action }) => { + actions.push(action); + }, + executeOperation: ({ input }) => { + inputs.push(input); + return Promise.resolve({ ok: true, data: { product: { id: 'product-1' } } }); + }, + }); + + expect(diagnostics).toEqual([]); + expect(inputs).toEqual([{ barcode: '7612345678901' }]); + expect(actions).toEqual([ + { + type: 'navigate', + payload: { route: '/products/[id]', params: { id: 'product-1' } }, + }, + ]); + }); + + it('takes the create branch when lookup returns no product', async () => { + const actions: { type: string; payload?: object }[] = []; + const diagnostics = await dispatchRuntimeComponentEvent({ + ...scannerEvent(), + apis: createApis(), + dataBindings: createScannerBindings(), + executeAction: ({ action }) => { + actions.push(action); + }, + executeOperation: () => Promise.resolve({ ok: true, data: {} }), + }); + + expect(diagnostics).toEqual([]); + expect(actions).toEqual([ + { + type: 'navigate', + payload: { + route: '/products/create', + params: { barcode: '7612345678901' }, + }, + }, + ]); + }); + + it('stops follow-up bindings when the API operation fails', async () => { + const actions: { type: string; payload?: object }[] = []; + const diagnostics = await dispatchRuntimeComponentEvent({ + ...scannerEvent(), + apis: createApis(), + dataBindings: createScannerBindings(), + executeAction: ({ action }) => { + actions.push(action); + }, + executeOperation: () => + Promise.resolve({ + ok: false, + diagnostics: [ + { + apiId: 'nutrition', + code: 'adapter-error', + endpointId: 'products', + message: 'Lookup failed.', + operationId: 'products.byBarcode', + severity: 'error', + }, + ], + }), + }); + + expect(diagnostics.map((diagnostic) => diagnostic.code)).toEqual(['adapter-error']); + expect(actions).toEqual([]); + }); +}); From 985d80dbb519f8706444967e508c30b9935f2f41 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:53:09 +0200 Subject: [PATCH 28/43] test: use runtime operation cache type owner --- src/runtimeActionRegistry.operations.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/runtimeActionRegistry.operations.test.ts b/src/runtimeActionRegistry.operations.test.ts index 6fbf57e..2ee078f 100644 --- a/src/runtimeActionRegistry.operations.test.ts +++ b/src/runtimeActionRegistry.operations.test.ts @@ -3,13 +3,16 @@ import type { BindingOperationRef, BindingValue, ComponentDataBindingRegistry, - RuntimeBindingOperationResultCache, UiNode, } from '@ankhorage/contracts'; import { describe, expect, it } from 'bun:test'; import { dispatchRuntimeComponentEvent } from './runtimeActionRegistry'; -import { createRuntimeBindingOperationKey, resolveRuntimeBindings } from './runtimeBindings'; +import { + createRuntimeBindingOperationKey, + resolveRuntimeBindings, + type RuntimeBindingOperationResultCache, +} from './runtimeBindings'; const postsOperation: BindingOperationRef = { apiId: 'cms', From bb7b537a87f0ff2ad05102a805279134fdaa4872 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:53:17 +0200 Subject: [PATCH 29/43] test: split runtime action registry coverage by concern --- src/runtimeActionRegistry.test.ts | 843 ------------------------------ 1 file changed, 843 deletions(-) delete mode 100644 src/runtimeActionRegistry.test.ts diff --git a/src/runtimeActionRegistry.test.ts b/src/runtimeActionRegistry.test.ts deleted file mode 100644 index 8a37a72..0000000 --- a/src/runtimeActionRegistry.test.ts +++ /dev/null @@ -1,843 +0,0 @@ -import type { - BindingValue, - ComponentDataBindingRegistry, - DataSourceRegistry, - UiNode, -} from '@ankhorage/contracts'; -import { describe, expect, it } from 'bun:test'; - -import { - createComponentEventFromHandlerArgs, - createRuntimeActionRegistry, - dispatchRuntimeComponentEvent, - wrapRuntimeEventProps, -} from './runtimeActionRegistry'; -import { - createRuntimeBindingOperationKey, - resolveRuntimeBindings, - type RuntimeBindingOperationResultCache, -} from './runtimeBindings'; - -function isNoArgFunction(value: unknown): value is () => unknown { - return typeof value === 'function'; -} - -function createDataSources(): DataSourceRegistry { - return { - cms: { - id: 'cms', - kind: 'api', - origin: 'external', - protocol: 'rest', - baseUrl: 'https://cms.example.com', - endpoints: { - posts: { - id: 'posts', - kind: 'http', - operations: { - 'posts.create': { - id: 'posts.create', - endpointId: 'posts', - protocol: 'http', - intent: 'create', - method: 'POST', - path: '/posts', - }, - 'posts.list': { - id: 'posts.list', - endpointId: 'posts', - protocol: 'http', - intent: 'read', - method: 'GET', - path: '/posts', - }, - }, - }, - }, - }, - }; -} - -describe('runtime action registry', () => { - it('dispatches component event bindings to registered action handlers', async () => { - const handledActionTypes: string[] = []; - const handledPayloads: object[] = []; - const node: UiNode = { - id: 'contact-form', - type: 'Form', - }; - const dataBindings: ComponentDataBindingRegistry = { - 'contact-form': { - componentId: 'contact-form', - events: { - submit: [ - { - target: { kind: 'action', type: 'email.send' }, - input: { - message: { - kind: 'source', - source: { kind: 'event', path: 'payload.values.message' }, - transforms: ['trim'], - }, - }, - }, - ], - }, - }, - }; - - await dispatchRuntimeComponentEvent({ - node, - eventName: 'submit', - event: { - type: 'form.submit', - sourceNodeId: 'contact-form', - payload: { - values: { - message: ' Hello ', - }, - }, - }, - dataBindings, - actionHandlers: { - 'email.send': ({ action, resolvedPayload }) => { - handledActionTypes.push(action.type); - if (resolvedPayload !== undefined) handledPayloads.push(resolvedPayload); - }, - }, - }); - - expect(handledActionTypes).toEqual(['email.send']); - expect(handledPayloads).toEqual([{ message: 'Hello' }]); - }); - - it('executes operation event bindings through the injected operation executor', async () => { - const node: UiNode = { - id: 'create-post-button', - type: 'Button', - }; - const calls: object[] = []; - - const diagnostics = await dispatchRuntimeComponentEvent({ - node, - eventName: 'press', - event: { - type: 'button.press', - sourceNodeId: 'create-post-button', - payload: {}, - }, - dataSources: createDataSources(), - dataBindings: { - 'create-post-button': { - componentId: 'create-post-button', - events: { - press: [ - { - target: { - kind: 'operation', - operation: { - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.create', - }, - }, - input: { - title: { kind: 'literal', value: 'Hello' }, - }, - }, - ], - }, - }, - }, - executeOperation: ({ input, operation }) => { - calls.push({ input, operation }); - return Promise.resolve({ ok: true, data: { id: 'post-1' } }); - }, - }); - - expect(diagnostics).toEqual([]); - expect(calls).toEqual([ - { - input: { title: 'Hello' }, - operation: { - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.create', - }, - }, - ]); - }); - - it('stores successful operation event results under the binding operation key', async () => { - const operation = { - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.list', - }; - const writtenResults: Record = {}; - - const diagnostics = await dispatchRuntimeComponentEvent({ - node: { - id: 'refresh-posts-button', - type: 'Button', - }, - eventName: 'press', - event: { - type: 'button.press', - sourceNodeId: 'refresh-posts-button', - payload: {}, - }, - dataSources: createDataSources(), - dataBindings: { - 'refresh-posts-button': { - componentId: 'refresh-posts-button', - events: { - press: [ - { - target: { - kind: 'operation', - operation, - }, - }, - ], - }, - }, - }, - executeOperation: () => - Promise.resolve({ - ok: true, - data: { - items: [{ id: 'post-1', title: 'Hello' }], - }, - }), - writeOperationResult: (key, value) => { - writtenResults[key] = value; - }, - }); - - expect(diagnostics).toEqual([]); - expect(writtenResults).toEqual({ - [createRuntimeBindingOperationKey(operation)]: { - items: [{ id: 'post-1', title: 'Hello' }], - }, - }); - }); - - it('lets subsequent prop bindings resolve from an event-populated operation result cache', async () => { - const operation = { - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.list', - }; - const operationResults: Record = {}; - const listNode: UiNode = { - id: 'posts-list', - type: 'List', - }; - const dataBindings: ComponentDataBindingRegistry = { - 'refresh-posts-button': { - componentId: 'refresh-posts-button', - events: { - press: [ - { - target: { - kind: 'operation', - operation, - }, - }, - ], - }, - }, - 'posts-list': { - componentId: 'posts-list', - props: { - items: { - source: { - kind: 'operation', - operation, - path: 'items', - }, - fallback: { value: [] }, - }, - }, - }, - }; - - await dispatchRuntimeComponentEvent({ - node: { - id: 'refresh-posts-button', - type: 'Button', - }, - eventName: 'press', - event: { - type: 'button.press', - sourceNodeId: 'refresh-posts-button', - payload: {}, - }, - dataSources: createDataSources(), - dataBindings, - executeOperation: () => - Promise.resolve({ - ok: true, - data: { - items: [{ id: 'post-1', title: 'Hello' }], - }, - }), - writeOperationResult: (key, value) => { - operationResults[key] = value; - }, - }); - - const result = resolveRuntimeBindings({ - node: listNode, - props: {}, - dataBindings, - dataSources: createDataSources(), - operationResults, - }); - - expect(result.props).toEqual({ - items: [{ id: 'post-1', title: 'Hello' }], - }); - expect(result.diagnostics).toEqual([]); - }); - - it('does not overwrite existing operation results when an event operation fails', async () => { - const operation = { - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.list', - }; - const operationKey = createRuntimeBindingOperationKey(operation); - const operationResults: RuntimeBindingOperationResultCache = { - [operationKey]: { - items: [{ id: 'existing-post', title: 'Existing' }], - }, - }; - const writtenResults: Record = {}; - - const diagnostics = await dispatchRuntimeComponentEvent({ - node: { - id: 'refresh-posts-button', - type: 'Button', - }, - eventName: 'press', - event: { - type: 'button.press', - sourceNodeId: 'refresh-posts-button', - payload: {}, - }, - dataSources: createDataSources(), - dataBindings: { - 'refresh-posts-button': { - componentId: 'refresh-posts-button', - events: { - press: [ - { - target: { - kind: 'operation', - operation, - }, - }, - ], - }, - }, - }, - executeOperation: () => - Promise.resolve({ - ok: false, - diagnostics: [ - { - code: 'adapter-error', - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.list', - message: 'Network failed.', - severity: 'error', - }, - ], - }), - writeOperationResult: (key, value) => { - writtenResults[key] = value; - }, - }); - - expect(diagnostics.map((diagnostic) => diagnostic.code)).toEqual(['adapter-error']); - expect(writtenResults).toEqual({}); - expect(operationResults[operationKey]).toEqual({ - items: [{ id: 'existing-post', title: 'Existing' }], - }); - }); - - it('executes chained scanner bindings using dispatch-scoped operation results', async () => { - const operation = { - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.list', - }; - const executedActions: { type: string; payload?: object }[] = []; - const operationInputs: object[] = []; - - const diagnostics = await dispatchRuntimeComponentEvent({ - node: { - id: 'scanner', - type: 'BarcodeScannerView', - }, - eventName: 'barcodeScanned', - event: { - type: 'barcodeScanned', - sourceNodeId: 'scanner', - payload: { - value: '7612345678901', - type: 'ean13', - }, - }, - dataSources: createDataSources(), - dataBindings: { - scanner: { - componentId: 'scanner', - events: { - barcodeScanned: [ - { - target: { - kind: 'operation', - operation, - }, - input: { - barcode: { - kind: 'source', - source: { kind: 'event', path: 'payload.value' }, - }, - }, - }, - { - target: { - kind: 'action', - type: 'navigate', - }, - when: { - source: { - kind: 'operation', - operation, - path: 'product.id', - }, - operator: 'exists', - }, - input: { - route: { kind: 'literal', value: '/products/[id]' }, - params: { - kind: 'object', - fields: { - id: { - kind: 'source', - source: { - kind: 'operation', - operation, - path: 'product.id', - }, - }, - }, - }, - }, - }, - { - target: { - kind: 'action', - type: 'navigate', - }, - when: { - source: { - kind: 'operation', - operation, - path: 'product.id', - }, - operator: 'notExists', - }, - input: { - route: { kind: 'literal', value: '/products/create' }, - params: { - kind: 'object', - fields: { - barcode: { - kind: 'source', - source: { kind: 'event', path: 'payload.value' }, - }, - }, - }, - }, - }, - ], - }, - }, - }, - executeAction: ({ action }) => { - executedActions.push(action); - }, - executeOperation: ({ input }) => { - operationInputs.push(input as object); - return Promise.resolve({ - ok: true, - data: { - product: { id: 'post-1' }, - }, - }); - }, - }); - - expect(diagnostics).toEqual([]); - expect(operationInputs).toEqual([{ barcode: '7612345678901' }]); - expect(executedActions).toEqual([ - { - type: 'navigate', - payload: { - route: '/products/[id]', - params: { id: 'post-1' }, - }, - }, - ]); - }); - - it('navigates to create when the scanner lookup result is missing', async () => { - const operation = { - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.list', - }; - const executedActions: { type: string; payload?: object }[] = []; - - const diagnostics = await dispatchRuntimeComponentEvent({ - node: { - id: 'scanner', - type: 'BarcodeScannerView', - }, - eventName: 'barcodeScanned', - event: { - type: 'barcodeScanned', - sourceNodeId: 'scanner', - payload: { - value: '7612345678901', - }, - }, - dataSources: createDataSources(), - dataBindings: { - scanner: { - componentId: 'scanner', - events: { - barcodeScanned: [ - { - target: { - kind: 'operation', - operation, - }, - }, - { - target: { - kind: 'action', - type: 'navigate', - }, - when: { - source: { - kind: 'operation', - operation, - path: 'product.id', - }, - operator: 'notExists', - }, - input: { - route: { kind: 'literal', value: '/products/create' }, - params: { - kind: 'object', - fields: { - barcode: { - kind: 'source', - source: { kind: 'event', path: 'payload.value' }, - }, - }, - }, - }, - }, - ], - }, - }, - }, - executeAction: ({ action }) => { - executedActions.push(action); - }, - executeOperation: () => - Promise.resolve({ - ok: true, - data: {}, - }), - }); - - expect(diagnostics).toEqual([]); - expect(executedActions).toEqual([ - { - type: 'navigate', - payload: { - route: '/products/create', - params: { barcode: '7612345678901' }, - }, - }, - ]); - }); - - it('stops scanner follow-up bindings when the lookup operation fails', async () => { - const operation = { - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.list', - }; - const executedActions: { type: string; payload?: object }[] = []; - - const diagnostics = await dispatchRuntimeComponentEvent({ - node: { - id: 'scanner', - type: 'BarcodeScannerView', - }, - eventName: 'barcodeScanned', - event: { - type: 'barcodeScanned', - sourceNodeId: 'scanner', - payload: { - value: '7612345678901', - }, - }, - dataSources: createDataSources(), - dataBindings: { - scanner: { - componentId: 'scanner', - events: { - barcodeScanned: [ - { - target: { - kind: 'operation', - operation, - }, - }, - { - target: { - kind: 'action', - type: 'navigate', - }, - when: { - source: { - kind: 'operation', - operation, - path: 'product.id', - }, - operator: 'notExists', - }, - input: { - route: { kind: 'literal', value: '/products/create' }, - params: { - kind: 'object', - fields: { - barcode: { - kind: 'source', - source: { kind: 'event', path: 'payload.value' }, - }, - }, - }, - }, - }, - ], - }, - }, - }, - executeAction: ({ action }) => { - executedActions.push(action); - }, - executeOperation: () => - Promise.resolve({ - ok: false, - diagnostics: [ - { - code: 'adapter-error', - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.list', - message: 'Lookup failed.', - severity: 'error', - }, - ], - }), - }); - - expect(diagnostics).toEqual([ - { - code: 'adapter-error', - dataSourceId: 'cms', - endpointId: 'posts', - operationId: 'posts.list', - message: 'Lookup failed.', - severity: 'error', - }, - ]); - expect(executedActions).toEqual([]); - }); - - it('returns a diagnostic when an action binding has no executor', async () => { - const diagnostics = await dispatchRuntimeComponentEvent({ - node: { - id: 'save-button', - type: 'Button', - }, - eventName: 'press', - event: { - type: 'button.press', - sourceNodeId: 'save-button', - payload: {}, - }, - dataBindings: { - 'save-button': { - componentId: 'save-button', - events: { - press: [{ target: { kind: 'action', type: 'missing.action' } }], - }, - }, - }, - }); - - expect(diagnostics).toEqual([ - { - code: 'missing-action-handler', - message: - "Action 'missing.action' could not be executed because no runtime executor or handler is registered.", - severity: 'error', - }, - ]); - }); - - it('creates canonical component events from handler args', () => { - const node: UiNode = { - id: 'contact-form', - type: 'Form', - }; - - const event = createComponentEventFromHandlerArgs({ - node, - eventName: 'submit', - handlerArgs: [ - { - message: 'Hello', - }, - ], - }); - - expect(event).toEqual({ - type: 'form.submit', - sourceNodeId: 'contact-form', - payload: { - values: { - message: 'Hello', - }, - }, - }); - }); - - it('creates canonical scanner component events from handler args', () => { - const node: UiNode = { - id: 'scanner', - type: 'BarcodeScannerView', - }; - - const event = createComponentEventFromHandlerArgs({ - node, - eventName: 'barcodeScanned', - handlerArgs: [{ value: '7612345678901', type: 'ean13' }], - }); - - expect(event).toEqual({ - type: 'barcodeScanned', - sourceNodeId: 'scanner', - payload: { - value: '7612345678901', - type: 'ean13', - }, - }); - }); - - it('wraps event props from component data bindings and preserves existing handlers', () => { - const calls: string[] = []; - const node: UiNode = { - id: 'save-button', - type: 'Button', - }; - - const props = wrapRuntimeEventProps({ - node, - dataBindings: { - 'save-button': { - componentId: 'save-button', - events: { - press: [{ target: { kind: 'action', type: 'console' } }], - }, - }, - }, - props: { - onPress: () => { - calls.push('existing'); - }, - }, - disableActions: false, - dispatchComponentEvent: ({ event }) => { - calls.push(event.type); - }, - }); - - const { onPress } = props; - if (!isNoArgFunction(onPress)) { - throw new TypeError('Expected onPress to be a function.'); - } - - onPress(); - - expect(calls).toEqual(['existing', 'button.press']); - }); - - it('supports registering action handlers imperatively with component data bindings', async () => { - const handled: string[] = []; - const registry = createRuntimeActionRegistry({ - dataBindings: { - 'save-button': { - componentId: 'save-button', - events: { - press: [{ target: { kind: 'action', type: 'console' } }], - }, - }, - }, - }); - const unregister = registry.registerActionHandler('console', ({ action }) => { - handled.push(action.type); - }); - - await registry.dispatchComponentEvent({ - node: { - id: 'save-button', - type: 'Button', - }, - eventName: 'press', - event: { - type: 'button.press', - sourceNodeId: 'save-button', - payload: {}, - }, - }); - unregister(); - await registry.dispatchComponentEvent({ - node: { - id: 'save-button', - type: 'Button', - }, - eventName: 'press', - event: { - type: 'button.press', - sourceNodeId: 'save-button', - payload: {}, - }, - }); - - expect(handled).toEqual(['console']); - }); -}); From 708d2c78f4657069617c9a600252a566e3d2ac50 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:54:07 +0200 Subject: [PATCH 30/43] style: format API selection diagnostic --- src/runtimeApiSelection.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/runtimeApiSelection.ts b/src/runtimeApiSelection.ts index c101b71..4c4f1ee 100644 --- a/src/runtimeApiSelection.ts +++ b/src/runtimeApiSelection.ts @@ -17,7 +17,9 @@ export function validateRuntimeBindingOperationRef( ): readonly DataSourceDiagnostic[] { const api = findRuntimeApi(apis, operation.apiId); if (api === undefined) { - return [createApiDiagnostic(operation, 'missing-api', `API '${operation.apiId}' could not be found.`)]; + return [ + createApiDiagnostic(operation, 'missing-api', `API '${operation.apiId}' could not be found.`), + ]; } const endpoint = resolveRuntimeApiEndpoint(operation, api); From 6fa46cadf32af505ff85b19965b6f55fa32d4c59 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:54:32 +0200 Subject: [PATCH 31/43] test: cover canonical API selection diagnostics --- src/runtimeApiSelection.test.ts | 71 +++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/runtimeApiSelection.test.ts diff --git a/src/runtimeApiSelection.test.ts b/src/runtimeApiSelection.test.ts new file mode 100644 index 0000000..f2dae8e --- /dev/null +++ b/src/runtimeApiSelection.test.ts @@ -0,0 +1,71 @@ +import type { ApiDefinitionList, BindingOperationRef } from '@ankhorage/contracts'; +import { describe, expect, it } from 'bun:test'; + +import { validateRuntimeBindingOperationRef } from './runtimeApiSelection'; + +function createApis(): ApiDefinitionList { + return [ + { + id: 'nutrition', + origin: 'external', + protocol: 'rest', + baseUrl: 'https://api.ankhorage.com/v1/nutrition', + endpoints: { + products: { + id: 'products', + kind: 'http', + operations: { + 'products.list': { + id: 'products.list', + endpointId: 'products', + protocol: 'http', + intent: 'read', + method: 'GET', + path: '/products', + }, + }, + }, + }, + }, + ]; +} + +function operation(overrides: Partial = {}): BindingOperationRef { + return { + apiId: 'nutrition', + endpointId: 'products', + operationId: 'products.list', + ...overrides, + }; +} + +describe('validateRuntimeBindingOperationRef', () => { + it('accepts a canonical API operation reference', () => { + expect(validateRuntimeBindingOperationRef(operation(), createApis())).toEqual([]); + }); + + it('reports missing API identity', () => { + expect( + validateRuntimeBindingOperationRef(operation({ apiId: 'missing' }), createApis()), + ).toMatchObject([{ apiId: 'missing', code: 'missing-api' }]); + }); + + it('reports missing endpoint identity', () => { + expect( + validateRuntimeBindingOperationRef(operation({ endpointId: 'missing' }), createApis()), + ).toMatchObject([{ apiId: 'nutrition', code: 'missing-endpoint', endpointId: 'missing' }]); + }); + + it('reports missing operation identity', () => { + expect( + validateRuntimeBindingOperationRef(operation({ operationId: 'products.missing' }), createApis()), + ).toMatchObject([ + { + apiId: 'nutrition', + code: 'missing-operation', + endpointId: 'products', + operationId: 'products.missing', + }, + ]); + }); +}); From 72a4f2f7486e39f7caafbeb4b47d8abd84dc190e Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:55:22 +0200 Subject: [PATCH 32/43] style: format API selection tests --- src/runtimeApiSelection.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/runtimeApiSelection.test.ts b/src/runtimeApiSelection.test.ts index f2dae8e..101272c 100644 --- a/src/runtimeApiSelection.test.ts +++ b/src/runtimeApiSelection.test.ts @@ -58,7 +58,10 @@ describe('validateRuntimeBindingOperationRef', () => { it('reports missing operation identity', () => { expect( - validateRuntimeBindingOperationRef(operation({ operationId: 'products.missing' }), createApis()), + validateRuntimeBindingOperationRef( + operation({ operationId: 'products.missing' }), + createApis(), + ), ).toMatchObject([ { apiId: 'nutrition', From 08941c48d571bc70197c656722877f3c262a0138 Mon Sep 17 00:00:00 2001 From: artiphishle Date: Mon, 17 Aug 2026 00:57:36 +0200 Subject: [PATCH 33/43] chore: update packages --- bun.lock | 84 +++++++++++++++++++++++++++++++++++++++++++++------- package.json | 2 +- 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/bun.lock b/bun.lock index 8a05da8..8b47d0e 100644 --- a/bun.lock +++ b/bun.lock @@ -5,11 +5,11 @@ "": { "name": "@ankhorage/runtime", "dependencies": { - "@ankhorage/contracts": "^7.4.0", - "@ankhorage/data-sources": "^1.0.0", + "@ankhorage/contracts": "^8.0.0", + "@ankhorage/data-sources": "^2.0.0", }, "devDependencies": { - "@ankhorage/devtools": "^1.0.6", + "@ankhorage/devtools": "^1.5.0", "@ankhorage/paradox": "^0.1.21", "@changesets/cli": "^2.31.0", "@types/bun": "^1.3.13", @@ -28,14 +28,16 @@ "packages": { "@ankhorage/color-theory": ["@ankhorage/color-theory@0.0.8", "", { "dependencies": { "culori": "^4.0.2" } }, "sha512-+JRLkvBUiPxFrRANyewRZxLv1sU5cKFOc3VBYB+b/eFngLFDIAqXf/a4e0A6gQE+lk6e3wb3FcGQYIyYB1Dqzg=="], - "@ankhorage/contracts": ["@ankhorage/contracts@7.5.0", "", { "dependencies": { "@ankhorage/color-theory": "^0.0.8" } }, "sha512-Rzastd2rCS37q3ywVDQd1ktFlfGy5Q2puaqwSaiNLLsdMB3t4rRnS1+1XBDFbfBgWu8tk6SFuAj3gF0VkSYbFQ=="], + "@ankhorage/contracts": ["@ankhorage/contracts@8.0.0", "", { "dependencies": { "@ankhorage/color-theory": "^0.0.8" } }, "sha512-dypyNIFVp56b9Nxpitixzd164s+HcCv4Za6cV0PUwOWbvV+UHBKhCcKK96FxC1EOExqJ+jLuCA3/8ZPD4VM47w=="], - "@ankhorage/data-sources": ["@ankhorage/data-sources@1.0.0", "", { "dependencies": { "@ankhorage/contracts": "^4.0.2" } }, "sha512-Kk+GwYkI4UILuijPuHnBr1yXS2pEl+IiUmWRnSvNMeoHPG11HjiS6XYfEJPE7xuiTolmCtHeR0/xiHb1PFl9wA=="], + "@ankhorage/data-sources": ["@ankhorage/data-sources@2.0.0", "", { "dependencies": { "@ankhorage/contracts": "^8.0.0" } }, "sha512-Fh6bUc2GlGkQqPw+rfUx8t7pPGlBux2Jg8ipSvh8ZhzZXhuLqNWgs1Lh8KOx2v4+p2iJp9ni6Ff+esAQWGFKgQ=="], - "@ankhorage/devtools": ["@ankhorage/devtools@1.1.0", "", { "dependencies": { "@eslint/js": "^10.0.1", "eslint": "^10.2.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-import": "^2.32.0", "eslint-plugin-prettier": "^5.5.5", "eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-unused-imports": "^4.4.1", "knip": "^6.12.2", "prettier": "^3.8.1", "typescript-eslint": "^8.24.0" }, "bin": { "ankhorage-eslint": "dist/eslint-cli.js", "ankhorage-knip": "dist/knip-cli.js", "ankhorage-prettier": "dist/prettier-cli.js" } }, "sha512-RKI53N+oMHFhpCpHyksozMybaXSudbwAV5InHwSPw49sa+PxTE4l6UOnpfIUOJ8l8qbWuaKYRBF56sPpYbhUgg=="], + "@ankhorage/devtools": ["@ankhorage/devtools@1.5.0", "", { "dependencies": { "@ankhorage/utility": "^0.1.1", "@eslint/compat": "^2.1.0", "@eslint/js": "^10.0.1", "eslint": "^10.7.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-import": "^2.32.0", "eslint-plugin-prettier": "^5.5.5", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-native": "^5.0.0", "eslint-plugin-security": "^4.0.1", "eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-unused-imports": "^4.4.1", "knip": "^6.12.2", "prettier": "^3.8.1", "typescript-eslint": "^8.24.0" }, "bin": { "ankhorage-eslint": "dist/cli/bin/eslint.js", "ankhorage-knip": "dist/cli/bin/knip.js", "ankhorage-prettier": "dist/cli/bin/prettier.js" } }, "sha512-adgebatKNzlw6RlJ3JTCZjZdkL8L8RrJyJakkSRCd6KvaEoPmpA/UQAay8T+aYLAqUj8O+piSEoWoeePPhuQ8g=="], "@ankhorage/paradox": ["@ankhorage/paradox@0.1.21", "", { "dependencies": { "ts-morph": "^24.0.0" }, "bin": { "paradox": "dist/cli/standalone.js" } }, "sha512-0M77MTVwAvJrpwcGoeRY+Ab8MhovZG5NGwSNFqYARkp8Qb1y35arrQ67AiwEoxN60cSYpskTrHV9D2x+0Q+JGA=="], + "@ankhorage/utility": ["@ankhorage/utility@0.1.1", "", {}, "sha512-6EehBCB59HOibxq7YUYq54TjgAfktBFGrEXZSqn1DsnsoRSIRUNbroKvzw7oF3bWiJRXj7mtc3DClFm0kIW0Mg=="], + "@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="], "@babel/compat-data": ["@babel/compat-data@7.29.7", "", {}, "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg=="], @@ -224,9 +226,11 @@ "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], + "@eslint/compat": ["@eslint/compat@2.1.0", "", { "dependencies": { "@eslint/core": "^1.2.1" }, "peerDependencies": { "eslint": "^8.40 || 9 || 10" }, "optionalPeers": ["eslint"] }, "sha512-LgaSCymEpw7tF53xvDw9SNsraPb1IBHxpdABIOM0hW8UAlP8znrjYtuxfR58FSJ3L9BhwD+FaPRFQpZq84Nh6g=="], + "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="], - "@eslint/config-helpers": ["@eslint/config-helpers@0.6.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA=="], + "@eslint/config-helpers": ["@eslint/config-helpers@0.7.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw=="], "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="], @@ -496,12 +500,16 @@ "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], + "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], + "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="], "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="], "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="], + "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="], + "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], "asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="], @@ -642,6 +650,8 @@ "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + "es-iterator-helpers": ["es-iterator-helpers@1.4.0", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0" } }, "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q=="], + "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], @@ -656,7 +666,7 @@ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "eslint": ["eslint@10.6.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.6.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-6lVbcqSodALYo+4ELD0heG6lFiFxnLMuLkiMi2qV8LMp54N8tE8FT1GMH+ev4Ti00nFjNze2+Su6DsV5OQW3Dg=="], + "eslint": ["eslint@10.8.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.7.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ=="], "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], @@ -668,6 +678,16 @@ "eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.6", "", { "dependencies": { "prettier-linter-helpers": "^1.0.1", "synckit": "^0.11.13" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ=="], + "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="], + + "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.1.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g=="], + + "eslint-plugin-react-native": ["eslint-plugin-react-native@5.0.0", "", { "dependencies": { "eslint-plugin-react-native-globals": "^0.1.1" }, "peerDependencies": { "eslint": "^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-VyWlyCC/7FC/aONibOwLkzmyKg4j9oI8fzrk9WYNs4I8/m436JuOTAFwLvEn1CVvc7La4cPfbCyspP4OYpP52Q=="], + + "eslint-plugin-react-native-globals": ["eslint-plugin-react-native-globals@0.1.2", "", {}, "sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g=="], + + "eslint-plugin-security": ["eslint-plugin-security@4.0.1", "", { "dependencies": { "safe-regex": "^2.1.1" } }, "sha512-/lZCkOxPOWaf1jXAqgICrS8St3BMBccIPvhOSUYuV6VCr1o5nFVG998FnTLt6w2Nxb8Uo0nM8fzmnhp+GY/aEg=="], + "eslint-plugin-simple-import-sort": ["eslint-plugin-simple-import-sort@12.1.1", "", { "peerDependencies": { "eslint": ">=5.0.0" } }, "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA=="], "eslint-plugin-unused-imports": ["eslint-plugin-unused-imports@4.4.1", "", { "peerDependencies": { "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", "eslint": "^10.0.0 || ^9.0.0 || ^8.0.0" }, "optionalPeers": ["@typescript-eslint/eslint-plugin"] }, "sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ=="], @@ -788,9 +808,9 @@ "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], - "hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="], + "hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="], - "hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="], + "hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="], "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], @@ -884,6 +904,8 @@ "istanbul-lib-instrument": ["istanbul-lib-instrument@5.2.1", "", { "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" } }, "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg=="], + "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="], + "jest-environment-node": ["jest-environment-node@29.7.0", "", { "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "jest-mock": "^29.7.0", "jest-util": "^29.7.0" } }, "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw=="], "jest-get-type": ["jest-get-type@29.6.3", "", {}, "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw=="], @@ -922,6 +944,8 @@ "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], "knip": ["knip@6.23.0", "", { "dependencies": { "fdir": "^6.5.0", "formatly": "^0.3.0", "get-tsconfig": "4.14.0", "jiti": "^2.7.0", "oxc-parser": "^0.137.0", "oxc-resolver": "11.21.3", "picomatch": "^4.0.4", "smol-toml": "^1.6.1", "strip-json-comments": "5.0.3", "tinyglobby": "^0.2.17", "unbash": "^4.0.1", "yaml": "^2.9.0", "zod": "^4.1.11" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-2DvAOX2pZWiG4SLvRRxOAU0aWGEn1ZoVblI541xIoXFdHqq2THMZXy66/qcY5WGuW3TXhb9T1x1zd/Hd1u+yqg=="], @@ -1018,6 +1042,8 @@ "ob1": ["ob1@0.83.7", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-9M5kpuOLyTPogMtZiQUIxdAZxl7Dxs6tVBbJErSumsqGMuhVSoUbkfeZ3XNPpLpwBBtqY5QDUzGwggLHX3slQg=="], + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], @@ -1094,6 +1120,8 @@ "promise": ["promise@8.3.0", "", { "dependencies": { "asap": "~2.0.6" } }, "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg=="], + "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], @@ -1124,6 +1152,8 @@ "regenerator-runtime": ["regenerator-runtime@0.13.11", "", {}, "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="], + "regexp-tree": ["regexp-tree@0.1.27", "", { "bin": { "regexp-tree": "bin/regexp-tree" } }, "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA=="], + "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="], "regexpu-core": ["regexpu-core@6.4.0", "", { "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.2", "regjsgen": "^0.8.0", "regjsparser": "^0.13.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.2.1" } }, "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA=="], @@ -1150,6 +1180,8 @@ "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="], + "safe-regex": ["safe-regex@2.1.1", "", { "dependencies": { "regexp-tree": "~0.1.1" } }, "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A=="], + "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], @@ -1212,6 +1244,10 @@ "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="], + + "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="], + "string.prototype.trim": ["string.prototype.trim@1.2.11", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-object-atoms": "^1.1.2", "has-property-descriptors": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w=="], "string.prototype.trimend": ["string.prototype.trimend@1.0.10", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.2" } }, "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw=="], @@ -1338,7 +1374,7 @@ "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], - "@ankhorage/data-sources/@ankhorage/contracts": ["@ankhorage/contracts@4.0.2", "", { "dependencies": { "@ankhorage/color-theory": "^0.0.8" } }, "sha512-mxWLgJ4DYcSe5PRZBmbeqsyJXjBT5mlBkSoYqigNFw750OjiCjs9DfAxK3npapEASuy4uJWsIWdqLlld3KT/ww=="], + "zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="], "@babel/core/json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], @@ -1384,6 +1420,8 @@ "@react-native/babel-preset/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.36.0", "", { "dependencies": { "hermes-parser": "0.36.0" } }, "sha512-LhD0xdoedDw7ansQgXbB2DADLZIK/LRXuWNBPuVzMc5S2WK5GyT89tCM+cQzxFGO0mGyLK6D5TrVOJJzAoDy8Q=="], + "@react-native/codegen/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="], + "@react-native/metro-babel-transformer/hermes-parser": ["hermes-parser@0.36.0", "", { "dependencies": { "hermes-estree": "0.36.0" } }, "sha512-GdpwMmH5x6IpC1cijvcvYnlPB60Mh6kTSF/NFdYV/j56gYdi+0RIakYs+eqOV+bbO0SW7mgVVGSsTJxyPQfo3w=="], "@react-native/metro-config/@react-native/js-polyfills": ["@react-native/js-polyfills@0.86.0", "", {}, "sha512-zYy/Cjd1VTnZ2iCNaG9bDF9C3l2ntESiPRscjIlI5FKugu6aeTwsDSv1aI8Bc4Kp3vEdoVg+UQhLAhE4svREaQ=="], @@ -1400,6 +1438,8 @@ "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="], + "chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "connect/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -1410,10 +1450,16 @@ "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + "eslint-plugin-import/eslint": ["eslint@10.6.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.6.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-6lVbcqSodALYo+4ELD0heG6lFiFxnLMuLkiMi2qV8LMp54N8tE8FT1GMH+ev4Ti00nFjNze2+Su6DsV5OQW3Dg=="], + "eslint-plugin-import/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], "eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "eslint-plugin-react/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + + "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -1444,6 +1490,8 @@ "node-exports-info/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + "react-devtools-core/ws": ["ws@7.5.11", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA=="], "read-yaml-file/js-yaml": ["js-yaml@3.15.0", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog=="], @@ -1476,6 +1524,8 @@ "@react-native/babel-preset/babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.36.0", "", { "dependencies": { "hermes-estree": "0.36.0" } }, "sha512-GdpwMmH5x6IpC1cijvcvYnlPB60Mh6kTSF/NFdYV/j56gYdi+0RIakYs+eqOV+bbO0SW7mgVVGSsTJxyPQfo3w=="], + "@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="], + "@react-native/metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.36.0", "", {}, "sha512-A1+8zn5oss2CFP7pKsOaxorQG6FNIz1WU1VDqruLPPZl3LVgeE2C5xfFg8Ow6/Ow4mSslLLtYP1J3n38eKyW9w=="], "@react-native/metro-config/metro-config/metro": ["metro@0.84.4", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "accepts": "^2.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.35.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.84.4", "metro-cache": "0.84.4", "metro-cache-key": "0.84.4", "metro-config": "0.84.4", "metro-core": "0.84.4", "metro-file-map": "0.84.4", "metro-resolver": "0.84.4", "metro-runtime": "0.84.4", "metro-source-map": "0.84.4", "metro-symbolicate": "0.84.4", "metro-transform-plugins": "0.84.4", "metro-transform-worker": "0.84.4", "mime-types": "^3.0.1", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-8ETTubqfD6ornDy2zYDvRcKnVDOXdFJsjetYDBsY4oAsb6NJkiwFR+FaMESyGppFmQUyBQA4H4sFGxzcQSGtFA=="], @@ -1486,10 +1536,20 @@ "@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="], + "babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="], + "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "eslint-plugin-import/eslint/@eslint/config-helpers": ["@eslint/config-helpers@0.6.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA=="], + + "eslint-plugin-import/eslint/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "eslint-plugin-import/eslint/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + "eslint-plugin-import/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="], + "eslint-plugin-react/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="], + "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "glob/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="], @@ -1540,6 +1600,8 @@ "eslint-plugin-import/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "eslint-plugin-react/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "test-exclude/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], diff --git a/package.json b/package.json index a52541d..3164ece 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "react-native": "0.81.5" }, "devDependencies": { - "@ankhorage/devtools": "^1.0.6", + "@ankhorage/devtools": "^1.5.0", "@ankhorage/paradox": "^0.1.21", "@changesets/cli": "^2.31.0", "@types/bun": "^1.3.13", From caa23de3769210b9ddb5c8316a61884fe1313206 Mon Sep 17 00:00:00 2001 From: Fabio Gartenmann <137318798+artiphishle@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:58:02 +0200 Subject: [PATCH 34/43] ci: materialize dependency lockfile --- .github/workflows/ci.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4f0ed1..ff3608e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: - main permissions: - contents: read + contents: write jobs: validate: @@ -18,6 +18,7 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + ref: ${{ github.head_ref || github.ref_name }} - name: Setup Bun uses: oven-sh/setup-bun@v2 @@ -27,8 +28,18 @@ jobs: - name: Install dependencies run: bun install - - name: Show lockfile changes - run: git diff -- bun.lock + - name: Commit generated lockfile + if: github.event_name == 'pull_request' + run: | + if git diff --quiet -- bun.lock; then + echo "bun.lock is already current." + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add bun.lock + git commit -m "chore: update runtime dependency lockfile" + git push origin HEAD:${{ github.head_ref }} - name: Run build run: bun run build From 2faad45078af5690e5a452dd2a8c8a867fff3ee5 Mon Sep 17 00:00:00 2001 From: artiphishle Date: Mon, 17 Aug 2026 00:58:09 +0200 Subject: [PATCH 35/43] docs: update --- README.md | 2 +- paradox/badges/npm.svg | 6 +- paradox/components.md | 2 +- paradox/diagrams/architecture-overview.mmd | 52 +- paradox/diagrams/export-graph.mmd | 30 +- paradox/diagrams/module-relationships.mmd | 38 +- ...validate-runtime-binding-operation-ref.mmd | 15 +- paradox/exports.json | 287 +- paradox/exports.md | 158 +- paradox/index.html | 1859 ++++++------ paradox/paradox.json | 2506 ++++++++--------- 11 files changed, 2435 insertions(+), 2520 deletions(-) diff --git a/README.md b/README.md index 4960c0e..e1ffac7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # @ankhorage/runtime -![license: MIT](./paradox/badges/license.svg) ![npm: v1.0.0](./paradox/badges/npm.svg) ![runtime: bun](./paradox/badges/runtime.svg) ![typescript: strict](./paradox/badges/typescript.svg) ![eslint: checked](./paradox/badges/eslint.svg) ![prettier: checked](./paradox/badges/prettier.svg) ![build: checked](./paradox/badges/build.svg) ![tests: checked](./paradox/badges/tests.svg) ![docs: paradox](./paradox/badges/docs.svg) +![license: MIT](./paradox/badges/license.svg) ![npm: v1.1.0](./paradox/badges/npm.svg) ![runtime: bun](./paradox/badges/runtime.svg) ![typescript: strict](./paradox/badges/typescript.svg) ![eslint: checked](./paradox/badges/eslint.svg) ![prettier: checked](./paradox/badges/prettier.svg) ![build: checked](./paradox/badges/build.svg) ![tests: checked](./paradox/badges/tests.svg) ![docs: paradox](./paradox/badges/docs.svg) Platform-neutral runtime contracts and helpers for Ankhorage generated apps. diff --git a/paradox/badges/npm.svg b/paradox/badges/npm.svg index 18b7b93..5cbe7f9 100644 --- a/paradox/badges/npm.svg +++ b/paradox/badges/npm.svg @@ -1,7 +1,7 @@ - -npm: v1.0.0 + +npm: v1.1.0 npm -v1.0.0 +v1.1.0 diff --git a/paradox/components.md b/paradox/components.md index 0fa8663..f91de78 100644 --- a/paradox/components.md +++ b/paradox/components.md @@ -32,9 +32,9 @@ Export paths: `src/index.ts` | Prop | Type | Required | Default | Description | | ----------------- | --------------------------------------------------------------------- | -------- | ------- | ----------- | +| apis | `ApiDefinitionList \| undefined` | no | — | | | bindingContext | `Record \| undefined` | no | — | | | dataBindings | `ComponentDataBindingRegistry \| undefined` | no | — | | -| dataSources | `DataSourceRegistry \| undefined` | no | — | | | dbAdapter | `DbAdapter \| undefined` | no | — | | | dbRealtimeAdapter | `DbRealtimeAdapter \| undefined` | no | — | | | disableActions | `boolean \| undefined` | no | — | | diff --git a/paradox/diagrams/architecture-overview.mmd b/paradox/diagrams/architecture-overview.mmd index dd8ad53..7d85bf4 100644 --- a/paradox/diagrams/architecture-overview.mmd +++ b/paradox/diagrams/architecture-overview.mmd @@ -21,30 +21,40 @@ graph TD module_src_rendering_ts["src/rendering.ts"] package__ankhorage_runtime -.-> module_src_rendering_ts module_src_rendering_ts --> module_src_registry_tsx - module_src_runtimeActionRegistry_test_ts["src/runtimeActionRegistry.test.ts"] - package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_test_ts - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeActionRegistry_ts - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeActionRegistry_actions_test_ts["src/runtimeActionRegistry.actions.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_actions_test_ts + module_src_runtimeActionRegistry_actions_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_chains_test_ts["src/runtimeActionRegistry.chains.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_chains_test_ts + module_src_runtimeActionRegistry_chains_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts["src/runtimeActionRegistry.operations.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_operations_test_ts + module_src_runtimeActionRegistry_operations_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts --> module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts["src/runtimeActionRegistry.ts"] package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_ts --> module_src_runtimeApiSelection_ts module_src_runtimeActionRegistry_ts --> module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts --> module_src_RuntimeRendererConfig_tsx + module_src_runtimeApiOperations_test_ts["src/runtimeApiOperations.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiOperations_test_ts + module_src_runtimeApiOperations_test_ts --> module_src_runtimeApiOperations_ts + module_src_runtimeApiOperations_ts["src/runtimeApiOperations.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiOperations_ts + module_src_runtimeApiOperations_ts --> module_src_runtimeBindings_ts + module_src_runtimeApiSelection_test_ts["src/runtimeApiSelection.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiSelection_test_ts + module_src_runtimeApiSelection_test_ts --> module_src_runtimeApiSelection_ts + module_src_runtimeApiSelection_ts["src/runtimeApiSelection.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts["src/runtimeBindings.test.ts"] package__ankhorage_runtime -.-> module_src_runtimeBindings_test_ts + module_src_runtimeBindings_test_ts --> module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts --> module_src_runtimeBindings_ts module_src_runtimeBindings_test_ts --> module_src_runtimeNodeProps_ts module_src_runtimeBindings_ts["src/runtimeBindings.ts"] package__ankhorage_runtime -.-> module_src_runtimeBindings_ts - module_src_runtimeDatabaseOperationExecutor_ts["src/runtimeDatabaseOperationExecutor.ts"] - package__ankhorage_runtime -.-> module_src_runtimeDatabaseOperationExecutor_ts - module_src_runtimeDatabaseOperationExecutor_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_test_ts["src/runtimeDataSourceOperations.test.ts"] - package__ankhorage_runtime -.-> module_src_runtimeDataSourceOperations_test_ts - module_src_runtimeDataSourceOperations_test_ts --> module_src_runtimeDataSourceOperations_ts - module_src_runtimeDataSourceOperations_ts["src/runtimeDataSourceOperations.ts"] - package__ankhorage_runtime -.-> module_src_runtimeDataSourceOperations_ts - module_src_runtimeDataSourceOperations_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_ts --> module_src_runtimeDatabaseOperationExecutor_ts + module_src_runtimeBindings_ts --> module_src_runtimeApiSelection_ts module_src_runtimeDbPersist_test_ts["src/runtimeDbPersist.test.ts"] package__ankhorage_runtime -.-> module_src_runtimeDbPersist_test_ts module_src_runtimeDbPersist_test_ts --> module_src_runtimeActionRegistry_ts @@ -115,6 +125,7 @@ graph TD module_src_runtimeRepeat_test_ts --> module_src_runtimeRepeat_ts module_src_runtimeRepeat_ts["src/runtimeRepeat.ts"] package__ankhorage_runtime -.-> module_src_runtimeRepeat_ts + module_src_runtimeRepeat_ts --> module_src_runtimeApiSelection_ts module_src_runtimeRepeat_ts --> module_src_runtimeBindings_ts module_src_runtimeRepeatDiagnostics_ts["src/runtimeRepeatDiagnostics.ts"] package__ankhorage_runtime -.-> module_src_runtimeRepeatDiagnostics_ts @@ -131,12 +142,17 @@ graph TD package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_arrayPath_test_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeBindings_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeScreenLoaders_ts - module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"] - package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_test_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeBindings_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_execution_test_ts["src/runtimeScreenLoaders.execution.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_execution_test_ts + module_src_runtimeScreenLoaders_execution_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_execution_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts["src/runtimeScreenLoaders.lifecycle.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_lifecycle_test_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> module_src_runtimeScreenLoaders_ts module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"] package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_ts --> module_src_runtimeApiSelection_ts module_src_runtimeScreenLoaders_ts --> module_src_runtimeBindings_ts module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"] package__ankhorage_runtime -.-> module_src_runtimeStateAdapter_ts diff --git a/paradox/diagrams/export-graph.mmd b/paradox/diagrams/export-graph.mmd index b5e5ff6..1448241 100644 --- a/paradox/diagrams/export-graph.mmd +++ b/paradox/diagrams/export-graph.mmd @@ -7,13 +7,16 @@ graph LR module_src_registry_tsx["src/registry.tsx"] module_src_rendering_test_ts["src/rendering.test.ts"] module_src_rendering_ts["src/rendering.ts"] - module_src_runtimeActionRegistry_test_ts["src/runtimeActionRegistry.test.ts"] + module_src_runtimeActionRegistry_actions_test_ts["src/runtimeActionRegistry.actions.test.ts"] + module_src_runtimeActionRegistry_chains_test_ts["src/runtimeActionRegistry.chains.test.ts"] + module_src_runtimeActionRegistry_operations_test_ts["src/runtimeActionRegistry.operations.test.ts"] module_src_runtimeActionRegistry_ts["src/runtimeActionRegistry.ts"] + module_src_runtimeApiOperations_test_ts["src/runtimeApiOperations.test.ts"] + module_src_runtimeApiOperations_ts["src/runtimeApiOperations.ts"] + module_src_runtimeApiSelection_test_ts["src/runtimeApiSelection.test.ts"] + module_src_runtimeApiSelection_ts["src/runtimeApiSelection.ts"] module_src_runtimeBindings_test_ts["src/runtimeBindings.test.ts"] module_src_runtimeBindings_ts["src/runtimeBindings.ts"] - module_src_runtimeDatabaseOperationExecutor_ts["src/runtimeDatabaseOperationExecutor.ts"] - module_src_runtimeDataSourceOperations_test_ts["src/runtimeDataSourceOperations.test.ts"] - module_src_runtimeDataSourceOperations_ts["src/runtimeDataSourceOperations.ts"] module_src_runtimeDbPersist_test_ts["src/runtimeDbPersist.test.ts"] module_src_runtimeDbPersist_ts["src/runtimeDbPersist.ts"] module_src_runtimeEventExecution_test_ts["src/runtimeEventExecution.test.ts"] @@ -36,7 +39,8 @@ graph LR module_src_runtimeRepeatEmptyState_ts["src/runtimeRepeatEmptyState.ts"] module_src_RuntimeScreen_tsx["src/RuntimeScreen.tsx"] module_src_runtimeScreenLoaders_arrayPath_test_ts["src/runtimeScreenLoaders.arrayPath.test.ts"] - module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"] + module_src_runtimeScreenLoaders_execution_test_ts["src/runtimeScreenLoaders.execution.test.ts"] + module_src_runtimeScreenLoaders_lifecycle_test_ts["src/runtimeScreenLoaders.lifecycle.test.ts"] module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"] module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"] module_src_runtimeStateAdapterConfig_test_ts["src/runtimeStateAdapterConfig.test.ts"] @@ -72,12 +76,12 @@ graph LR export_createRuntimeActionRegistry -.-> export_RuntimeBindingOperationExecutor export_createRuntimeActionRegistry -.-> export_RuntimeBindingOperationResultCache export_createRuntimeActionRegistry -.-> export_RuntimeBindingOperationResultWriter + export_createRuntimeApiOperationExecutor["createRuntimeApiOperationExecutor"] + module_src_runtimeApiOperations_ts --> export_createRuntimeApiOperationExecutor + export_createRuntimeApiOperationExecutor -.-> export_RuntimeApiOperationExecutorOptions + export_createRuntimeApiOperationExecutor -.-> export_RuntimeBindingOperationExecutor export_createRuntimeBindingOperationKey["createRuntimeBindingOperationKey"] module_src_runtimeBindings_ts --> export_createRuntimeBindingOperationKey - export_createRuntimeDataSourceOperationExecutor["createRuntimeDataSourceOperationExecutor"] - module_src_runtimeDataSourceOperations_ts --> export_createRuntimeDataSourceOperationExecutor - export_createRuntimeDataSourceOperationExecutor -.-> export_RuntimeBindingOperationExecutor - export_createRuntimeDataSourceOperationExecutor -.-> export_RuntimeDataSourceOperationExecutorOptions export_createRuntimeMemoryStateAdapter["createRuntimeMemoryStateAdapter"] module_src_runtimeStateAdapter_ts --> export_createRuntimeMemoryStateAdapter export_createRuntimeMemoryStateAdapter -.-> export_RuntimeMemoryStateAdapterOptions @@ -161,6 +165,10 @@ graph LR module_src_runtimeActionRegistry_ts --> export_RuntimeActionResolutionScope export_RuntimeAdapterDescriptor["RuntimeAdapterDescriptor"] module_src_runtimeManifest_ts --> export_RuntimeAdapterDescriptor + export_RuntimeApiOperationExecutorOptions["RuntimeApiOperationExecutorOptions"] + module_src_runtimeApiOperations_ts --> export_RuntimeApiOperationExecutorOptions + export_RuntimeApiOperationSelection["RuntimeApiOperationSelection"] + module_src_runtimeApiSelection_ts --> export_RuntimeApiOperationSelection export_RuntimeBindingDescriptor["RuntimeBindingDescriptor"] module_src_runtimeManifest_ts --> export_RuntimeBindingDescriptor export_RuntimeBindingOperationExecutionArgs["RuntimeBindingOperationExecutionArgs"] @@ -190,8 +198,6 @@ graph LR export_RuntimeComponentEventDispatchArgs -.-> export_RuntimeActionHandler export_RuntimeComponentEventDispatchArgs -.-> export_RuntimeBindingOperationExecutor export_RuntimeComponentEventDispatchArgs -.-> export_RuntimeBindingOperationResultWriter - export_RuntimeDataSourceOperationExecutorOptions["RuntimeDataSourceOperationExecutorOptions"] - module_src_runtimeDataSourceOperations_ts --> export_RuntimeDataSourceOperationExecutorOptions export_RuntimeDbPersistError["RuntimeDbPersistError"] module_src_runtimeDbPersist_ts --> export_RuntimeDbPersistError export_RuntimeDbPersistExecutionResult["RuntimeDbPersistExecutionResult"] @@ -284,7 +290,7 @@ graph LR export_useRuntimeScreenOperationLoaders -.-> export_RuntimeBindingResolutionContext export_useRuntimeScreenOperationLoaders -.-> export_RuntimeScreenOperationLoaderState export_validateRuntimeBindingOperationRef["validateRuntimeBindingOperationRef"] - module_src_runtimeBindings_ts --> export_validateRuntimeBindingOperationRef + module_src_runtimeApiSelection_ts --> export_validateRuntimeBindingOperationRef export_wrapRuntimeEventProps["wrapRuntimeEventProps"] module_src_runtimeActionRegistry_ts --> export_wrapRuntimeEventProps export_wrapRuntimeEventProps -.-> export_RuntimeEventPropWrapArgs diff --git a/paradox/diagrams/module-relationships.mmd b/paradox/diagrams/module-relationships.mmd index d5d383d..90abffa 100644 --- a/paradox/diagrams/module-relationships.mmd +++ b/paradox/diagrams/module-relationships.mmd @@ -7,13 +7,16 @@ graph LR module_src_registry_tsx["src/registry.tsx"] module_src_rendering_test_ts["src/rendering.test.ts"] module_src_rendering_ts["src/rendering.ts"] - module_src_runtimeActionRegistry_test_ts["src/runtimeActionRegistry.test.ts"] + module_src_runtimeActionRegistry_actions_test_ts["src/runtimeActionRegistry.actions.test.ts"] + module_src_runtimeActionRegistry_chains_test_ts["src/runtimeActionRegistry.chains.test.ts"] + module_src_runtimeActionRegistry_operations_test_ts["src/runtimeActionRegistry.operations.test.ts"] module_src_runtimeActionRegistry_ts["src/runtimeActionRegistry.ts"] + module_src_runtimeApiOperations_test_ts["src/runtimeApiOperations.test.ts"] + module_src_runtimeApiOperations_ts["src/runtimeApiOperations.ts"] + module_src_runtimeApiSelection_test_ts["src/runtimeApiSelection.test.ts"] + module_src_runtimeApiSelection_ts["src/runtimeApiSelection.ts"] module_src_runtimeBindings_test_ts["src/runtimeBindings.test.ts"] module_src_runtimeBindings_ts["src/runtimeBindings.ts"] - module_src_runtimeDatabaseOperationExecutor_ts["src/runtimeDatabaseOperationExecutor.ts"] - module_src_runtimeDataSourceOperations_test_ts["src/runtimeDataSourceOperations.test.ts"] - module_src_runtimeDataSourceOperations_ts["src/runtimeDataSourceOperations.ts"] module_src_runtimeDbPersist_test_ts["src/runtimeDbPersist.test.ts"] module_src_runtimeDbPersist_ts["src/runtimeDbPersist.ts"] module_src_runtimeEventExecution_test_ts["src/runtimeEventExecution.test.ts"] @@ -36,7 +39,8 @@ graph LR module_src_runtimeRepeatEmptyState_ts["src/runtimeRepeatEmptyState.ts"] module_src_RuntimeScreen_tsx["src/RuntimeScreen.tsx"] module_src_runtimeScreenLoaders_arrayPath_test_ts["src/runtimeScreenLoaders.arrayPath.test.ts"] - module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"] + module_src_runtimeScreenLoaders_execution_test_ts["src/runtimeScreenLoaders.execution.test.ts"] + module_src_runtimeScreenLoaders_lifecycle_test_ts["src/runtimeScreenLoaders.lifecycle.test.ts"] module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"] module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"] module_src_runtimeStateAdapterConfig_test_ts["src/runtimeStateAdapterConfig.test.ts"] @@ -46,16 +50,20 @@ graph LR module_src_rendering_test_ts --> module_src_registry_tsx module_src_rendering_test_ts --> module_src_rendering_ts module_src_rendering_ts --> module_src_registry_tsx - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeActionRegistry_ts - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeActionRegistry_actions_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_chains_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeActionRegistry_ts --> module_src_runtimeApiSelection_ts module_src_runtimeActionRegistry_ts --> module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts --> module_src_RuntimeRendererConfig_tsx + module_src_runtimeApiOperations_test_ts --> module_src_runtimeApiOperations_ts + module_src_runtimeApiOperations_ts --> module_src_runtimeBindings_ts + module_src_runtimeApiSelection_test_ts --> module_src_runtimeApiSelection_ts + module_src_runtimeBindings_test_ts --> module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts --> module_src_runtimeBindings_ts module_src_runtimeBindings_test_ts --> module_src_runtimeNodeProps_ts - module_src_runtimeDatabaseOperationExecutor_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_test_ts --> module_src_runtimeDataSourceOperations_ts - module_src_runtimeDataSourceOperations_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_ts --> module_src_runtimeDatabaseOperationExecutor_ts + module_src_runtimeBindings_ts --> module_src_runtimeApiSelection_ts module_src_runtimeDbPersist_test_ts --> module_src_runtimeActionRegistry_ts module_src_runtimeDbPersist_test_ts --> module_src_runtimeDbPersist_ts module_src_runtimeDbPersist_ts --> module_src_RuntimeRendererConfig_tsx @@ -90,6 +98,7 @@ graph LR module_src_runtimeRepeat_test_ts --> module_src_runtimeActionRegistry_ts module_src_runtimeRepeat_test_ts --> module_src_runtimeBindings_ts module_src_runtimeRepeat_test_ts --> module_src_runtimeRepeat_ts + module_src_runtimeRepeat_ts --> module_src_runtimeApiSelection_ts module_src_runtimeRepeat_ts --> module_src_runtimeBindings_ts module_src_RuntimeScreen_tsx --> module_src_registry_tsx module_src_RuntimeScreen_tsx --> module_src_RuntimeRenderer_tsx @@ -98,8 +107,11 @@ graph LR module_src_RuntimeScreen_tsx --> module_src_runtimeStateAdapter_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeBindings_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeScreenLoaders_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeBindings_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_execution_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_execution_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_ts --> module_src_runtimeApiSelection_ts module_src_runtimeScreenLoaders_ts --> module_src_runtimeBindings_ts module_src_runtimeStateAdapterConfig_test_ts --> module_src_runtimeBindings_ts module_src_runtimeStateAdapterConfig_test_ts --> module_src_runtimeNodeProps_ts diff --git a/paradox/diagrams/sequences/validate-runtime-binding-operation-ref.mmd b/paradox/diagrams/sequences/validate-runtime-binding-operation-ref.mmd index 69c4073..eae87eb 100644 --- a/paradox/diagrams/sequences/validate-runtime-binding-operation-ref.mmd +++ b/paradox/diagrams/sequences/validate-runtime-binding-operation-ref.mmd @@ -1,8 +1,11 @@ sequenceDiagram - participant participant_createRuntimeBindingDiagnostic as createRuntimeBindingDiagnostic - participant participant_resolveRuntimeBindingEndpoint as resolveRuntimeBindingEndpoint + participant participant_createApiDiagnostic as createApiDiagnostic + participant participant_findRuntimeApi as findRuntimeApi + participant participant_resolveRuntimeApiEndpoint as resolveRuntimeApiEndpoint participant participant_validateRuntimeBindingOperationRef as validateRuntimeBindingOperationRef - participant_validateRuntimeBindingOperationRef->>participant_createRuntimeBindingDiagnostic: createRuntimeBindingDiagnostic() - participant_createRuntimeBindingDiagnostic-->>participant_validateRuntimeBindingOperationRef: return - participant_validateRuntimeBindingOperationRef->>participant_resolveRuntimeBindingEndpoint: resolveRuntimeBindingEndpoint() - participant_resolveRuntimeBindingEndpoint-->>participant_validateRuntimeBindingOperationRef: return + participant_validateRuntimeBindingOperationRef->>participant_findRuntimeApi: findRuntimeApi() + participant_findRuntimeApi-->>participant_validateRuntimeBindingOperationRef: return + participant_validateRuntimeBindingOperationRef->>participant_createApiDiagnostic: createApiDiagnostic() + participant_createApiDiagnostic-->>participant_validateRuntimeBindingOperationRef: return + participant_validateRuntimeBindingOperationRef->>participant_resolveRuntimeApiEndpoint: resolveRuntimeApiEndpoint() + participant_resolveRuntimeApiEndpoint-->>participant_validateRuntimeBindingOperationRef: return diff --git a/paradox/exports.json b/paradox/exports.json index ba22ac8..1331bc3 100644 --- a/paradox/exports.json +++ b/paradox/exports.json @@ -102,7 +102,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 217, + "line": 216, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -262,7 +262,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 67, + "line": 66, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -276,11 +276,11 @@ ], "signatures": [ { - "label": "(options?: { actionHandlers?: RuntimeActionHandlers; dataSources?: DataSourceRegistry; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }) => RuntimeActionRegistry", + "label": "(options?: { actionHandlers?: RuntimeActionHandlers; apis?: ApiDefinitionList; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }) => RuntimeActionRegistry", "parameters": [ { "name": "options", - "type": "{ actionHandlers?: RuntimeActionHandlers; dataSources?: DataSourceRegistry; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }", + "type": "{ actionHandlers?: RuntimeActionHandlers; apis?: ApiDefinitionList; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }", "required": false, "description": null } @@ -293,31 +293,31 @@ "structuredRows": [] }, { - "name": "createRuntimeBindingOperationKey", + "name": "createRuntimeApiOperationExecutor", "description": null, "isReadme": false, "examples": [], "kind": "function", - "modulePath": "src/runtimeBindings.ts", + "modulePath": "src/runtimeApiOperations.ts", "sourceLocation": { - "filePath": "src/runtimeBindings.ts", - "line": 163, + "filePath": "src/runtimeApiOperations.ts", + "line": 12, "column": 1 }, "exportPaths": ["src/index.ts"], - "relatedSymbols": [], + "relatedSymbols": ["RuntimeApiOperationExecutorOptions", "RuntimeBindingOperationExecutor"], "signatures": [ { - "label": "(operation: BindingOperationRef) => string", + "label": "(options: RuntimeApiOperationExecutorOptions) => RuntimeBindingOperationExecutor", "parameters": [ { - "name": "operation", - "type": "BindingOperationRef", + "name": "options", + "type": "RuntimeApiOperationExecutorOptions", "required": true, "description": null } ], - "returnType": "string", + "returnType": "RuntimeBindingOperationExecutor", "returnDescription": null } ], @@ -325,34 +325,31 @@ "structuredRows": [] }, { - "name": "createRuntimeDataSourceOperationExecutor", + "name": "createRuntimeBindingOperationKey", "description": null, "isReadme": false, "examples": [], "kind": "function", - "modulePath": "src/runtimeDataSourceOperations.ts", + "modulePath": "src/runtimeBindings.ts", "sourceLocation": { - "filePath": "src/runtimeDataSourceOperations.ts", - "line": 14, + "filePath": "src/runtimeBindings.ts", + "line": 165, "column": 1 }, "exportPaths": ["src/index.ts"], - "relatedSymbols": [ - "RuntimeBindingOperationExecutor", - "RuntimeDataSourceOperationExecutorOptions" - ], + "relatedSymbols": [], "signatures": [ { - "label": "(options: RuntimeDataSourceOperationExecutorOptions) => RuntimeBindingOperationExecutor", + "label": "(operation: BindingOperationRef) => string", "parameters": [ { - "name": "options", - "type": "RuntimeDataSourceOperationExecutorOptions", + "name": "operation", + "type": "BindingOperationRef", "required": true, "description": null } ], - "returnType": "RuntimeBindingOperationExecutor", + "returnType": "string", "returnDescription": null } ], @@ -432,7 +429,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 103, + "line": 102, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -544,11 +541,11 @@ ], "signatures": [ { - "label": "(args: { readonly bindingContext?: Record; readonly dataSources?: RuntimeBindingResolutionContext[\"dataSources\"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }) => Promise", + "label": "(args: { readonly bindingContext?: Record; readonly apis?: RuntimeBindingResolutionContext[\"apis\"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }) => Promise", "parameters": [ { "name": "args", - "type": "{ readonly bindingContext?: Record; readonly dataSources?: RuntimeBindingResolutionContext[\"dataSources\"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }", + "type": "{ readonly bindingContext?: Record; readonly apis?: RuntimeBindingResolutionContext[\"apis\"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }", "required": true, "description": null } @@ -657,7 +654,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 129, + "line": 131, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -733,7 +730,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 231, + "line": 230, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -771,7 +768,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 242, + "line": 241, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -809,7 +806,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 89, + "line": 91, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -841,7 +838,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 74, + "line": 76, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -873,7 +870,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 103, + "line": 105, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -917,7 +914,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 116, + "line": 118, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1159,7 +1156,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 31, + "line": 30, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1192,7 +1189,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 42, + "line": 41, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1239,7 +1236,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 36, + "line": 35, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1310,6 +1307,72 @@ ], "structuredRows": [] }, + { + "name": "RuntimeApiOperationExecutorOptions", + "description": null, + "isReadme": false, + "examples": [], + "kind": "type", + "modulePath": "src/runtimeApiOperations.ts", + "sourceLocation": { + "filePath": "src/runtimeApiOperations.ts", + "line": 7, + "column": 1 + }, + "exportPaths": ["src/index.ts"], + "relatedSymbols": [], + "signatures": [], + "members": [ + { + "name": "credentialResolver", + "kind": "property", + "type": "EndpointTestCredentialResolver | undefined", + "required": false, + "description": null + }, + { + "name": "fetch", + "kind": "property", + "type": "EndpointTestFetch | undefined", + "required": false, + "description": null + } + ], + "structuredRows": [] + }, + { + "name": "RuntimeApiOperationSelection", + "description": null, + "isReadme": false, + "examples": [], + "kind": "type", + "modulePath": "src/runtimeApiSelection.ts", + "sourceLocation": { + "filePath": "src/runtimeApiSelection.ts", + "line": 9, + "column": 1 + }, + "exportPaths": ["src/index.ts"], + "relatedSymbols": [], + "signatures": [], + "members": [ + { + "name": "api", + "kind": "property", + "type": "ApiDefinition", + "required": true, + "description": null + }, + { + "name": "endpoint", + "kind": "property", + "type": "DataEndpointConfig", + "required": true, + "description": null + } + ], + "structuredRows": [] + }, { "name": "RuntimeBindingDescriptor", "description": null, @@ -1373,7 +1436,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 22, + "line": 24, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1381,17 +1444,17 @@ "signatures": [], "members": [ { - "name": "dataSource", + "name": "api", "kind": "property", - "type": "DataSourceConfig", + "type": "ApiDefinition", "required": true, "description": null }, { "name": "endpoint", "kind": "property", - "type": "DataEndpointConfig | undefined", - "required": false, + "type": "DataEndpointConfig", + "required": true, "description": null }, { @@ -1427,7 +1490,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 30, + "line": 32, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1445,7 +1508,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 41, + "line": 43, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1463,7 +1526,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 20, + "line": 22, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1481,7 +1544,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 45, + "line": 47, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1499,7 +1562,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 49, + "line": 51, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1517,7 +1580,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 64, + "line": 66, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1525,23 +1588,23 @@ "signatures": [], "members": [ { - "name": "context", + "name": "apis", "kind": "property", - "type": "Record | undefined", + "type": "ApiDefinitionList | undefined", "required": false, "description": null }, { - "name": "dataBindings", + "name": "context", "kind": "property", - "type": "Readonly> | undefined", + "type": "Record | undefined", "required": false, "description": null }, { - "name": "dataSources", + "name": "dataBindings", "kind": "property", - "type": "Readonly> | undefined", + "type": "Readonly> | undefined", "required": false, "description": null }, @@ -1599,7 +1662,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 54, + "line": 56, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1607,23 +1670,23 @@ "signatures": [], "members": [ { - "name": "context", + "name": "apis", "kind": "property", - "type": "Record | undefined", + "type": "ApiDefinitionList | undefined", "required": false, "description": null }, { - "name": "dataBindings", + "name": "context", "kind": "property", - "type": "Readonly> | undefined", + "type": "Record | undefined", "required": false, "description": null }, { - "name": "dataSources", + "name": "dataBindings", "kind": "property", - "type": "Readonly> | undefined", + "type": "Readonly> | undefined", "required": false, "description": null }, @@ -1667,7 +1730,7 @@ "modulePath": "src/runtimeBindings.ts", "sourceLocation": { "filePath": "src/runtimeBindings.ts", - "line": 69, + "line": 71, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1718,7 +1781,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 46, + "line": 45, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -1730,23 +1793,23 @@ "signatures": [], "members": [ { - "name": "context", + "name": "apis", "kind": "property", - "type": "Record | undefined", + "type": "ApiDefinitionList | undefined", "required": false, "description": null }, { - "name": "dataBindings", + "name": "context", "kind": "property", - "type": "Readonly> | undefined", + "type": "Record | undefined", "required": false, "description": null }, { - "name": "dataSources", + "name": "dataBindings", "kind": "property", - "type": "Readonly> | undefined", + "type": "Readonly> | undefined", "required": false, "description": null }, @@ -1809,46 +1872,6 @@ ], "structuredRows": [] }, - { - "name": "RuntimeDataSourceOperationExecutorOptions", - "description": null, - "isReadme": false, - "examples": [], - "kind": "type", - "modulePath": "src/runtimeDataSourceOperations.ts", - "sourceLocation": { - "filePath": "src/runtimeDataSourceOperations.ts", - "line": 8, - "column": 1 - }, - "exportPaths": ["src/index.ts"], - "relatedSymbols": [], - "signatures": [], - "members": [ - { - "name": "credentialResolver", - "kind": "property", - "type": "EndpointTestCredentialResolver | undefined", - "required": false, - "description": null - }, - { - "name": "databaseAdapters", - "kind": "property", - "type": "Readonly> | undefined", - "required": false, - "description": null - }, - { - "name": "fetch", - "kind": "property", - "type": "EndpointTestFetch | undefined", - "required": false, - "description": null - } - ], - "structuredRows": [] - }, { "name": "RuntimeDbPersistError", "description": null, @@ -2015,7 +2038,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 57, + "line": 56, "column": 1 }, "exportPaths": ["src/index.ts"], @@ -2407,23 +2430,23 @@ "description": null }, { - "name": "bindingContext", + "name": "apis", "kind": "property", - "type": "Record | undefined", + "type": "ApiDefinitionList | undefined", "required": false, "description": null }, { - "name": "dataBindings", + "name": "bindingContext", "kind": "property", - "type": "Readonly> | undefined", + "type": "Record | undefined", "required": false, "description": null }, { - "name": "dataSources", + "name": "dataBindings", "kind": "property", - "type": "Readonly> | undefined", + "type": "Readonly> | undefined", "required": false, "description": null }, @@ -2583,23 +2606,23 @@ "signatures": [], "members": [ { - "name": "bindingContext", + "name": "apis", "kind": "property", - "type": "Record | undefined", + "type": "ApiDefinitionList | undefined", "required": false, "description": null }, { - "name": "dataBindings", + "name": "bindingContext", "kind": "property", - "type": "Readonly> | undefined", + "type": "Record | undefined", "required": false, "description": null }, { - "name": "dataSources", + "name": "dataBindings", "kind": "property", - "type": "Readonly> | undefined", + "type": "Readonly> | undefined", "required": false, "description": null }, @@ -3114,11 +3137,11 @@ ], "signatures": [ { - "label": "(args: { readonly bindingContext?: Record; readonly dataSources?: RuntimeBindingResolutionContext[\"dataSources\"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }) => RuntimeScreenOperationLoaderState", + "label": "(args: { readonly bindingContext?: Record; readonly apis?: RuntimeBindingResolutionContext[\"apis\"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }) => RuntimeScreenOperationLoaderState", "parameters": [ { "name": "args", - "type": "{ readonly bindingContext?: Record; readonly dataSources?: RuntimeBindingResolutionContext[\"dataSources\"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }", + "type": "{ readonly bindingContext?: Record; readonly apis?: RuntimeBindingResolutionContext[\"apis\"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }", "required": true, "description": null } @@ -3136,21 +3159,21 @@ "isReadme": false, "examples": [], "kind": "function", - "modulePath": "src/runtimeBindings.ts", + "modulePath": "src/runtimeApiSelection.ts", "sourceLocation": { - "filePath": "src/runtimeBindings.ts", - "line": 169, + "filePath": "src/runtimeApiSelection.ts", + "line": 14, "column": 1 }, "exportPaths": ["src/index.ts"], "relatedSymbols": [], "signatures": [ { - "label": "(operation: BindingOperationRef, dataSources: Readonly> | undefined) => readonly DataSourceDiagnostic[]", + "label": "(operation: BindingOperationRef, apis: ApiDefinitionList | undefined) => readonly DataSourceDiagnostic[]", "parameters": [ { - "name": "dataSources", - "type": "Readonly> | undefined", + "name": "apis", + "type": "ApiDefinitionList | undefined", "required": true, "description": null }, @@ -3177,7 +3200,7 @@ "modulePath": "src/runtimeActionRegistry.ts", "sourceLocation": { "filePath": "src/runtimeActionRegistry.ts", - "line": 180, + "line": 179, "column": 1 }, "exportPaths": ["src/index.ts"], diff --git a/paradox/exports.md b/paradox/exports.md index bb462cb..e317bcf 100644 --- a/paradox/exports.md +++ b/paradox/exports.md @@ -36,7 +36,7 @@ Source: `src/RuntimeRendererConfig.tsx:77:1` Kind: `function` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:217:1` +Source: `src/runtimeActionRegistry.ts:216:1` ### Signatures @@ -96,37 +96,37 @@ Source: `src/runtimeScreenLoaders.ts:82:1` Kind: `function` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:67:1` +Source: `src/runtimeActionRegistry.ts:66:1` ### Signatures -- `(options?: { actionHandlers?: RuntimeActionHandlers; dataSources?: DataSourceRegistry; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }) => RuntimeActionRegistry` - - options: `{ actionHandlers?: RuntimeActionHandlers; dataSources?: DataSourceRegistry; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }` (optional) +- `(options?: { actionHandlers?: RuntimeActionHandlers; apis?: ApiDefinitionList; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }) => RuntimeActionRegistry` + - options: `{ actionHandlers?: RuntimeActionHandlers; apis?: ApiDefinitionList; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }` (optional) - returns: `RuntimeActionRegistry` -## createRuntimeBindingOperationKey +## createRuntimeApiOperationExecutor Kind: `function` -Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:163:1` +Module: `src/runtimeApiOperations.ts` +Source: `src/runtimeApiOperations.ts:12:1` ### Signatures -- `(operation: BindingOperationRef) => string` - - operation: `BindingOperationRef` - - returns: `string` +- `(options: RuntimeApiOperationExecutorOptions) => RuntimeBindingOperationExecutor` + - options: `RuntimeApiOperationExecutorOptions` + - returns: `RuntimeBindingOperationExecutor` -## createRuntimeDataSourceOperationExecutor +## createRuntimeBindingOperationKey Kind: `function` -Module: `src/runtimeDataSourceOperations.ts` -Source: `src/runtimeDataSourceOperations.ts:14:1` +Module: `src/runtimeBindings.ts` +Source: `src/runtimeBindings.ts:165:1` ### Signatures -- `(options: RuntimeDataSourceOperationExecutorOptions) => RuntimeBindingOperationExecutor` - - options: `RuntimeDataSourceOperationExecutorOptions` - - returns: `RuntimeBindingOperationExecutor` +- `(operation: BindingOperationRef) => string` + - operation: `BindingOperationRef` + - returns: `string` ## createRuntimeMemoryStateAdapter @@ -156,7 +156,7 @@ Source: `src/runtimeScreenLoaders.ts:49:1` Kind: `function` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:103:1` +Source: `src/runtimeActionRegistry.ts:102:1` ### Signatures @@ -196,8 +196,8 @@ Source: `src/runtimeScreenLoaders.ts:178:1` ### Signatures -- `(args: { readonly bindingContext?: Record; readonly dataSources?: RuntimeBindingResolutionContext["dataSources"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }) => Promise` - - args: `{ readonly bindingContext?: Record; readonly dataSources?: RuntimeBindingResolutionContext["dataSources"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }` +- `(args: { readonly bindingContext?: Record; readonly apis?: RuntimeBindingResolutionContext["apis"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }) => Promise` + - args: `{ readonly bindingContext?: Record; readonly apis?: RuntimeBindingResolutionContext["apis"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }` - returns: `Promise` ## ManifestContext @@ -235,7 +235,7 @@ Source: `src/RuntimeRendererConfig.tsx:110:1` Kind: `function` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:129:1` +Source: `src/runtimeBindings.ts:131:1` ### Signatures @@ -261,7 +261,7 @@ Source: `src/runtimeDbPersist.ts:68:1` Kind: `function` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:231:1` +Source: `src/runtimeActionRegistry.ts:230:1` ### Signatures @@ -274,7 +274,7 @@ Source: `src/runtimeActionRegistry.ts:231:1` Kind: `function` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:242:1` +Source: `src/runtimeActionRegistry.ts:241:1` ### Signatures @@ -287,7 +287,7 @@ Source: `src/runtimeActionRegistry.ts:242:1` Kind: `function` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:89:1` +Source: `src/runtimeBindings.ts:91:1` ### Signatures @@ -299,7 +299,7 @@ Source: `src/runtimeBindings.ts:89:1` Kind: `function` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:74:1` +Source: `src/runtimeBindings.ts:76:1` ### Signatures @@ -311,7 +311,7 @@ Source: `src/runtimeBindings.ts:74:1` Kind: `function` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:103:1` +Source: `src/runtimeBindings.ts:105:1` ### Signatures @@ -325,7 +325,7 @@ Source: `src/runtimeBindings.ts:103:1` Kind: `function` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:116:1` +Source: `src/runtimeBindings.ts:118:1` ### Signatures @@ -405,7 +405,7 @@ Source: `src/RuntimeRendererConfig.tsx:47:1` Kind: `type` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:31:1` +Source: `src/runtimeActionRegistry.ts:30:1` ### Members @@ -418,7 +418,7 @@ Source: `src/runtimeActionRegistry.ts:31:1` Kind: `type` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:42:1` +Source: `src/runtimeActionRegistry.ts:41:1` ### Members @@ -433,7 +433,7 @@ Source: `src/runtimeActionRegistry.ts:42:1` Kind: `type` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:36:1` +Source: `src/runtimeActionRegistry.ts:35:1` ### Members @@ -457,6 +457,32 @@ Source: `src/runtimeManifest.ts:39:1` | kind | property | `string` | yes | | | options | property | `Options \| undefined` | no | | +## RuntimeApiOperationExecutorOptions + +Kind: `type` +Module: `src/runtimeApiOperations.ts` +Source: `src/runtimeApiOperations.ts:7:1` + +### Members + +| Name | Kind | Type | Required | Description | +| ------------------ | -------- | --------------------------------------------- | -------- | ----------- | +| credentialResolver | property | `EndpointTestCredentialResolver \| undefined` | no | | +| fetch | property | `EndpointTestFetch \| undefined` | no | | + +## RuntimeApiOperationSelection + +Kind: `type` +Module: `src/runtimeApiSelection.ts` +Source: `src/runtimeApiSelection.ts:9:1` + +### Members + +| Name | Kind | Type | Required | Description | +| -------- | -------- | -------------------- | -------- | ----------- | +| api | property | `ApiDefinition` | yes | | +| endpoint | property | `DataEndpointConfig` | yes | | + ## RuntimeBindingDescriptor Kind: `type` @@ -477,61 +503,61 @@ Source: `src/runtimeManifest.ts:31:1` Kind: `type` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:22:1` +Source: `src/runtimeBindings.ts:24:1` ### Members -| Name | Kind | Type | Required | Description | -| ---------- | -------- | --------------------------------- | -------- | ----------- | -| dataSource | property | `DataSourceConfig` | yes | | -| endpoint | property | `DataEndpointConfig \| undefined` | no | | -| input | property | `BindingValue \| undefined` | no | | -| node | property | `UiNode \| undefined` | no | | -| operation | property | `BindingOperationRef` | yes | | +| Name | Kind | Type | Required | Description | +| --------- | -------- | --------------------------- | -------- | ----------- | +| api | property | `ApiDefinition` | yes | | +| endpoint | property | `DataEndpointConfig` | yes | | +| input | property | `BindingValue \| undefined` | no | | +| node | property | `UiNode \| undefined` | no | | +| operation | property | `BindingOperationRef` | yes | | ## RuntimeBindingOperationExecutionResult Kind: `unknown` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:30:1` +Source: `src/runtimeBindings.ts:32:1` ## RuntimeBindingOperationExecutor Kind: `unknown` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:41:1` +Source: `src/runtimeBindings.ts:43:1` ## RuntimeBindingOperationKey Kind: `unknown` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:20:1` +Source: `src/runtimeBindings.ts:22:1` ## RuntimeBindingOperationResultCache Kind: `unknown` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:45:1` +Source: `src/runtimeBindings.ts:47:1` ## RuntimeBindingOperationResultWriter Kind: `unknown` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:49:1` +Source: `src/runtimeBindings.ts:51:1` ## RuntimeBindingResolutionArgs Kind: `type` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:64:1` +Source: `src/runtimeBindings.ts:66:1` ### Members | Name | Kind | Type | Required | Description | | ---------------- | -------- | ---------------------------------------------------------------------------------------------------------- | -------- | ----------- | +| apis | property | `ApiDefinitionList \| undefined` | no | | | context | property | `Record \| undefined` | no | | | dataBindings | property | `Readonly> \| undefined` | no | | -| dataSources | property | `Readonly> \| undefined` | no | | | event | property | `ComponentEventDto \| undefined` | no | | | executeOperation | property | `RuntimeBindingOperationExecutor \| undefined` | no | | | node | property | `UiNode` | yes | | @@ -543,15 +569,15 @@ Source: `src/runtimeBindings.ts:64:1` Kind: `type` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:54:1` +Source: `src/runtimeBindings.ts:56:1` ### Members | Name | Kind | Type | Required | Description | | ---------------- | -------- | ---------------------------------------------------------------------------------------------------------- | -------- | ----------- | +| apis | property | `ApiDefinitionList \| undefined` | no | | | context | property | `Record \| undefined` | no | | | dataBindings | property | `Readonly> \| undefined` | no | | -| dataSources | property | `Readonly> \| undefined` | no | | | event | property | `ComponentEventDto \| undefined` | no | | | executeOperation | property | `RuntimeBindingOperationExecutor \| undefined` | no | | | operationResults | property | `Readonly> \| undefined` | no | | @@ -561,7 +587,7 @@ Source: `src/runtimeBindings.ts:54:1` Kind: `type` Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:69:1` +Source: `src/runtimeBindings.ts:71:1` ### Members @@ -580,15 +606,15 @@ Source: `src/runtimeManifest.ts:10:1` Kind: `type` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:46:1` +Source: `src/runtimeActionRegistry.ts:45:1` ### Members | Name | Kind | Type | Required | Description | | -------------------- | -------- | ---------------------------------------------------------------------------------------------------------- | -------- | ----------- | +| apis | property | `ApiDefinitionList \| undefined` | no | | | context | property | `Record \| undefined` | no | | | dataBindings | property | `Readonly> \| undefined` | no | | -| dataSources | property | `Readonly> \| undefined` | no | | | event | property | `ComponentEventDto` | yes | | | eventName | property | `string \| undefined` | no | | | executeAction | property | `RuntimeActionHandler \| undefined` | no | | @@ -598,20 +624,6 @@ Source: `src/runtimeActionRegistry.ts:46:1` | state | property | `Record \| undefined` | no | | | writeOperationResult | property | `RuntimeBindingOperationResultWriter \| undefined` | no | | -## RuntimeDataSourceOperationExecutorOptions - -Kind: `type` -Module: `src/runtimeDataSourceOperations.ts` -Source: `src/runtimeDataSourceOperations.ts:8:1` - -### Members - -| Name | Kind | Type | Required | Description | -| ------------------ | -------- | -------------------------------------------------- | -------- | ----------- | -| credentialResolver | property | `EndpointTestCredentialResolver \| undefined` | no | | -| databaseAdapters | property | `Readonly> \| undefined` | no | | -| fetch | property | `EndpointTestFetch \| undefined` | no | | - ## RuntimeDbPersistError Kind: `type` @@ -675,7 +687,7 @@ Source: `src/runtimeEventExecution.ts:9:1` Kind: `type` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:57:1` +Source: `src/runtimeActionRegistry.ts:56:1` ### Members @@ -797,9 +809,9 @@ Source: `src/RuntimeRendererConfig.tsx:50:1` | Name | Kind | Type | Required | Description | | -------------------- | -------- | --------------------------------------------------------------------------------------------------------------- | -------- | ----------- | | actionHandlers | property | `RuntimeActionHandlers \| undefined` | no | | +| apis | property | `ApiDefinitionList \| undefined` | no | | | bindingContext | property | `Record \| undefined` | no | | | dataBindings | property | `Readonly> \| undefined` | no | | -| dataSources | property | `Readonly> \| undefined` | no | | | dbAdapter | property | `DbAdapter \| undefined` | no | | | dbRealtimeAdapter | property | `DbRealtimeAdapter \| undefined` | no | | | disableActions | property | `boolean \| undefined` | no | | @@ -837,9 +849,9 @@ Source: `src/RuntimeRenderer.tsx:56:1` | Name | Kind | Type | Required | Description | | ----------------- | -------- | ---------------------------------------------------------------------------------------------------------- | -------- | ----------- | +| apis | property | `ApiDefinitionList \| undefined` | no | | | bindingContext | property | `Record \| undefined` | no | | | dataBindings | property | `Readonly> \| undefined` | no | | -| dataSources | property | `Readonly> \| undefined` | no | | | dbAdapter | property | `DbAdapter \| undefined` | no | | | dbRealtimeAdapter | property | `DbRealtimeAdapter \| undefined` | no | | | disableActions | property | `boolean \| undefined` | no | | @@ -1008,20 +1020,20 @@ Source: `src/runtimeScreenLoaders.ts:273:1` ### Signatures -- `(args: { readonly bindingContext?: Record; readonly dataSources?: RuntimeBindingResolutionContext["dataSources"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }) => RuntimeScreenOperationLoaderState` - - args: `{ readonly bindingContext?: Record; readonly dataSources?: RuntimeBindingResolutionContext["dataSources"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }` +- `(args: { readonly bindingContext?: Record; readonly apis?: RuntimeBindingResolutionContext["apis"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }) => RuntimeScreenOperationLoaderState` + - args: `{ readonly bindingContext?: Record; readonly apis?: RuntimeBindingResolutionContext["apis"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }` - returns: `RuntimeScreenOperationLoaderState` ## validateRuntimeBindingOperationRef Kind: `function` -Module: `src/runtimeBindings.ts` -Source: `src/runtimeBindings.ts:169:1` +Module: `src/runtimeApiSelection.ts` +Source: `src/runtimeApiSelection.ts:14:1` ### Signatures -- `(operation: BindingOperationRef, dataSources: Readonly> | undefined) => readonly DataSourceDiagnostic[]` - - dataSources: `Readonly> | undefined` +- `(operation: BindingOperationRef, apis: ApiDefinitionList | undefined) => readonly DataSourceDiagnostic[]` + - apis: `ApiDefinitionList | undefined` - operation: `BindingOperationRef` - returns: `readonly DataSourceDiagnostic[]` @@ -1029,7 +1041,7 @@ Source: `src/runtimeBindings.ts:169:1` Kind: `function` Module: `src/runtimeActionRegistry.ts` -Source: `src/runtimeActionRegistry.ts:180:1` +Source: `src/runtimeActionRegistry.ts:179:1` ### Signatures diff --git a/paradox/index.html b/paradox/index.html index 4059c0b..6957844 100644 --- a/paradox/index.html +++ b/paradox/index.html @@ -229,58 +229,80 @@

@ankhorage/runtime

  • -
  • -
  • -
  • -
  • +
  • +
  • + +
  • +
  • + +
  • +
  • +
  • @@ -423,10 +445,20 @@

    @ankhorage/runtime

    +
  • +
  • +
  • @@ -465,9 +497,9 @@

    @ankhorage/runtime

    Package overview

    -
    84public exports
    +
    85public exports
    5components
    -
    43modules
    +
    47modules
    1entrypoints

    Entrypoints

    @@ -498,7 +530,7 @@

    src/componentRegistry.ts

    src/index.ts

    Configured entrypoint

    @@ -512,8 +544,8 @@

    src/index.ts

    createDbPersistAdapterError, createPendingRuntimeScreenOperationLoaderState, createRuntimeActionRegistry, + createRuntimeApiOperationExecutor, createRuntimeBindingOperationKey, - createRuntimeDataSourceOperationExecutor, createRuntimeMemoryStateAdapter, createRuntimeScreenLoaderRequestKey, dispatchRuntimeComponentEvent, @@ -531,7 +563,9 @@

    src/index.ts

    RuntimeActionHandler, RuntimeActionHandlerArgs, RuntimeActionHandlers, RuntimeActionRegistry, RuntimeActionResolutionArgs, RuntimeActionResolutionScope, - RuntimeAdapterDescriptor, RuntimeBindingDescriptor, + RuntimeAdapterDescriptor, + RuntimeApiOperationExecutorOptions, + RuntimeApiOperationSelection, RuntimeBindingDescriptor, RuntimeBindingOperationExecutionArgs, RuntimeBindingOperationExecutionResult, RuntimeBindingOperationExecutor, @@ -541,14 +575,12 @@

    src/index.ts

    RuntimeBindingResolutionArgs, RuntimeBindingResolutionContext, RuntimeBindingResolutionResult, RuntimeCapability, - RuntimeComponentEventDispatchArgs, - RuntimeDataSourceOperationExecutorOptions, - RuntimeDbPersistError, RuntimeDbPersistExecutionResult, - RuntimeDbPersistResult, RuntimeDiagnostic, - RuntimeEventDiagnosticsReporter, RuntimeEventPropWrapArgs, - RuntimeManifest, RuntimeManifestConfig, - RuntimeManifestInput, RuntimeMediaAssetResolver, - RuntimeMediaAssetResolverArgs, + RuntimeComponentEventDispatchArgs, RuntimeDbPersistError, + RuntimeDbPersistExecutionResult, RuntimeDbPersistResult, + RuntimeDiagnostic, RuntimeEventDiagnosticsReporter, + RuntimeEventPropWrapArgs, RuntimeManifest, + RuntimeManifestConfig, RuntimeManifestInput, + RuntimeMediaAssetResolver, RuntimeMediaAssetResolverArgs, RuntimeMemoryStateAdapterOptions, RuntimeNodePropsResolver, RuntimeRenderer, RuntimeRendererConfig, RuntimeRendererConfigProvider, @@ -621,9 +653,27 @@

    src/rendering.ts

    +

    src/runtimeActionRegistry.actions.test.ts

    +

    Referenced module

    +

    Dependencies: src/runtimeActionRegistry.ts

    +

    Exports: None

    +
    +
    +

    src/runtimeActionRegistry.chains.test.ts

    +

    Referenced module

    +

    Dependencies: src/runtimeActionRegistry.ts

    +

    Exports: None

    +
    +
    -

    src/runtimeActionRegistry.test.ts

    +

    src/runtimeActionRegistry.operations.test.ts

    Referenced module

    Dependencies: src/runtimeActionRegistry.ts, @@ -633,13 +683,13 @@

    src/runtimeActionRegistry.test.ts

    src/runtimeActionRegistry.ts

    Referenced module

    - Dependencies: src/runtimeBindings.ts, - src/RuntimeRendererConfig.tsx + Dependencies: src/runtimeApiSelection.ts, + src/runtimeBindings.ts, src/RuntimeRendererConfig.tsx

    Exports: createComponentEventFromHandlerArgs, @@ -654,75 +704,82 @@

    src/runtimeActionRegistry.ts

    -

    src/runtimeBindings.test.ts

    +

    src/runtimeApiOperations.test.ts

    Referenced module

    -

    - Dependencies: src/runtimeBindings.ts, - src/runtimeNodeProps.ts -

    +

    Dependencies: src/runtimeApiOperations.ts

    Exports: None

    -

    src/runtimeBindings.ts

    +

    src/runtimeApiOperations.ts

    Referenced module

    -

    Dependencies: None

    +

    Dependencies: src/runtimeBindings.ts

    - Exports: applyRuntimeBindingDataPath, - createRuntimeBindingOperationKey, resolveBindingInputMap, - resolveBindingInputMapSync, - resolveRuntimeBindingOperationSelection, - resolveRuntimeBindings, resolveRuntimeBindingsAsync, - resolveRuntimeBindingValue, - resolveRuntimeBindingValueSourceSync, - resolveRuntimeBindingValueSync, - RuntimeBindingOperationExecutionArgs, - RuntimeBindingOperationExecutionResult, - RuntimeBindingOperationExecutor, - RuntimeBindingOperationKey, - RuntimeBindingOperationResultCache, - RuntimeBindingOperationResultWriter, - RuntimeBindingResolutionArgs, - RuntimeBindingResolutionContext, - RuntimeBindingResolutionResult, - validateRuntimeBindingOperationRef + Exports: createRuntimeApiOperationExecutor, + RuntimeApiOperationExecutorOptions

    -

    src/runtimeDatabaseOperationExecutor.ts

    +

    src/runtimeApiSelection.test.ts

    Referenced module

    -

    Dependencies: src/runtimeBindings.ts

    -

    Exports: executeRuntimeDatabaseOperation

    +

    Dependencies: src/runtimeApiSelection.ts

    +

    Exports: None

    -

    src/runtimeDataSourceOperations.test.ts

    +

    src/runtimeApiSelection.ts

    Referenced module

    -

    Dependencies: src/runtimeDataSourceOperations.ts

    -

    Exports: None

    +

    Dependencies: None

    +

    + Exports: resolveRuntimeBindingOperationSelection, + RuntimeApiOperationSelection, + validateRuntimeBindingOperationRef +

    -

    src/runtimeDataSourceOperations.ts

    +

    src/runtimeBindings.test.ts

    Referenced module

    - Dependencies: src/runtimeBindings.ts, - src/runtimeDatabaseOperationExecutor.ts + Dependencies: src/runtimeApiSelection.ts, + src/runtimeBindings.ts, src/runtimeNodeProps.ts

    +

    Exports: None

    +
    +
    +

    src/runtimeBindings.ts

    +

    Referenced module

    +

    Dependencies: src/runtimeApiSelection.ts

    - Exports: createRuntimeDataSourceOperationExecutor, - RuntimeDataSourceOperationExecutorOptions + Exports: applyRuntimeBindingDataPath, + createRuntimeBindingOperationKey, resolveBindingInputMap, + resolveBindingInputMapSync, resolveRuntimeBindings, + resolveRuntimeBindingsAsync, resolveRuntimeBindingValue, + resolveRuntimeBindingValueSourceSync, + resolveRuntimeBindingValueSync, + RuntimeBindingOperationExecutionArgs, + RuntimeBindingOperationExecutionResult, + RuntimeBindingOperationExecutor, + RuntimeBindingOperationKey, + RuntimeBindingOperationResultCache, + RuntimeBindingOperationResultWriter, + RuntimeBindingResolutionArgs, + RuntimeBindingResolutionContext, + RuntimeBindingResolutionResult

    src/runtimeRepeat.test.ts

    src/runtimeRepeat.ts

    Referenced module

    -

    Dependencies: src/runtimeBindings.ts

    +

    + Dependencies: src/runtimeApiSelection.ts, + src/runtimeBindings.ts +

    Exports: createRuntimeRepeatBindingContext, resolveRuntimeRepeatItemKey, @@ -1003,9 +1063,21 @@

    src/runtimeScreenLoaders.arrayPath.test.ts

    +

    src/runtimeScreenLoaders.execution.test.ts

    +

    Referenced module

    +

    + Dependencies: src/runtimeBindings.ts, + src/runtimeScreenLoaders.ts +

    +

    Exports: None

    +
    +
    -

    src/runtimeScreenLoaders.test.ts

    +

    src/runtimeScreenLoaders.lifecycle.test.ts

    Referenced module

    Dependencies: src/runtimeBindings.ts, @@ -1015,11 +1087,14 @@

    src/runtimeScreenLoaders.test.ts

    src/runtimeScreenLoaders.ts

    Referenced module

    -

    Dependencies: src/runtimeBindings.ts

    +

    + Dependencies: src/runtimeApiSelection.ts, + src/runtimeBindings.ts +

    Exports: beginRuntimeScreenOperationLoaderRequest, completeRuntimeScreenOperationLoaderRequest, @@ -1307,7 +1382,7 @@

    src/runtimeActionRegistry.ts

    data-search="createComponentEventFromHandlerArgs function src/runtimeActionRegistry.ts (args: { readonly node: UiNode; readonly eventName: string; readonly handlerArgs: readonly unknown[]; }) => ComponentEventDto<string, RuntimeEventPayload>" >

    createComponentEventFromHandlerArgs

    -

    function • src/runtimeActionRegistry.ts:217:1

    +

    function • src/runtimeActionRegistry.ts:216:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -1347,10 +1422,10 @@
    Signature

    createRuntimeActionRegistry

    -

    function • src/runtimeActionRegistry.ts:67:1

    +

    function • src/runtimeActionRegistry.ts:66:1

    Export paths: src/index.ts

    @@ -1367,7 +1442,7 @@

    createRuntimeActionRegistry

    Signature
    -(options?: { actionHandlers?: RuntimeActionHandlers; dataSources?: DataSourceRegistry; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }) => RuntimeActionRegistry
    +(options?: { actionHandlers?: RuntimeActionHandlers; apis?: ApiDefinitionList; dataBindings?: ComponentDataBindingRegistry; executeAction?: RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }) => RuntimeActionRegistry @@ -1382,9 +1457,9 @@
    Signature
    + + + + + + + @@ -1750,17 +1832,6 @@

    RuntimeComponentEventDispatchArgs

    - - - - - - - @@ -1831,7 +1902,7 @@

    RuntimeComponentEventDispatchArgs

    data-search="RuntimeEventPropWrapArgs type src/runtimeActionRegistry.ts RuntimeComponentEventDispatchArgs" >

    RuntimeEventPropWrapArgs

    -

    type • src/runtimeActionRegistry.ts:57:1

    +

    type • src/runtimeActionRegistry.ts:56:1

    Export paths: src/index.ts

    @@ -1933,7 +2004,7 @@

    RuntimeEventPropWrapArgs

    data-search="wrapRuntimeEventProps function src/runtimeActionRegistry.ts RuntimeEventPropWrapArgs (args: RuntimeEventPropWrapArgs) => Record<string, unknown>" >

    wrapRuntimeEventProps

    -

    function • src/runtimeActionRegistry.ts:180:1

    +

    function • src/runtimeActionRegistry.ts:179:1

    Export paths: src/index.ts

    @@ -1968,20 +2039,27 @@
    Signature
    -

    src/runtimeBindings.ts

    +

    src/runtimeApiOperations.ts

    -

    createRuntimeBindingOperationKey

    -

    function • src/runtimeBindings.ts:163:1

    +

    createRuntimeApiOperationExecutor

    +

    function • src/runtimeApiOperations.ts:12:1

    Export paths: src/index.ts

    -
    Related symbols: None
    +
    + Related symbols: +
      +
    • RuntimeApiOperationExecutorOptions
    • +
    • RuntimeBindingOperationExecutor
    • +
    +
    Signature
    -
    (operation: BindingOperationRef) => string
    +
    +(options: RuntimeApiOperationExecutorOptions) => RuntimeBindingOperationExecutor
    options { actionHandlers?: RuntimeActionHandlers; dataSources?: - DataSourceRegistry; dataBindings?: ComponentDataBindingRegistry; - executeAction?: RuntimeActionHandler; executeOperation?: + >{ actionHandlers?: RuntimeActionHandlers; apis?: ApiDefinitionList; + dataBindings?: ComponentDataBindingRegistry; executeAction?: + RuntimeActionHandler; executeOperation?: RuntimeBindingOperationExecutor; operationResults?: RuntimeBindingOperationResultCache; writeOperationResult?: RuntimeBindingOperationResultWriter; }Signature data-search="dispatchRuntimeComponentEvent function src/runtimeActionRegistry.ts RuntimeActionHandlers RuntimeComponentEventDispatchArgs (args: RuntimeComponentEventDispatchArgs & { readonly actionHandlers?: RuntimeActionHandlers; }) => Promise<readonly DataSourceDiagnostic[]>" >

    dispatchRuntimeComponentEvent

    -

    function • src/runtimeActionRegistry.ts:103:1

    +

    function • src/runtimeActionRegistry.ts:102:1

    Export paths: src/index.ts

    @@ -1453,7 +1528,7 @@
    Signature
    data-search="resolveRuntimeActionPayload function src/runtimeActionRegistry.ts RuntimeActionResolutionArgs (payload: object | undefined, args: RuntimeActionResolutionArgs) => object | undefined" >

    resolveRuntimeActionPayload

    -

    function • src/runtimeActionRegistry.ts:231:1

    +

    function • src/runtimeActionRegistry.ts:230:1

    Export paths: src/index.ts

    @@ -1499,7 +1574,7 @@
    Signature
    data-search="resolveRuntimeActionValue function src/runtimeActionRegistry.ts RuntimeActionResolutionArgs (value: unknown, args: RuntimeActionResolutionArgs) => object | undefined" >

    resolveRuntimeActionValue

    -

    function • src/runtimeActionRegistry.ts:242:1

    +

    function • src/runtimeActionRegistry.ts:241:1

    Export paths: src/index.ts

    @@ -1545,7 +1620,7 @@
    Signature
    data-search="RuntimeActionRegistry type src/runtimeActionRegistry.ts RuntimeActionHandler RuntimeComponentEventDispatchArgs" >

    RuntimeActionRegistry

    -

    type • src/runtimeActionRegistry.ts:31:1

    +

    type • src/runtimeActionRegistry.ts:30:1

    Export paths: src/index.ts

    @@ -1598,7 +1673,7 @@

    RuntimeActionRegistry

    data-search="RuntimeActionResolutionArgs type src/runtimeActionRegistry.ts " >

    RuntimeActionResolutionArgs

    -

    type • src/runtimeActionRegistry.ts:42:1

    +

    type • src/runtimeActionRegistry.ts:41:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -1656,7 +1731,7 @@

    RuntimeActionResolutionArgs

    data-search="RuntimeActionResolutionScope type src/runtimeActionRegistry.ts " >

    RuntimeActionResolutionScope

    -

    type • src/runtimeActionRegistry.ts:36:1

    +

    type • src/runtimeActionRegistry.ts:35:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -1707,7 +1782,7 @@

    RuntimeActionResolutionScope

    data-search="RuntimeComponentEventDispatchArgs type src/runtimeActionRegistry.ts RuntimeActionHandler RuntimeBindingOperationExecutor RuntimeBindingOperationResultWriter" >

    RuntimeComponentEventDispatchArgs

    -

    type • src/runtimeActionRegistry.ts:46:1

    +

    type • src/runtimeActionRegistry.ts:45:1

    Export paths: src/index.ts

    @@ -1730,6 +1805,13 @@

    RuntimeComponentEventDispatchArgs

    apispropertyApiDefinitionList | undefinedno
    context property no
    dataSourcesproperty - Readonly<Record<string, DataSourceConfig>> | undefined - no
    event property
    @@ -1993,35 +2071,111 @@
    Signature
    - - + +
    operationBindingOperationRefoptionsRuntimeApiOperationExecutorOptions yes
    -

    Returns: string

    +

    Returns: RuntimeBindingOperationExecutor

    -

    resolveBindingInputMap

    -

    function • src/runtimeBindings.ts:129:1

    +

    RuntimeApiOperationExecutorOptions

    +

    type • src/runtimeApiOperations.ts:7:1

    Export paths: src/index.ts

    -
    - Related symbols: -
      -
    • RuntimeBindingResolutionContext
    • -
    -
    +
    Related symbols: None
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MemberKindTypeRequiredDescription
    credentialResolverpropertyEndpointTestCredentialResolver | undefinedno
    fetchpropertyEndpointTestFetch | undefinedno
    +
    +
    +
    +

    src/runtimeApiSelection.ts

    +
    +

    RuntimeApiOperationSelection

    +

    type • src/runtimeApiSelection.ts:9:1

    + +

    Export paths: src/index.ts

    +
    Related symbols: None
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MemberKindTypeRequiredDescription
    apipropertyApiDefinitionyes
    endpointpropertyDataEndpointConfigyes
    +
    +
    +

    validateRuntimeBindingOperationRef

    +

    function • src/runtimeApiSelection.ts:14:1

    + +

    Export paths: src/index.ts

    +
    Related symbols: None
    Signature
    -(input: Readonly<Record<string, BindingInputValue>> | undefined, context: RuntimeBindingResolutionContext, diagnostics?: DataSourceDiagnostic[]) => Promise<BindingValue | undefined>
    +(operation: BindingOperationRef, apis: ApiDefinitionList | undefined) => readonly DataSourceDiagnostic[] @@ -2033,15 +2187,98 @@
    Signature
    - - + + - - - + + + + + + +
    contextRuntimeBindingResolutionContextapisApiDefinitionList | undefined yes
    diagnosticsDataSourceDiagnostic[]nooperationBindingOperationRefyes
    +

    Returns: readonly DataSourceDiagnostic[]

    +
    +
    +
    +
    +

    src/runtimeBindings.ts

    +
    +

    createRuntimeBindingOperationKey

    +

    function • src/runtimeBindings.ts:165:1

    + +

    Export paths: src/index.ts

    +
    Related symbols: None
    +
    +
    Signature
    +
    (operation: BindingOperationRef) => string
    + + + + + + + + + + + + + + + + + +
    ParameterTypeRequiredDescription
    operationBindingOperationRefyes
    +

    Returns: string

    +
    +
    +
    +

    resolveBindingInputMap

    +

    function • src/runtimeBindings.ts:131:1

    + +

    Export paths: src/index.ts

    +
    + Related symbols: +
      +
    • RuntimeBindingResolutionContext
    • +
    +
    +
    +
    Signature
    +
    +(input: Readonly<Record<string, BindingInputValue>> | undefined, context: RuntimeBindingResolutionContext, diagnostics?: DataSourceDiagnostic[]) => Promise<BindingValue | undefined>
    + + + + + + + + + + + + + + + + + + + + @@ -2068,7 +2305,7 @@
    Signature
    data-search="resolveRuntimeBindings function src/runtimeBindings.ts RuntimeBindingResolutionArgs RuntimeBindingResolutionResult (args: RuntimeBindingResolutionArgs) => RuntimeBindingResolutionResult" >

    resolveRuntimeBindings

    -

    function • src/runtimeBindings.ts:89:1

    +

    function • src/runtimeBindings.ts:91:1

    Export paths: src/index.ts

    @@ -2109,7 +2346,7 @@
    Signature
    data-search="resolveRuntimeBindingsAsync function src/runtimeBindings.ts RuntimeBindingResolutionArgs RuntimeBindingResolutionResult (args: RuntimeBindingResolutionArgs) => Promise<RuntimeBindingResolutionResult>" >

    resolveRuntimeBindingsAsync

    -

    function • src/runtimeBindings.ts:74:1

    +

    function • src/runtimeBindings.ts:76:1

    Export paths: src/index.ts

    @@ -2153,7 +2390,7 @@
    Signature
    data-search="resolveRuntimeBindingValue function src/runtimeBindings.ts RuntimeBindingResolutionContext (binding: PropBinding, context: RuntimeBindingResolutionContext, diagnostics?: DataSourceDiagnostic[]) => Promise<unknown>" >

    resolveRuntimeBindingValue

    -

    function • src/runtimeBindings.ts:103:1

    +

    function • src/runtimeBindings.ts:105:1

    Export paths: src/index.ts

    @@ -2205,7 +2442,7 @@
    Signature
    data-search="resolveRuntimeBindingValueSync function src/runtimeBindings.ts RuntimeBindingResolutionContext (binding: PropBinding, context: RuntimeBindingResolutionContext, diagnostics?: DataSourceDiagnostic[]) => unknown" >

    resolveRuntimeBindingValueSync

    -

    function • src/runtimeBindings.ts:116:1

    +

    function • src/runtimeBindings.ts:118:1

    Export paths: src/index.ts

    @@ -2257,7 +2494,7 @@
    Signature
    data-search="RuntimeBindingOperationExecutionArgs type src/runtimeBindings.ts " >

    RuntimeBindingOperationExecutionArgs

    -

    type • src/runtimeBindings.ts:22:1

    +

    type • src/runtimeBindings.ts:24:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -2274,17 +2511,17 @@

    RuntimeBindingOperationExecutionArgs

    - + - + - - + + @@ -2317,7 +2554,7 @@

    RuntimeBindingOperationExecutionArgs

    data-search="RuntimeBindingOperationExecutionResult unknown src/runtimeBindings.ts " >

    RuntimeBindingOperationExecutionResult

    -

    unknown • src/runtimeBindings.ts:30:1

    +

    unknown • src/runtimeBindings.ts:32:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -2328,7 +2565,7 @@

    RuntimeBindingOperationExecutionResult

    data-search="RuntimeBindingOperationExecutor unknown src/runtimeBindings.ts " >

    RuntimeBindingOperationExecutor

    -

    unknown • src/runtimeBindings.ts:41:1

    +

    unknown • src/runtimeBindings.ts:43:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -2339,7 +2576,7 @@

    RuntimeBindingOperationExecutor

    data-search="RuntimeBindingOperationKey unknown src/runtimeBindings.ts " >

    RuntimeBindingOperationKey

    -

    unknown • src/runtimeBindings.ts:20:1

    +

    unknown • src/runtimeBindings.ts:22:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -2350,7 +2587,7 @@

    RuntimeBindingOperationKey

    data-search="RuntimeBindingOperationResultCache unknown src/runtimeBindings.ts " >

    RuntimeBindingOperationResultCache

    -

    unknown • src/runtimeBindings.ts:45:1

    +

    unknown • src/runtimeBindings.ts:47:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -2361,7 +2598,7 @@

    RuntimeBindingOperationResultCache

    data-search="RuntimeBindingOperationResultWriter unknown src/runtimeBindings.ts " >

    RuntimeBindingOperationResultWriter

    -

    unknown • src/runtimeBindings.ts:49:1

    +

    unknown • src/runtimeBindings.ts:51:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -2372,7 +2609,7 @@

    RuntimeBindingOperationResultWriter

    data-search="RuntimeBindingResolutionArgs type src/runtimeBindings.ts RuntimeBindingOperationExecutor" >

    RuntimeBindingResolutionArgs

    -

    type • src/runtimeBindings.ts:64:1

    +

    type • src/runtimeBindings.ts:66:1

    Export paths: src/index.ts

    @@ -2393,6 +2630,13 @@

    RuntimeBindingResolutionArgs

    + + + + + + + @@ -2413,17 +2657,6 @@

    RuntimeBindingResolutionArgs

    - - - - - - - @@ -2480,7 +2713,7 @@

    RuntimeBindingResolutionArgs

    data-search="RuntimeBindingResolutionContext type src/runtimeBindings.ts RuntimeBindingOperationExecutor" >

    RuntimeBindingResolutionContext

    -

    type • src/runtimeBindings.ts:54:1

    +

    type • src/runtimeBindings.ts:56:1

    Export paths: src/index.ts

    @@ -2501,6 +2734,13 @@

    RuntimeBindingResolutionContext

    + + + + + + + @@ -2521,17 +2761,6 @@

    RuntimeBindingResolutionContext

    - - - - - - - @@ -2574,7 +2803,7 @@

    RuntimeBindingResolutionContext

    data-search="RuntimeBindingResolutionResult type src/runtimeBindings.ts " >

    RuntimeBindingResolutionResult

    -

    type • src/runtimeBindings.ts:69:1

    +

    type • src/runtimeBindings.ts:71:1

    Export paths: src/index.ts

    Related symbols: None
    @@ -2607,144 +2836,6 @@

    RuntimeBindingResolutionResult

    ParameterTypeRequiredDescription
    contextRuntimeBindingResolutionContextyes
    diagnosticsDataSourceDiagnostic[]no
    dataSourceapi propertyDataSourceConfigApiDefinition yes
    endpoint propertyDataEndpointConfig | undefinednoDataEndpointConfigyes
    apispropertyApiDefinitionList | undefinedno
    context property no
    dataSourcesproperty - Readonly<Record<string, DataSourceConfig>> | undefined - no
    event property
    apispropertyApiDefinitionList | undefinedno
    context property no
    dataSourcesproperty - Readonly<Record<string, DataSourceConfig>> | undefined - no
    event property
    -
    -

    validateRuntimeBindingOperationRef

    -

    function • src/runtimeBindings.ts:169:1

    - -

    Export paths: src/index.ts

    -
    Related symbols: None
    -
    -
    Signature
    -
    -(operation: BindingOperationRef, dataSources: Readonly<Record<string, DataSourceConfig>> | undefined) => readonly DataSourceDiagnostic[]
    - - - - - - - - - - - - - - - - - - - - - - - -
    ParameterTypeRequiredDescription
    dataSources - Readonly<Record<string, DataSourceConfig>> | - undefined - yes
    operationBindingOperationRefyes
    -

    Returns: readonly DataSourceDiagnostic[]

    -
    -
    -
    -
    -

    src/runtimeDataSourceOperations.ts

    -
    -

    createRuntimeDataSourceOperationExecutor

    -

    function • src/runtimeDataSourceOperations.ts:14:1

    - -

    Export paths: src/index.ts

    -
    - Related symbols: -
      -
    • RuntimeBindingOperationExecutor
    • -
    • RuntimeDataSourceOperationExecutorOptions
    • -
    -
    -
    -
    Signature
    -
    -(options: RuntimeDataSourceOperationExecutorOptions) => RuntimeBindingOperationExecutor
    - - - - - - - - - - - - - - - - - -
    ParameterTypeRequiredDescription
    optionsRuntimeDataSourceOperationExecutorOptionsyes
    -

    Returns: RuntimeBindingOperationExecutor

    -
    -
    -
    -

    RuntimeDataSourceOperationExecutorOptions

    -

    type • src/runtimeDataSourceOperations.ts:8:1

    - -

    Export paths: src/index.ts

    -
    Related symbols: None
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    MemberKindTypeRequiredDescription
    credentialResolverpropertyEndpointTestCredentialResolver | undefinedno
    databaseAdaptersproperty - Readonly<Record<string, DbAdapter>> | undefined - no
    fetchpropertyEndpointTestFetch | undefinedno
    -

    src/runtimeDbPersist.ts

    @@ -3683,32 +3774,26 @@

    RuntimeRendererProps

    - bindingContext + apis property - Record<string, unknown> | undefined + ApiDefinitionList | undefined no - dataBindings + bindingContext property - - Readonly<Record<string, - import("@ankhorage/contracts/dist/bindings").ComponentDataBinding>> - | undefined - + Record<string, unknown> | undefined no - dataSources + dataBindings property Readonly<Record<string, - import("@ankhorage/contracts/dist/index").DataSourceConfig>> + import("@ankhorage/contracts/dist/bindings").ComponentDataBinding>> | undefined @@ -4142,6 +4227,13 @@

    RuntimeRendererConfig

    no + + apis + property + ApiDefinitionList | undefined + no + + bindingContext property @@ -4163,20 +4255,7 @@

    RuntimeRendererConfig

    - dataSources - property - - Readonly<Record<string, - import("@ankhorage/contracts/dist/index").DataSourceConfig>> - | undefined - - no - - - - dbAdapter + dbAdapter property DbAdapter | undefined no @@ -4654,7 +4733,7 @@
    Signature

    executeRuntimeScreenOperationLoaders

    function • src/runtimeScreenLoaders.ts:178:1

    @@ -4672,7 +4751,7 @@

    executeRuntimeScreenOperationLoaders

    Signature
    -(args: { readonly bindingContext?: Record<string, unknown>; readonly dataSources?: RuntimeBindingResolutionContext["dataSources"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }) => Promise<RuntimeScreenOperationLoaderExecutionResult>
    +(args: { readonly bindingContext?: Record<string, unknown>; readonly apis?: RuntimeBindingResolutionContext["apis"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }) => Promise<RuntimeScreenOperationLoaderExecutionResult> @@ -4688,8 +4767,8 @@
    Signature
    { readonly bindingContext?: Record<string, unknown>; readonly - dataSources?: RuntimeBindingResolutionContext["dataSources"]; - readonly executeOperation?: RuntimeBindingOperationExecutor; readonly + apis?: RuntimeBindingResolutionContext["apis"]; readonly + executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly screen: ScreenSpec; readonly loaders: readonly OperationScreenDataLoaderDefinition[]; }RuntimeScreenOperationLoaderState

    useRuntimeScreenOperationLoaders

    function • src/runtimeScreenLoaders.ts:273:1

    @@ -4868,7 +4947,7 @@

    useRuntimeScreenOperationLoaders

    Signature
    -(args: { readonly bindingContext?: Record<string, unknown>; readonly dataSources?: RuntimeBindingResolutionContext["dataSources"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }) => RuntimeScreenOperationLoaderState
    +(args: { readonly bindingContext?: Record<string, unknown>; readonly apis?: RuntimeBindingResolutionContext["apis"]; readonly executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }) => RuntimeScreenOperationLoaderState @@ -4884,8 +4963,8 @@
    Signature
    - - + + - - + + - - + + @@ -5300,32 +5379,45 @@

    Architecture overview

    module_src_rendering_ts["src/rendering.ts"] package__ankhorage_runtime -.-> module_src_rendering_ts module_src_rendering_ts --> module_src_registry_tsx - module_src_runtimeActionRegistry_test_ts["src/runtimeActionRegistry.test.ts"] - package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_test_ts - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeActionRegistry_ts - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeActionRegistry_actions_test_ts["src/runtimeActionRegistry.actions.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_actions_test_ts + module_src_runtimeActionRegistry_actions_test_ts --> + module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_chains_test_ts["src/runtimeActionRegistry.chains.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_chains_test_ts + module_src_runtimeActionRegistry_chains_test_ts --> + module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts["src/runtimeActionRegistry.operations.test.ts"] + package__ankhorage_runtime -.-> + module_src_runtimeActionRegistry_operations_test_ts + module_src_runtimeActionRegistry_operations_test_ts --> + module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts --> + module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts["src/runtimeActionRegistry.ts"] package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_ts --> module_src_runtimeApiSelection_ts module_src_runtimeActionRegistry_ts --> module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts --> module_src_RuntimeRendererConfig_tsx + module_src_runtimeApiOperations_test_ts["src/runtimeApiOperations.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiOperations_test_ts + module_src_runtimeApiOperations_test_ts --> module_src_runtimeApiOperations_ts + module_src_runtimeApiOperations_ts["src/runtimeApiOperations.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiOperations_ts + module_src_runtimeApiOperations_ts --> module_src_runtimeBindings_ts + module_src_runtimeApiSelection_test_ts["src/runtimeApiSelection.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiSelection_test_ts + module_src_runtimeApiSelection_test_ts --> module_src_runtimeApiSelection_ts + module_src_runtimeApiSelection_ts["src/runtimeApiSelection.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts["src/runtimeBindings.test.ts"] package__ankhorage_runtime -.-> module_src_runtimeBindings_test_ts + module_src_runtimeBindings_test_ts --> module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts --> module_src_runtimeBindings_ts module_src_runtimeBindings_test_ts --> module_src_runtimeNodeProps_ts module_src_runtimeBindings_ts["src/runtimeBindings.ts"] package__ankhorage_runtime -.-> module_src_runtimeBindings_ts - module_src_runtimeDatabaseOperationExecutor_ts["src/runtimeDatabaseOperationExecutor.ts"] - package__ankhorage_runtime -.-> module_src_runtimeDatabaseOperationExecutor_ts - module_src_runtimeDatabaseOperationExecutor_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_test_ts["src/runtimeDataSourceOperations.test.ts"] - package__ankhorage_runtime -.-> module_src_runtimeDataSourceOperations_test_ts - module_src_runtimeDataSourceOperations_test_ts --> - module_src_runtimeDataSourceOperations_ts - module_src_runtimeDataSourceOperations_ts["src/runtimeDataSourceOperations.ts"] - package__ankhorage_runtime -.-> module_src_runtimeDataSourceOperations_ts - module_src_runtimeDataSourceOperations_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_ts --> - module_src_runtimeDatabaseOperationExecutor_ts + module_src_runtimeBindings_ts --> module_src_runtimeApiSelection_ts module_src_runtimeDbPersist_test_ts["src/runtimeDbPersist.test.ts"] package__ankhorage_runtime -.-> module_src_runtimeDbPersist_test_ts module_src_runtimeDbPersist_test_ts --> module_src_runtimeActionRegistry_ts @@ -5397,6 +5489,7 @@

    Architecture overview

    module_src_runtimeRepeat_test_ts --> module_src_runtimeRepeat_ts module_src_runtimeRepeat_ts["src/runtimeRepeat.ts"] package__ankhorage_runtime -.-> module_src_runtimeRepeat_ts + module_src_runtimeRepeat_ts --> module_src_runtimeApiSelection_ts module_src_runtimeRepeat_ts --> module_src_runtimeBindings_ts module_src_runtimeRepeatDiagnostics_ts["src/runtimeRepeatDiagnostics.ts"] package__ankhorage_runtime -.-> module_src_runtimeRepeatDiagnostics_ts @@ -5414,12 +5507,19 @@

    Architecture overview

    module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeBindings_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeScreenLoaders_ts - module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"] - package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_test_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeBindings_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_execution_test_ts["src/runtimeScreenLoaders.execution.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_execution_test_ts + module_src_runtimeScreenLoaders_execution_test_ts --> + module_src_runtimeBindings_ts module_src_runtimeScreenLoaders_execution_test_ts + --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts["src/runtimeScreenLoaders.lifecycle.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_lifecycle_test_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> + module_src_runtimeBindings_ts module_src_runtimeScreenLoaders_lifecycle_test_ts + --> module_src_runtimeScreenLoaders_ts module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"] package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_ts --> module_src_runtimeApiSelection_ts module_src_runtimeScreenLoaders_ts --> module_src_runtimeBindings_ts module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"] package__ankhorage_runtime -.-> module_src_runtimeStateAdapter_ts @@ -5462,30 +5562,40 @@

    Architecture overview

    module_src_rendering_ts["src/rendering.ts"] package__ankhorage_runtime -.-> module_src_rendering_ts module_src_rendering_ts --> module_src_registry_tsx - module_src_runtimeActionRegistry_test_ts["src/runtimeActionRegistry.test.ts"] - package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_test_ts - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeActionRegistry_ts - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeActionRegistry_actions_test_ts["src/runtimeActionRegistry.actions.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_actions_test_ts + module_src_runtimeActionRegistry_actions_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_chains_test_ts["src/runtimeActionRegistry.chains.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_chains_test_ts + module_src_runtimeActionRegistry_chains_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts["src/runtimeActionRegistry.operations.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_operations_test_ts + module_src_runtimeActionRegistry_operations_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts --> module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts["src/runtimeActionRegistry.ts"] package__ankhorage_runtime -.-> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_ts --> module_src_runtimeApiSelection_ts module_src_runtimeActionRegistry_ts --> module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts --> module_src_RuntimeRendererConfig_tsx + module_src_runtimeApiOperations_test_ts["src/runtimeApiOperations.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiOperations_test_ts + module_src_runtimeApiOperations_test_ts --> module_src_runtimeApiOperations_ts + module_src_runtimeApiOperations_ts["src/runtimeApiOperations.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiOperations_ts + module_src_runtimeApiOperations_ts --> module_src_runtimeBindings_ts + module_src_runtimeApiSelection_test_ts["src/runtimeApiSelection.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiSelection_test_ts + module_src_runtimeApiSelection_test_ts --> module_src_runtimeApiSelection_ts + module_src_runtimeApiSelection_ts["src/runtimeApiSelection.ts"] + package__ankhorage_runtime -.-> module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts["src/runtimeBindings.test.ts"] package__ankhorage_runtime -.-> module_src_runtimeBindings_test_ts + module_src_runtimeBindings_test_ts --> module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts --> module_src_runtimeBindings_ts module_src_runtimeBindings_test_ts --> module_src_runtimeNodeProps_ts module_src_runtimeBindings_ts["src/runtimeBindings.ts"] package__ankhorage_runtime -.-> module_src_runtimeBindings_ts - module_src_runtimeDatabaseOperationExecutor_ts["src/runtimeDatabaseOperationExecutor.ts"] - package__ankhorage_runtime -.-> module_src_runtimeDatabaseOperationExecutor_ts - module_src_runtimeDatabaseOperationExecutor_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_test_ts["src/runtimeDataSourceOperations.test.ts"] - package__ankhorage_runtime -.-> module_src_runtimeDataSourceOperations_test_ts - module_src_runtimeDataSourceOperations_test_ts --> module_src_runtimeDataSourceOperations_ts - module_src_runtimeDataSourceOperations_ts["src/runtimeDataSourceOperations.ts"] - package__ankhorage_runtime -.-> module_src_runtimeDataSourceOperations_ts - module_src_runtimeDataSourceOperations_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_ts --> module_src_runtimeDatabaseOperationExecutor_ts + module_src_runtimeBindings_ts --> module_src_runtimeApiSelection_ts module_src_runtimeDbPersist_test_ts["src/runtimeDbPersist.test.ts"] package__ankhorage_runtime -.-> module_src_runtimeDbPersist_test_ts module_src_runtimeDbPersist_test_ts --> module_src_runtimeActionRegistry_ts @@ -5556,6 +5666,7 @@

    Architecture overview

    module_src_runtimeRepeat_test_ts --> module_src_runtimeRepeat_ts module_src_runtimeRepeat_ts["src/runtimeRepeat.ts"] package__ankhorage_runtime -.-> module_src_runtimeRepeat_ts + module_src_runtimeRepeat_ts --> module_src_runtimeApiSelection_ts module_src_runtimeRepeat_ts --> module_src_runtimeBindings_ts module_src_runtimeRepeatDiagnostics_ts["src/runtimeRepeatDiagnostics.ts"] package__ankhorage_runtime -.-> module_src_runtimeRepeatDiagnostics_ts @@ -5572,12 +5683,17 @@

    Architecture overview

    package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_arrayPath_test_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeBindings_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeScreenLoaders_ts - module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"] - package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_test_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeBindings_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_execution_test_ts["src/runtimeScreenLoaders.execution.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_execution_test_ts + module_src_runtimeScreenLoaders_execution_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_execution_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts["src/runtimeScreenLoaders.lifecycle.test.ts"] + package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_lifecycle_test_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> module_src_runtimeScreenLoaders_ts module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"] package__ankhorage_runtime -.-> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_ts --> module_src_runtimeApiSelection_ts module_src_runtimeScreenLoaders_ts --> module_src_runtimeBindings_ts module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"] package__ankhorage_runtime -.-> module_src_runtimeStateAdapter_ts @@ -5610,13 +5726,16 @@

    Module relationships

    module_src_registry_tsx["src/registry.tsx"] module_src_rendering_test_ts["src/rendering.test.ts"] module_src_rendering_ts["src/rendering.ts"] - module_src_runtimeActionRegistry_test_ts["src/runtimeActionRegistry.test.ts"] + module_src_runtimeActionRegistry_actions_test_ts["src/runtimeActionRegistry.actions.test.ts"] + module_src_runtimeActionRegistry_chains_test_ts["src/runtimeActionRegistry.chains.test.ts"] + module_src_runtimeActionRegistry_operations_test_ts["src/runtimeActionRegistry.operations.test.ts"] module_src_runtimeActionRegistry_ts["src/runtimeActionRegistry.ts"] + module_src_runtimeApiOperations_test_ts["src/runtimeApiOperations.test.ts"] + module_src_runtimeApiOperations_ts["src/runtimeApiOperations.ts"] + module_src_runtimeApiSelection_test_ts["src/runtimeApiSelection.test.ts"] + module_src_runtimeApiSelection_ts["src/runtimeApiSelection.ts"] module_src_runtimeBindings_test_ts["src/runtimeBindings.test.ts"] module_src_runtimeBindings_ts["src/runtimeBindings.ts"] - module_src_runtimeDatabaseOperationExecutor_ts["src/runtimeDatabaseOperationExecutor.ts"] - module_src_runtimeDataSourceOperations_test_ts["src/runtimeDataSourceOperations.test.ts"] - module_src_runtimeDataSourceOperations_ts["src/runtimeDataSourceOperations.ts"] module_src_runtimeDbPersist_test_ts["src/runtimeDbPersist.test.ts"] module_src_runtimeDbPersist_ts["src/runtimeDbPersist.ts"] module_src_runtimeEventExecution_test_ts["src/runtimeEventExecution.test.ts"] @@ -5639,7 +5758,8 @@

    Module relationships

    module_src_runtimeRepeatEmptyState_ts["src/runtimeRepeatEmptyState.ts"] module_src_RuntimeScreen_tsx["src/RuntimeScreen.tsx"] module_src_runtimeScreenLoaders_arrayPath_test_ts["src/runtimeScreenLoaders.arrayPath.test.ts"] - module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"] + module_src_runtimeScreenLoaders_execution_test_ts["src/runtimeScreenLoaders.execution.test.ts"] + module_src_runtimeScreenLoaders_lifecycle_test_ts["src/runtimeScreenLoaders.lifecycle.test.ts"] module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"] module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"] module_src_runtimeStateAdapterConfig_test_ts["src/runtimeStateAdapterConfig.test.ts"] @@ -5648,45 +5768,51 @@

    Module relationships

    module_src_registry_test_ts --> module_src_registry_tsx module_src_rendering_test_ts --> module_src_registry_tsx module_src_rendering_test_ts --> module_src_rendering_ts module_src_rendering_ts - --> module_src_registry_tsx module_src_runtimeActionRegistry_test_ts --> - module_src_runtimeActionRegistry_ts module_src_runtimeActionRegistry_test_ts --> + --> module_src_registry_tsx module_src_runtimeActionRegistry_actions_test_ts + --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_chains_test_ts --> + module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts --> + module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts --> module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts --> + module_src_runtimeApiSelection_ts module_src_runtimeActionRegistry_ts --> module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts --> - module_src_RuntimeRendererConfig_tsx module_src_runtimeBindings_test_ts --> + module_src_RuntimeRendererConfig_tsx module_src_runtimeApiOperations_test_ts --> + module_src_runtimeApiOperations_ts module_src_runtimeApiOperations_ts --> + module_src_runtimeBindings_ts module_src_runtimeApiSelection_test_ts --> + module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts --> + module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts --> module_src_runtimeBindings_ts module_src_runtimeBindings_test_ts --> - module_src_runtimeNodeProps_ts module_src_runtimeDatabaseOperationExecutor_ts --> - module_src_runtimeBindings_ts module_src_runtimeDataSourceOperations_test_ts --> - module_src_runtimeDataSourceOperations_ts module_src_runtimeDataSourceOperations_ts - --> module_src_runtimeBindings_ts module_src_runtimeDataSourceOperations_ts - --> module_src_runtimeDatabaseOperationExecutor_ts - module_src_runtimeDbPersist_test_ts --> module_src_runtimeActionRegistry_ts - module_src_runtimeDbPersist_test_ts --> module_src_runtimeDbPersist_ts - module_src_runtimeDbPersist_ts --> module_src_RuntimeRendererConfig_tsx - module_src_runtimeEventExecution_test_ts --> module_src_runtimeEventExecution_ts - module_src_runtimeEventExecution_ts --> module_src_runtimeActionRegistry_ts - module_src_runtimeEventExecution_ts --> module_src_RuntimeRendererConfig_tsx - module_src_runtimeMedia_test_ts --> module_src_runtimeMedia_ts - module_src_runtimeMediaCache_tsx --> module_src_runtimeMedia_ts - module_src_runtimeMediaConfig_test_ts --> module_src_RuntimeRendererConfig_tsx - module_src_runtimeNodeProps_test_ts --> module_src_runtimeNodeProps_ts - module_src_runtimeNodeProps_ts --> module_src_runtimeBindings_ts - module_src_runtimeNodeProps_ts --> module_src_RuntimeRendererConfig_tsx - module_src_RuntimeRenderer_test_ts --> module_src_runtimeRepeatEmptyState_ts - module_src_RuntimeRenderer_tsx --> module_src_registry_tsx - module_src_RuntimeRenderer_tsx --> module_src_rendering_ts - module_src_RuntimeRenderer_tsx --> module_src_runtimeActionRegistry_ts - module_src_RuntimeRenderer_tsx --> module_src_runtimeBindings_ts - module_src_RuntimeRenderer_tsx --> module_src_runtimeDbPersist_ts - module_src_RuntimeRenderer_tsx --> module_src_runtimeEventExecution_ts - module_src_RuntimeRenderer_tsx --> module_src_runtimeMedia_ts - module_src_RuntimeRenderer_tsx --> module_src_runtimeMediaCache_tsx - module_src_RuntimeRenderer_tsx --> module_src_runtimeNodeProps_ts - module_src_RuntimeRenderer_tsx --> module_src_RuntimeRendererConfig_tsx - module_src_RuntimeRenderer_tsx --> module_src_runtimeRepeat_ts - module_src_RuntimeRenderer_tsx --> module_src_runtimeRepeatDiagnostics_ts - module_src_RuntimeRenderer_tsx --> module_src_runtimeRepeatEmptyState_ts - module_src_RuntimeRenderer_tsx --> module_src_useRuntimeMediaProps_ts - module_src_RuntimeRendererConfig_test_tsx --> + module_src_runtimeNodeProps_ts module_src_runtimeBindings_ts --> + module_src_runtimeApiSelection_ts module_src_runtimeDbPersist_test_ts --> + module_src_runtimeActionRegistry_ts module_src_runtimeDbPersist_test_ts --> + module_src_runtimeDbPersist_ts module_src_runtimeDbPersist_ts --> + module_src_RuntimeRendererConfig_tsx module_src_runtimeEventExecution_test_ts --> + module_src_runtimeEventExecution_ts module_src_runtimeEventExecution_ts --> + module_src_runtimeActionRegistry_ts module_src_runtimeEventExecution_ts --> + module_src_RuntimeRendererConfig_tsx module_src_runtimeMedia_test_ts --> + module_src_runtimeMedia_ts module_src_runtimeMediaCache_tsx --> + module_src_runtimeMedia_ts module_src_runtimeMediaConfig_test_ts --> + module_src_RuntimeRendererConfig_tsx module_src_runtimeNodeProps_test_ts --> + module_src_runtimeNodeProps_ts module_src_runtimeNodeProps_ts --> + module_src_runtimeBindings_ts module_src_runtimeNodeProps_ts --> + module_src_RuntimeRendererConfig_tsx module_src_RuntimeRenderer_test_ts --> + module_src_runtimeRepeatEmptyState_ts module_src_RuntimeRenderer_tsx --> + module_src_registry_tsx module_src_RuntimeRenderer_tsx --> + module_src_rendering_ts module_src_RuntimeRenderer_tsx --> + module_src_runtimeActionRegistry_ts module_src_RuntimeRenderer_tsx --> + module_src_runtimeBindings_ts module_src_RuntimeRenderer_tsx --> + module_src_runtimeDbPersist_ts module_src_RuntimeRenderer_tsx --> + module_src_runtimeEventExecution_ts module_src_RuntimeRenderer_tsx --> + module_src_runtimeMedia_ts module_src_RuntimeRenderer_tsx --> + module_src_runtimeMediaCache_tsx module_src_RuntimeRenderer_tsx --> + module_src_runtimeNodeProps_ts module_src_RuntimeRenderer_tsx --> + module_src_RuntimeRendererConfig_tsx module_src_RuntimeRenderer_tsx --> + module_src_runtimeRepeat_ts module_src_RuntimeRenderer_tsx --> + module_src_runtimeRepeatDiagnostics_ts module_src_RuntimeRenderer_tsx --> + module_src_runtimeRepeatEmptyState_ts module_src_RuntimeRenderer_tsx --> + module_src_useRuntimeMediaProps_ts module_src_RuntimeRendererConfig_test_tsx --> module_src_RuntimeRendererConfig_tsx module_src_RuntimeRendererConfig_tsx --> module_src_registry_tsx module_src_RuntimeRendererConfig_tsx --> module_src_runtimeBindings_ts module_src_RuntimeRendererConfig_tsx --> @@ -5694,6 +5820,7 @@

    Module relationships

    module_src_runtimeActionRegistry_ts module_src_runtimeRepeat_test_ts --> module_src_runtimeBindings_ts module_src_runtimeRepeat_test_ts --> module_src_runtimeRepeat_ts module_src_runtimeRepeat_ts --> + module_src_runtimeApiSelection_ts module_src_runtimeRepeat_ts --> module_src_runtimeBindings_ts module_src_RuntimeScreen_tsx --> module_src_registry_tsx module_src_RuntimeScreen_tsx --> module_src_RuntimeRenderer_tsx module_src_RuntimeScreen_tsx --> @@ -5702,9 +5829,14 @@

    Module relationships

    module_src_runtimeStateAdapter_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeBindings_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> - module_src_runtimeScreenLoaders_ts module_src_runtimeScreenLoaders_test_ts --> - module_src_runtimeBindings_ts module_src_runtimeScreenLoaders_test_ts --> + module_src_runtimeScreenLoaders_ts module_src_runtimeScreenLoaders_execution_test_ts + --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_execution_test_ts --> + module_src_runtimeScreenLoaders_ts module_src_runtimeScreenLoaders_lifecycle_test_ts + --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> module_src_runtimeScreenLoaders_ts module_src_runtimeScreenLoaders_ts --> + module_src_runtimeApiSelection_ts module_src_runtimeScreenLoaders_ts --> module_src_runtimeBindings_ts module_src_runtimeStateAdapterConfig_test_ts --> module_src_runtimeBindings_ts module_src_runtimeStateAdapterConfig_test_ts --> module_src_runtimeNodeProps_ts module_src_runtimeStateAdapterConfig_test_ts --> @@ -5724,13 +5856,16 @@

    Module relationships

    module_src_registry_tsx["src/registry.tsx"] module_src_rendering_test_ts["src/rendering.test.ts"] module_src_rendering_ts["src/rendering.ts"] - module_src_runtimeActionRegistry_test_ts["src/runtimeActionRegistry.test.ts"] + module_src_runtimeActionRegistry_actions_test_ts["src/runtimeActionRegistry.actions.test.ts"] + module_src_runtimeActionRegistry_chains_test_ts["src/runtimeActionRegistry.chains.test.ts"] + module_src_runtimeActionRegistry_operations_test_ts["src/runtimeActionRegistry.operations.test.ts"] module_src_runtimeActionRegistry_ts["src/runtimeActionRegistry.ts"] + module_src_runtimeApiOperations_test_ts["src/runtimeApiOperations.test.ts"] + module_src_runtimeApiOperations_ts["src/runtimeApiOperations.ts"] + module_src_runtimeApiSelection_test_ts["src/runtimeApiSelection.test.ts"] + module_src_runtimeApiSelection_ts["src/runtimeApiSelection.ts"] module_src_runtimeBindings_test_ts["src/runtimeBindings.test.ts"] module_src_runtimeBindings_ts["src/runtimeBindings.ts"] - module_src_runtimeDatabaseOperationExecutor_ts["src/runtimeDatabaseOperationExecutor.ts"] - module_src_runtimeDataSourceOperations_test_ts["src/runtimeDataSourceOperations.test.ts"] - module_src_runtimeDataSourceOperations_ts["src/runtimeDataSourceOperations.ts"] module_src_runtimeDbPersist_test_ts["src/runtimeDbPersist.test.ts"] module_src_runtimeDbPersist_ts["src/runtimeDbPersist.ts"] module_src_runtimeEventExecution_test_ts["src/runtimeEventExecution.test.ts"] @@ -5753,7 +5888,8 @@

    Module relationships

    module_src_runtimeRepeatEmptyState_ts["src/runtimeRepeatEmptyState.ts"] module_src_RuntimeScreen_tsx["src/RuntimeScreen.tsx"] module_src_runtimeScreenLoaders_arrayPath_test_ts["src/runtimeScreenLoaders.arrayPath.test.ts"] - module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"] + module_src_runtimeScreenLoaders_execution_test_ts["src/runtimeScreenLoaders.execution.test.ts"] + module_src_runtimeScreenLoaders_lifecycle_test_ts["src/runtimeScreenLoaders.lifecycle.test.ts"] module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"] module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"] module_src_runtimeStateAdapterConfig_test_ts["src/runtimeStateAdapterConfig.test.ts"] @@ -5763,16 +5899,20 @@

    Module relationships

    module_src_rendering_test_ts --> module_src_registry_tsx module_src_rendering_test_ts --> module_src_rendering_ts module_src_rendering_ts --> module_src_registry_tsx - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeActionRegistry_ts - module_src_runtimeActionRegistry_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeActionRegistry_actions_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_chains_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts --> module_src_runtimeActionRegistry_ts + module_src_runtimeActionRegistry_operations_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeActionRegistry_ts --> module_src_runtimeApiSelection_ts module_src_runtimeActionRegistry_ts --> module_src_runtimeBindings_ts module_src_runtimeActionRegistry_ts --> module_src_RuntimeRendererConfig_tsx + module_src_runtimeApiOperations_test_ts --> module_src_runtimeApiOperations_ts + module_src_runtimeApiOperations_ts --> module_src_runtimeBindings_ts + module_src_runtimeApiSelection_test_ts --> module_src_runtimeApiSelection_ts + module_src_runtimeBindings_test_ts --> module_src_runtimeApiSelection_ts module_src_runtimeBindings_test_ts --> module_src_runtimeBindings_ts module_src_runtimeBindings_test_ts --> module_src_runtimeNodeProps_ts - module_src_runtimeDatabaseOperationExecutor_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_test_ts --> module_src_runtimeDataSourceOperations_ts - module_src_runtimeDataSourceOperations_ts --> module_src_runtimeBindings_ts - module_src_runtimeDataSourceOperations_ts --> module_src_runtimeDatabaseOperationExecutor_ts + module_src_runtimeBindings_ts --> module_src_runtimeApiSelection_ts module_src_runtimeDbPersist_test_ts --> module_src_runtimeActionRegistry_ts module_src_runtimeDbPersist_test_ts --> module_src_runtimeDbPersist_ts module_src_runtimeDbPersist_ts --> module_src_RuntimeRendererConfig_tsx @@ -5807,6 +5947,7 @@

    Module relationships

    module_src_runtimeRepeat_test_ts --> module_src_runtimeActionRegistry_ts module_src_runtimeRepeat_test_ts --> module_src_runtimeBindings_ts module_src_runtimeRepeat_test_ts --> module_src_runtimeRepeat_ts + module_src_runtimeRepeat_ts --> module_src_runtimeApiSelection_ts module_src_runtimeRepeat_ts --> module_src_runtimeBindings_ts module_src_RuntimeScreen_tsx --> module_src_registry_tsx module_src_RuntimeScreen_tsx --> module_src_RuntimeRenderer_tsx @@ -5815,8 +5956,11 @@

    Module relationships

    module_src_RuntimeScreen_tsx --> module_src_runtimeStateAdapter_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeBindings_ts module_src_runtimeScreenLoaders_arrayPath_test_ts --> module_src_runtimeScreenLoaders_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeBindings_ts - module_src_runtimeScreenLoaders_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_execution_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_execution_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> module_src_runtimeBindings_ts + module_src_runtimeScreenLoaders_lifecycle_test_ts --> module_src_runtimeScreenLoaders_ts + module_src_runtimeScreenLoaders_ts --> module_src_runtimeApiSelection_ts module_src_runtimeScreenLoaders_ts --> module_src_runtimeBindings_ts module_src_runtimeStateAdapterConfig_test_ts --> module_src_runtimeBindings_ts module_src_runtimeStateAdapterConfig_test_ts --> module_src_runtimeNodeProps_ts @@ -5838,13 +5982,16 @@

    Export graph

    module_src_registry_tsx["src/registry.tsx"] module_src_rendering_test_ts["src/rendering.test.ts"] module_src_rendering_ts["src/rendering.ts"] - module_src_runtimeActionRegistry_test_ts["src/runtimeActionRegistry.test.ts"] + module_src_runtimeActionRegistry_actions_test_ts["src/runtimeActionRegistry.actions.test.ts"] + module_src_runtimeActionRegistry_chains_test_ts["src/runtimeActionRegistry.chains.test.ts"] + module_src_runtimeActionRegistry_operations_test_ts["src/runtimeActionRegistry.operations.test.ts"] module_src_runtimeActionRegistry_ts["src/runtimeActionRegistry.ts"] + module_src_runtimeApiOperations_test_ts["src/runtimeApiOperations.test.ts"] + module_src_runtimeApiOperations_ts["src/runtimeApiOperations.ts"] + module_src_runtimeApiSelection_test_ts["src/runtimeApiSelection.test.ts"] + module_src_runtimeApiSelection_ts["src/runtimeApiSelection.ts"] module_src_runtimeBindings_test_ts["src/runtimeBindings.test.ts"] module_src_runtimeBindings_ts["src/runtimeBindings.ts"] - module_src_runtimeDatabaseOperationExecutor_ts["src/runtimeDatabaseOperationExecutor.ts"] - module_src_runtimeDataSourceOperations_test_ts["src/runtimeDataSourceOperations.test.ts"] - module_src_runtimeDataSourceOperations_ts["src/runtimeDataSourceOperations.ts"] module_src_runtimeDbPersist_test_ts["src/runtimeDbPersist.test.ts"] module_src_runtimeDbPersist_ts["src/runtimeDbPersist.ts"] module_src_runtimeEventExecution_test_ts["src/runtimeEventExecution.test.ts"] @@ -5867,7 +6014,8 @@

    Export graph

    module_src_runtimeRepeatEmptyState_ts["src/runtimeRepeatEmptyState.ts"] module_src_RuntimeScreen_tsx["src/RuntimeScreen.tsx"] module_src_runtimeScreenLoaders_arrayPath_test_ts["src/runtimeScreenLoaders.arrayPath.test.ts"] - module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"] + module_src_runtimeScreenLoaders_execution_test_ts["src/runtimeScreenLoaders.execution.test.ts"] + module_src_runtimeScreenLoaders_lifecycle_test_ts["src/runtimeScreenLoaders.lifecycle.test.ts"] module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"] module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"] module_src_runtimeStateAdapterConfig_test_ts["src/runtimeStateAdapterConfig.test.ts"] @@ -5907,15 +6055,13 @@

    Export graph

    export_createRuntimeActionRegistry -.-> export_RuntimeBindingOperationResultCache export_createRuntimeActionRegistry -.-> export_RuntimeBindingOperationResultWriter + export_createRuntimeApiOperationExecutor["createRuntimeApiOperationExecutor"] + module_src_runtimeApiOperations_ts --> export_createRuntimeApiOperationExecutor + export_createRuntimeApiOperationExecutor -.-> + export_RuntimeApiOperationExecutorOptions export_createRuntimeApiOperationExecutor + -.-> export_RuntimeBindingOperationExecutor export_createRuntimeBindingOperationKey["createRuntimeBindingOperationKey"] module_src_runtimeBindings_ts --> export_createRuntimeBindingOperationKey - export_createRuntimeDataSourceOperationExecutor["createRuntimeDataSourceOperationExecutor"] - module_src_runtimeDataSourceOperations_ts --> - export_createRuntimeDataSourceOperationExecutor - export_createRuntimeDataSourceOperationExecutor -.-> - export_RuntimeBindingOperationExecutor - export_createRuntimeDataSourceOperationExecutor -.-> - export_RuntimeDataSourceOperationExecutorOptions export_createRuntimeMemoryStateAdapter["createRuntimeMemoryStateAdapter"] module_src_runtimeStateAdapter_ts --> export_createRuntimeMemoryStateAdapter export_createRuntimeMemoryStateAdapter -.-> @@ -6007,6 +6153,10 @@

    Export graph

    module_src_runtimeActionRegistry_ts --> export_RuntimeActionResolutionScope export_RuntimeAdapterDescriptor["RuntimeAdapterDescriptor"] module_src_runtimeManifest_ts --> export_RuntimeAdapterDescriptor + export_RuntimeApiOperationExecutorOptions["RuntimeApiOperationExecutorOptions"] + module_src_runtimeApiOperations_ts --> export_RuntimeApiOperationExecutorOptions + export_RuntimeApiOperationSelection["RuntimeApiOperationSelection"] + module_src_runtimeApiSelection_ts --> export_RuntimeApiOperationSelection export_RuntimeBindingDescriptor["RuntimeBindingDescriptor"] module_src_runtimeManifest_ts --> export_RuntimeBindingDescriptor export_RuntimeBindingOperationExecutionArgs["RuntimeBindingOperationExecutionArgs"] @@ -6038,9 +6188,6 @@

    Export graph

    export_RuntimeComponentEventDispatchArgs -.-> export_RuntimeBindingOperationExecutor export_RuntimeComponentEventDispatchArgs -.-> export_RuntimeBindingOperationResultWriter - export_RuntimeDataSourceOperationExecutorOptions["RuntimeDataSourceOperationExecutorOptions"] - module_src_runtimeDataSourceOperations_ts --> - export_RuntimeDataSourceOperationExecutorOptions export_RuntimeDbPersistError["RuntimeDbPersistError"] module_src_runtimeDbPersist_ts --> export_RuntimeDbPersistError export_RuntimeDbPersistExecutionResult["RuntimeDbPersistExecutionResult"] @@ -6135,7 +6282,7 @@

    Export graph

    export_RuntimeBindingResolutionContext export_useRuntimeScreenOperationLoaders -.-> export_RuntimeScreenOperationLoaderState export_validateRuntimeBindingOperationRef["validateRuntimeBindingOperationRef"] - module_src_runtimeBindings_ts --> export_validateRuntimeBindingOperationRef + module_src_runtimeApiSelection_ts --> export_validateRuntimeBindingOperationRef export_wrapRuntimeEventProps["wrapRuntimeEventProps"] module_src_runtimeActionRegistry_ts --> export_wrapRuntimeEventProps export_wrapRuntimeEventProps -.-> export_RuntimeEventPropWrapArgs @@ -6152,13 +6299,16 @@

    Export graph

    module_src_registry_tsx["src/registry.tsx"] module_src_rendering_test_ts["src/rendering.test.ts"] module_src_rendering_ts["src/rendering.ts"] - module_src_runtimeActionRegistry_test_ts["src/runtimeActionRegistry.test.ts"] + module_src_runtimeActionRegistry_actions_test_ts["src/runtimeActionRegistry.actions.test.ts"] + module_src_runtimeActionRegistry_chains_test_ts["src/runtimeActionRegistry.chains.test.ts"] + module_src_runtimeActionRegistry_operations_test_ts["src/runtimeActionRegistry.operations.test.ts"] module_src_runtimeActionRegistry_ts["src/runtimeActionRegistry.ts"] + module_src_runtimeApiOperations_test_ts["src/runtimeApiOperations.test.ts"] + module_src_runtimeApiOperations_ts["src/runtimeApiOperations.ts"] + module_src_runtimeApiSelection_test_ts["src/runtimeApiSelection.test.ts"] + module_src_runtimeApiSelection_ts["src/runtimeApiSelection.ts"] module_src_runtimeBindings_test_ts["src/runtimeBindings.test.ts"] module_src_runtimeBindings_ts["src/runtimeBindings.ts"] - module_src_runtimeDatabaseOperationExecutor_ts["src/runtimeDatabaseOperationExecutor.ts"] - module_src_runtimeDataSourceOperations_test_ts["src/runtimeDataSourceOperations.test.ts"] - module_src_runtimeDataSourceOperations_ts["src/runtimeDataSourceOperations.ts"] module_src_runtimeDbPersist_test_ts["src/runtimeDbPersist.test.ts"] module_src_runtimeDbPersist_ts["src/runtimeDbPersist.ts"] module_src_runtimeEventExecution_test_ts["src/runtimeEventExecution.test.ts"] @@ -6181,7 +6331,8 @@

    Export graph

    module_src_runtimeRepeatEmptyState_ts["src/runtimeRepeatEmptyState.ts"] module_src_RuntimeScreen_tsx["src/RuntimeScreen.tsx"] module_src_runtimeScreenLoaders_arrayPath_test_ts["src/runtimeScreenLoaders.arrayPath.test.ts"] - module_src_runtimeScreenLoaders_test_ts["src/runtimeScreenLoaders.test.ts"] + module_src_runtimeScreenLoaders_execution_test_ts["src/runtimeScreenLoaders.execution.test.ts"] + module_src_runtimeScreenLoaders_lifecycle_test_ts["src/runtimeScreenLoaders.lifecycle.test.ts"] module_src_runtimeScreenLoaders_ts["src/runtimeScreenLoaders.ts"] module_src_runtimeStateAdapter_ts["src/runtimeStateAdapter.ts"] module_src_runtimeStateAdapterConfig_test_ts["src/runtimeStateAdapterConfig.test.ts"] @@ -6217,12 +6368,12 @@

    Export graph

    export_createRuntimeActionRegistry -.-> export_RuntimeBindingOperationExecutor export_createRuntimeActionRegistry -.-> export_RuntimeBindingOperationResultCache export_createRuntimeActionRegistry -.-> export_RuntimeBindingOperationResultWriter + export_createRuntimeApiOperationExecutor["createRuntimeApiOperationExecutor"] + module_src_runtimeApiOperations_ts --> export_createRuntimeApiOperationExecutor + export_createRuntimeApiOperationExecutor -.-> export_RuntimeApiOperationExecutorOptions + export_createRuntimeApiOperationExecutor -.-> export_RuntimeBindingOperationExecutor export_createRuntimeBindingOperationKey["createRuntimeBindingOperationKey"] module_src_runtimeBindings_ts --> export_createRuntimeBindingOperationKey - export_createRuntimeDataSourceOperationExecutor["createRuntimeDataSourceOperationExecutor"] - module_src_runtimeDataSourceOperations_ts --> export_createRuntimeDataSourceOperationExecutor - export_createRuntimeDataSourceOperationExecutor -.-> export_RuntimeBindingOperationExecutor - export_createRuntimeDataSourceOperationExecutor -.-> export_RuntimeDataSourceOperationExecutorOptions export_createRuntimeMemoryStateAdapter["createRuntimeMemoryStateAdapter"] module_src_runtimeStateAdapter_ts --> export_createRuntimeMemoryStateAdapter export_createRuntimeMemoryStateAdapter -.-> export_RuntimeMemoryStateAdapterOptions @@ -6306,6 +6457,10 @@

    Export graph

    module_src_runtimeActionRegistry_ts --> export_RuntimeActionResolutionScope export_RuntimeAdapterDescriptor["RuntimeAdapterDescriptor"] module_src_runtimeManifest_ts --> export_RuntimeAdapterDescriptor + export_RuntimeApiOperationExecutorOptions["RuntimeApiOperationExecutorOptions"] + module_src_runtimeApiOperations_ts --> export_RuntimeApiOperationExecutorOptions + export_RuntimeApiOperationSelection["RuntimeApiOperationSelection"] + module_src_runtimeApiSelection_ts --> export_RuntimeApiOperationSelection export_RuntimeBindingDescriptor["RuntimeBindingDescriptor"] module_src_runtimeManifest_ts --> export_RuntimeBindingDescriptor export_RuntimeBindingOperationExecutionArgs["RuntimeBindingOperationExecutionArgs"] @@ -6335,8 +6490,6 @@

    Export graph

    export_RuntimeComponentEventDispatchArgs -.-> export_RuntimeActionHandler export_RuntimeComponentEventDispatchArgs -.-> export_RuntimeBindingOperationExecutor export_RuntimeComponentEventDispatchArgs -.-> export_RuntimeBindingOperationResultWriter - export_RuntimeDataSourceOperationExecutorOptions["RuntimeDataSourceOperationExecutorOptions"] - module_src_runtimeDataSourceOperations_ts --> export_RuntimeDataSourceOperationExecutorOptions export_RuntimeDbPersistError["RuntimeDbPersistError"] module_src_runtimeDbPersist_ts --> export_RuntimeDbPersistError export_RuntimeDbPersistExecutionResult["RuntimeDbPersistExecutionResult"] @@ -6429,7 +6582,7 @@

    Export graph

    export_useRuntimeScreenOperationLoaders -.-> export_RuntimeBindingResolutionContext export_useRuntimeScreenOperationLoaders -.-> export_RuntimeScreenOperationLoaderState export_validateRuntimeBindingOperationRef["validateRuntimeBindingOperationRef"] - module_src_runtimeBindings_ts --> export_validateRuntimeBindingOperationRef + module_src_runtimeApiSelection_ts --> export_validateRuntimeBindingOperationRef export_wrapRuntimeEventProps["wrapRuntimeEventProps"] module_src_runtimeActionRegistry_ts --> export_wrapRuntimeEventProps export_wrapRuntimeEventProps -.-> export_RuntimeEventPropWrapArgs @@ -6920,30 +7073,37 @@

    validateRuntimeBindingOperationRef sequence

    diagrams/sequences/validate-runtime-binding-operation-ref.mmd

    - sequenceDiagram participant participant_createRuntimeBindingDiagnostic as - createRuntimeBindingDiagnostic participant participant_resolveRuntimeBindingEndpoint - as resolveRuntimeBindingEndpoint participant + sequenceDiagram participant participant_createApiDiagnostic as createApiDiagnostic + participant participant_findRuntimeApi as findRuntimeApi participant + participant_resolveRuntimeApiEndpoint as resolveRuntimeApiEndpoint participant participant_validateRuntimeBindingOperationRef as validateRuntimeBindingOperationRef - participant_validateRuntimeBindingOperationRef->>participant_createRuntimeBindingDiagnostic: - createRuntimeBindingDiagnostic() - participant_createRuntimeBindingDiagnostic-->>participant_validateRuntimeBindingOperationRef: + participant_validateRuntimeBindingOperationRef->>participant_findRuntimeApi: + findRuntimeApi() + participant_findRuntimeApi-->>participant_validateRuntimeBindingOperationRef: + return + participant_validateRuntimeBindingOperationRef->>participant_createApiDiagnostic: + createApiDiagnostic() + participant_createApiDiagnostic-->>participant_validateRuntimeBindingOperationRef: return - participant_validateRuntimeBindingOperationRef->>participant_resolveRuntimeBindingEndpoint: - resolveRuntimeBindingEndpoint() - participant_resolveRuntimeBindingEndpoint-->>participant_validateRuntimeBindingOperationRef: + participant_validateRuntimeBindingOperationRef->>participant_resolveRuntimeApiEndpoint: + resolveRuntimeApiEndpoint() + participant_resolveRuntimeApiEndpoint-->>participant_validateRuntimeBindingOperationRef: return
    View Mermaid source
     sequenceDiagram
    -  participant participant_createRuntimeBindingDiagnostic as createRuntimeBindingDiagnostic
    -  participant participant_resolveRuntimeBindingEndpoint as resolveRuntimeBindingEndpoint
    +  participant participant_createApiDiagnostic as createApiDiagnostic
    +  participant participant_findRuntimeApi as findRuntimeApi
    +  participant participant_resolveRuntimeApiEndpoint as resolveRuntimeApiEndpoint
       participant participant_validateRuntimeBindingOperationRef as validateRuntimeBindingOperationRef
    -  participant_validateRuntimeBindingOperationRef->>participant_createRuntimeBindingDiagnostic: createRuntimeBindingDiagnostic()
    -  participant_createRuntimeBindingDiagnostic-->>participant_validateRuntimeBindingOperationRef: return
    -  participant_validateRuntimeBindingOperationRef->>participant_resolveRuntimeBindingEndpoint: resolveRuntimeBindingEndpoint()
    -  participant_resolveRuntimeBindingEndpoint-->>participant_validateRuntimeBindingOperationRef: return
    +  participant_validateRuntimeBindingOperationRef->>participant_findRuntimeApi: findRuntimeApi()
    +  participant_findRuntimeApi-->>participant_validateRuntimeBindingOperationRef: return
    +  participant_validateRuntimeBindingOperationRef->>participant_createApiDiagnostic: createApiDiagnostic()
    +  participant_createApiDiagnostic-->>participant_validateRuntimeBindingOperationRef: return
    +  participant_validateRuntimeBindingOperationRef->>participant_resolveRuntimeApiEndpoint: resolveRuntimeApiEndpoint()
    +  participant_resolveRuntimeApiEndpoint-->>participant_validateRuntimeBindingOperationRef: return
     
    @@ -7091,24 +7251,95 @@

    getUnknownComponentDiagnostic

    + + + + + + + - - - - @@ -8396,64 +8442,69 @@

    createOperationResults

    +
    { readonly bindingContext?: Record<string, unknown>; readonly - dataSources?: RuntimeBindingResolutionContext["dataSources"]; - readonly executeOperation?: RuntimeBindingOperationExecutor; readonly + apis?: RuntimeBindingResolutionContext["apis"]; readonly + executeOperation?: RuntimeBindingOperationExecutor; readonly operationResults?: RuntimeBindingOperationResultCache; readonly onDiagnostics?: (diagnostics: readonly DataSourceDiagnostic[]) => void; readonly screen: ScreenSpec; }ManifestProvider

    RuntimeRenderer

    src/RuntimeRenderer.tsx:76:1

    @@ -5079,20 +5158,20 @@

    RuntimeRenderer

    bindingContextRecord<string, unknown> | undefinedapisApiDefinitionList | undefined no
    dataBindingsComponentDataBindingRegistry | undefinedbindingContextRecord<string, unknown> | undefined no
    dataSourcesDataSourceRegistry | undefineddataBindingsComponentDataBindingRegistry | undefined no