@ankhorage/runtime 0.2.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/dist/RuntimeScreen.d.ts.map +1 -1
- package/dist/RuntimeScreen.js +5 -43
- package/dist/RuntimeScreen.js.map +1 -1
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/registry.d.ts +0 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +0 -1
- package/dist/registry.js.map +1 -1
- package/dist/runtimeDataSourceOperations.d.ts +3 -1
- package/dist/runtimeDataSourceOperations.d.ts.map +1 -1
- package/dist/runtimeDataSourceOperations.js +31 -26
- package/dist/runtimeDataSourceOperations.js.map +1 -1
- package/dist/runtimeDatabaseOperationExecutor.d.ts +9 -0
- package/dist/runtimeDatabaseOperationExecutor.d.ts.map +1 -0
- package/dist/runtimeDatabaseOperationExecutor.js +228 -0
- package/dist/runtimeDatabaseOperationExecutor.js.map +1 -0
- package/dist/runtimeScreenLoaders.d.ts +1 -2
- package/dist/runtimeScreenLoaders.d.ts.map +1 -1
- package/dist/runtimeScreenLoaders.js +1 -4
- package/dist/runtimeScreenLoaders.js.map +1 -1
- package/package.json +3 -3
- package/paradox/badges/npm.svg +3 -3
- package/paradox/components.md +1 -1
- package/paradox/diagrams/architecture-overview.mmd +5 -12
- package/paradox/diagrams/export-graph.mmd +1 -31
- package/paradox/diagrams/module-relationships.mmd +4 -9
- package/paradox/diagrams/sequences/runtime-screen.mmd +0 -3
- package/paradox/exports.json +30 -311
- package/paradox/exports.md +94 -199
- package/paradox/index.html +382 -744
- package/paradox/paradox.json +685 -928
- package/dist/appExtensionRegistry.d.ts +0 -3
- package/dist/appExtensionRegistry.d.ts.map +0 -1
- package/dist/appExtensionRegistry.js +0 -2
- package/dist/appExtensionRegistry.js.map +0 -1
- package/dist/runtimeApiLoaders.d.ts +0 -35
- package/dist/runtimeApiLoaders.d.ts.map +0 -1
- package/dist/runtimeApiLoaders.js +0 -218
- package/dist/runtimeApiLoaders.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @ankhorage/runtime
|
|
2
2
|
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 3e09665: Consume the canonical Contracts 4 and Data Sources 1 API taxonomy, remove the obsolete `manifest.data.apis` seed-loader surface, and execute database-backed generated API operations through their referenced runtime database adapters.
|
|
8
|
+
|
|
9
|
+
## 0.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 290ca3a: Remove Runtime-owned concrete and app-extension component registry exports so hosts inject all component registries explicitly.
|
|
14
|
+
|
|
3
15
|
## 0.2.4
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# @ankhorage/runtime
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Platform-neutral runtime contracts and helpers for Ankhorage generated apps.
|
|
9
9
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuntimeScreen.d.ts","sourceRoot":"","sources":["../src/RuntimeScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"RuntimeScreen.d.ts","sourceRoot":"","sources":["../src/RuntimeScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMpD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;CACtC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,qBA0BtD"}
|
package/dist/RuntimeScreen.js
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { useRuntimeApiStateLoaders } from './runtimeApiLoaders';
|
|
3
2
|
import { RuntimeRenderer } from './RuntimeRenderer';
|
|
4
3
|
import { useRuntimeRendererConfig } from './RuntimeRendererConfig';
|
|
5
|
-
import {
|
|
4
|
+
import { useRuntimeScreenOperationLoaders } from './runtimeScreenLoaders';
|
|
5
|
+
import { createRuntimeMemoryStateAdapter } from './runtimeStateAdapter';
|
|
6
6
|
export function RuntimeScreen(props) {
|
|
7
7
|
const { manifest, screen, registry, stateAdapter: injectedStateAdapter } = props;
|
|
8
8
|
const runtimeConfig = useRuntimeRendererConfig();
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
...resolveApiLoadersFromBindings(manifest.dataBindings),
|
|
12
|
-
], [manifest.dataBindings, screen]);
|
|
13
|
-
const { stateAdapter, stateVersion } = useRuntimeApiStateLoaders({
|
|
14
|
-
data: manifest.data,
|
|
15
|
-
loaders,
|
|
16
|
-
stateAdapter: injectedStateAdapter,
|
|
17
|
-
});
|
|
9
|
+
const fallbackStateAdapter = React.useMemo(() => createRuntimeMemoryStateAdapter(), []);
|
|
10
|
+
const stateAdapter = injectedStateAdapter ?? fallbackStateAdapter;
|
|
18
11
|
const screenOperationLoaders = useRuntimeScreenOperationLoaders({
|
|
19
12
|
bindingContext: runtimeConfig.bindingContext,
|
|
20
13
|
dataSources: manifest.dataSources,
|
|
@@ -23,37 +16,6 @@ export function RuntimeScreen(props) {
|
|
|
23
16
|
onDiagnostics: runtimeConfig.onDiagnostics,
|
|
24
17
|
screen,
|
|
25
18
|
});
|
|
26
|
-
return (<RuntimeRenderer key={`${screen.id}:${
|
|
27
|
-
}
|
|
28
|
-
function resolveApiLoadersFromBindings(dataBindings) {
|
|
29
|
-
const loadersByApiId = new Map();
|
|
30
|
-
for (const componentBinding of Object.values(dataBindings ?? {})) {
|
|
31
|
-
for (const binding of Object.values(componentBinding.props ?? {})) {
|
|
32
|
-
const loader = resolveApiLoaderFromPropBinding(binding);
|
|
33
|
-
if (loader !== null && !loadersByApiId.has(loader.apiId)) {
|
|
34
|
-
loadersByApiId.set(loader.apiId, loader);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return [...loadersByApiId.values()].sort((left, right) => left.apiId.localeCompare(right.apiId));
|
|
39
|
-
}
|
|
40
|
-
function resolveApiLoaderFromPropBinding(binding) {
|
|
41
|
-
if (binding.source.kind !== 'state') {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
const parts = binding.source.path
|
|
45
|
-
.split('.')
|
|
46
|
-
.map((part) => part.trim())
|
|
47
|
-
.filter(Boolean);
|
|
48
|
-
const [root, apiId, collectionSlot] = parts;
|
|
49
|
-
if (root !== 'apis' || apiId === undefined || collectionSlot !== 'current') {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
kind: 'api',
|
|
54
|
-
apiId,
|
|
55
|
-
mode: 'one',
|
|
56
|
-
targetPath: `apis.${apiId}.current`,
|
|
57
|
-
};
|
|
19
|
+
return (<RuntimeRenderer key={`${screen.id}:${screenOperationLoaders.renderVersion}`} node={screen.root} isRoot registry={registry} stateAdapter={stateAdapter} dataBindings={manifest.dataBindings} dataSources={manifest.dataSources} operationResults={screenOperationLoaders.operationResults}/>);
|
|
58
20
|
}
|
|
59
21
|
//# sourceMappingURL=RuntimeScreen.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuntimeScreen.js","sourceRoot":"","sources":["../src/RuntimeScreen.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RuntimeScreen.js","sourceRoot":"","sources":["../src/RuntimeScreen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AASxE,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,oBAAoB,EAAE,GAAG,KAAK,CAAC;IACjF,MAAM,aAAa,GAAG,wBAAwB,EAAE,CAAC;IACjD,MAAM,oBAAoB,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,+BAA+B,EAAE,EAAE,EAAE,CAAC,CAAC;IACxF,MAAM,YAAY,GAAG,oBAAoB,IAAI,oBAAoB,CAAC;IAClE,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;QAC9D,cAAc,EAAE,aAAa,CAAC,cAAc;QAC5C,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,gBAAgB,EAAE,aAAa,CAAC,gBAAgB;QAChD,gBAAgB,EAAE,aAAa,CAAC,gBAAgB;QAChD,aAAa,EAAE,aAAa,CAAC,aAAa;QAC1C,MAAM;KACP,CAAC,CAAC;IAEH,OAAO,CACL,CAAC,eAAe,CACd,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,sBAAsB,CAAC,aAAa,EAAE,CAAC,CAC5D,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAClB,MAAM,CACN,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,YAAY,CAAC,CAAC,YAAY,CAAC,CAC3B,YAAY,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CACpC,WAAW,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAClC,gBAAgB,CAAC,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,EAC1D,CACH,CAAC;AACJ,CAAC","sourcesContent":["import type { AppManifest, ScreenSpec, StateAdapter } from '@ankhorage/contracts';\nimport React from 'react';\n\nimport type { ComponentRegistry } from './registry';\nimport { RuntimeRenderer } from './RuntimeRenderer';\nimport { useRuntimeRendererConfig } from './RuntimeRendererConfig';\nimport { useRuntimeScreenOperationLoaders } from './runtimeScreenLoaders';\nimport { createRuntimeMemoryStateAdapter } from './runtimeStateAdapter';\n\nexport interface RuntimeScreenProps {\n readonly manifest: AppManifest;\n readonly screen: ScreenSpec;\n readonly registry?: ComponentRegistry;\n readonly stateAdapter?: StateAdapter;\n}\n\nexport function RuntimeScreen(props: RuntimeScreenProps) {\n const { manifest, screen, registry, stateAdapter: injectedStateAdapter } = props;\n const runtimeConfig = useRuntimeRendererConfig();\n const fallbackStateAdapter = React.useMemo(() => createRuntimeMemoryStateAdapter(), []);\n const stateAdapter = injectedStateAdapter ?? fallbackStateAdapter;\n const screenOperationLoaders = useRuntimeScreenOperationLoaders({\n bindingContext: runtimeConfig.bindingContext,\n dataSources: manifest.dataSources,\n executeOperation: runtimeConfig.executeOperation,\n operationResults: runtimeConfig.operationResults,\n onDiagnostics: runtimeConfig.onDiagnostics,\n screen,\n });\n\n return (\n <RuntimeRenderer\n key={`${screen.id}:${screenOperationLoaders.renderVersion}`}\n node={screen.root}\n isRoot\n registry={registry}\n stateAdapter={stateAdapter}\n dataBindings={manifest.dataBindings}\n dataSources={manifest.dataSources}\n operationResults={screenOperationLoaders.operationResults}\n />\n );\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
export { ManifestContext, ManifestProvider, useManifest, useManifestContext, useOptionalManifestContext, } from './ManifestContext';
|
|
2
2
|
export type { ComponentRegistry } from './registry';
|
|
3
|
-
export {
|
|
3
|
+
export { createComponentRegistry } from './registry';
|
|
4
4
|
export type { RuntimeActionRegistry, RuntimeActionResolutionArgs, RuntimeActionResolutionScope, RuntimeComponentEventDispatchArgs, RuntimeEventPropWrapArgs, } from './runtimeActionRegistry';
|
|
5
5
|
export { createComponentEventFromHandlerArgs, createRuntimeActionRegistry, dispatchRuntimeComponentEvent, resolveRuntimeActionPayload, resolveRuntimeActionValue, wrapRuntimeEventProps, } from './runtimeActionRegistry';
|
|
6
|
-
export type { RuntimeApiLoaderDefinition, RuntimeApiLoaderDiagnostic, RuntimeApiLoaderExecutionResult, RuntimeApiLoaderMaterializationResult, RuntimeApiLoaderMode, } from './runtimeApiLoaders';
|
|
7
|
-
export { executeRuntimeApiLoaders, materializeRuntimeApiLoaderState, useRuntimeApiStateLoaders, } from './runtimeApiLoaders';
|
|
8
6
|
export type { RuntimeBindingOperationExecutionArgs, RuntimeBindingOperationExecutionResult, RuntimeBindingOperationExecutor, RuntimeBindingOperationKey, RuntimeBindingOperationResultCache, RuntimeBindingOperationResultWriter, RuntimeBindingResolutionArgs, RuntimeBindingResolutionContext, RuntimeBindingResolutionResult, } from './runtimeBindings';
|
|
9
7
|
export { createRuntimeBindingOperationKey, resolveBindingInputMap, resolveRuntimeBindings, resolveRuntimeBindingsAsync, resolveRuntimeBindingValue, resolveRuntimeBindingValueSync, validateRuntimeBindingOperationRef, } from './runtimeBindings';
|
|
10
8
|
export type { RuntimeDataSourceOperationExecutorOptions } from './runtimeDataSourceOperations';
|
|
@@ -21,7 +19,7 @@ export { shouldRenderRuntimeRepeatEmptyState } from './runtimeRepeatEmptyState';
|
|
|
21
19
|
export type { RuntimeScreenProps } from './RuntimeScreen';
|
|
22
20
|
export { RuntimeScreen } from './RuntimeScreen';
|
|
23
21
|
export type { RuntimeScreenOperationLoaderExecutionResult, RuntimeScreenOperationLoaderState, } from './runtimeScreenLoaders';
|
|
24
|
-
export { createPendingRuntimeScreenOperationLoaderState, createRuntimeScreenLoaderRequestKey, executeRuntimeScreenOperationLoaders,
|
|
22
|
+
export { createPendingRuntimeScreenOperationLoaderState, createRuntimeScreenLoaderRequestKey, executeRuntimeScreenOperationLoaders, resolveScreenOperationLoaders, useRuntimeScreenOperationLoaders, } from './runtimeScreenLoaders';
|
|
25
23
|
export type { RuntimeMemoryStateAdapterOptions } from './runtimeStateAdapter';
|
|
26
24
|
export { createRuntimeMemoryStateAdapter } from './runtimeStateAdapter';
|
|
27
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,YAAY,EACV,qBAAqB,EACrB,2BAA2B,EAC3B,4BAA4B,EAC5B,iCAAiC,EACjC,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,mCAAmC,EACnC,2BAA2B,EAC3B,6BAA6B,EAC7B,2BAA2B,EAC3B,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,oCAAoC,EACpC,sCAAsC,EACtC,+BAA+B,EAC/B,0BAA0B,EAC1B,kCAAkC,EAClC,mCAAmC,EACnC,4BAA4B,EAC5B,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gCAAgC,EAChC,sBAAsB,EACtB,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,EAC1B,8BAA8B,EAC9B,kCAAkC,GACnC,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,yCAAyC,EAAE,MAAM,+BAA+B,CAAC;AAC/F,OAAO,EAAE,wCAAwC,EAAE,MAAM,+BAA+B,CAAC;AACzF,YAAY,EACV,qBAAqB,EACrB,+BAA+B,EAC/B,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAC3B,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,0CAA0C,EAC1C,KAAK,+BAA+B,GACrC,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACL,+BAA+B,EAC/B,8BAA8B,EAC9B,0BAA0B,EAC1B,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,6BAA6B,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mCAAmC,EAAE,MAAM,2BAA2B,CAAC;AAChF,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EACV,2CAA2C,EAC3C,iCAAiC,GAClC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,8CAA8C,EAC9C,mCAAmC,EACnC,oCAAoC,EACpC,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gCAAgC,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { ManifestContext, ManifestProvider, useManifest, useManifestContext, useOptionalManifestContext, } from './ManifestContext';
|
|
2
|
-
export {
|
|
2
|
+
export { createComponentRegistry } from './registry';
|
|
3
3
|
export { createComponentEventFromHandlerArgs, createRuntimeActionRegistry, dispatchRuntimeComponentEvent, resolveRuntimeActionPayload, resolveRuntimeActionValue, wrapRuntimeEventProps, } from './runtimeActionRegistry';
|
|
4
|
-
export { executeRuntimeApiLoaders, materializeRuntimeApiLoaderState, useRuntimeApiStateLoaders, } from './runtimeApiLoaders';
|
|
5
4
|
export { createRuntimeBindingOperationKey, resolveBindingInputMap, resolveRuntimeBindings, resolveRuntimeBindingsAsync, resolveRuntimeBindingValue, resolveRuntimeBindingValueSync, validateRuntimeBindingOperationRef, } from './runtimeBindings';
|
|
6
5
|
export { createRuntimeDataSourceOperationExecutor } from './runtimeDataSourceOperations';
|
|
7
6
|
export { createDbPersistActionHandler, createDbPersistAdapterError, executeDbPersistAction, resolveDbPersistInput, } from './runtimeDbPersist';
|
|
@@ -11,6 +10,6 @@ export { RuntimeRenderer } from './RuntimeRenderer';
|
|
|
11
10
|
export { composeRuntimeNodePropsResolver, composeRuntimeRendererWrapNode, mergeRuntimeRendererConfig, RuntimeRendererConfigProvider, useRuntimeRendererConfig, } from './RuntimeRendererConfig';
|
|
12
11
|
export { shouldRenderRuntimeRepeatEmptyState } from './runtimeRepeatEmptyState';
|
|
13
12
|
export { RuntimeScreen } from './RuntimeScreen';
|
|
14
|
-
export { createPendingRuntimeScreenOperationLoaderState, createRuntimeScreenLoaderRequestKey, executeRuntimeScreenOperationLoaders,
|
|
13
|
+
export { createPendingRuntimeScreenOperationLoaderState, createRuntimeScreenLoaderRequestKey, executeRuntimeScreenOperationLoaders, resolveScreenOperationLoaders, useRuntimeScreenOperationLoaders, } from './runtimeScreenLoaders';
|
|
15
14
|
export { createRuntimeMemoryStateAdapter } from './runtimeStateAdapter';
|
|
16
15
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAQrD,OAAO,EACL,mCAAmC,EACnC,2BAA2B,EAC3B,6BAA6B,EAC7B,2BAA2B,EAC3B,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AAYjC,OAAO,EACL,gCAAgC,EAChC,sBAAsB,EACtB,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,EAC1B,8BAA8B,EAC9B,kCAAkC,GACnC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,wCAAwC,EAAE,MAAM,+BAA+B,CAAC;AAMzF,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAC3B,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,0CAA0C,GAE3C,MAAM,yBAAyB,CAAC;AAWjC,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACL,+BAA+B,EAC/B,8BAA8B,EAC9B,0BAA0B,EAQ1B,6BAA6B,EAG7B,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mCAAmC,EAAE,MAAM,2BAA2B,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAKhD,OAAO,EACL,8CAA8C,EAC9C,mCAAmC,EACnC,oCAAoC,EACpC,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["export {\n ManifestContext,\n ManifestProvider,\n useManifest,\n useManifestContext,\n useOptionalManifestContext,\n} from './ManifestContext';\nexport type { ComponentRegistry } from './registry';\nexport { createComponentRegistry } from './registry';\nexport type {\n RuntimeActionRegistry,\n RuntimeActionResolutionArgs,\n RuntimeActionResolutionScope,\n RuntimeComponentEventDispatchArgs,\n RuntimeEventPropWrapArgs,\n} from './runtimeActionRegistry';\nexport {\n createComponentEventFromHandlerArgs,\n createRuntimeActionRegistry,\n dispatchRuntimeComponentEvent,\n resolveRuntimeActionPayload,\n resolveRuntimeActionValue,\n wrapRuntimeEventProps,\n} from './runtimeActionRegistry';\nexport type {\n RuntimeBindingOperationExecutionArgs,\n RuntimeBindingOperationExecutionResult,\n RuntimeBindingOperationExecutor,\n RuntimeBindingOperationKey,\n RuntimeBindingOperationResultCache,\n RuntimeBindingOperationResultWriter,\n RuntimeBindingResolutionArgs,\n RuntimeBindingResolutionContext,\n RuntimeBindingResolutionResult,\n} from './runtimeBindings';\nexport {\n createRuntimeBindingOperationKey,\n resolveBindingInputMap,\n resolveRuntimeBindings,\n resolveRuntimeBindingsAsync,\n resolveRuntimeBindingValue,\n resolveRuntimeBindingValueSync,\n validateRuntimeBindingOperationRef,\n} from './runtimeBindings';\nexport type { RuntimeDataSourceOperationExecutorOptions } from './runtimeDataSourceOperations';\nexport { createRuntimeDataSourceOperationExecutor } from './runtimeDataSourceOperations';\nexport type {\n RuntimeDbPersistError,\n RuntimeDbPersistExecutionResult,\n RuntimeDbPersistResult,\n} from './runtimeDbPersist';\nexport {\n createDbPersistActionHandler,\n createDbPersistAdapterError,\n executeDbPersistAction,\n resolveDbPersistInput,\n} from './runtimeDbPersist';\nexport {\n dispatchRuntimeComponentEventWithReporting,\n type RuntimeEventDiagnosticsReporter,\n} from './runtimeEventExecution';\nexport type {\n RuntimeActionDescriptor,\n RuntimeAdapterDescriptor,\n RuntimeBindingDescriptor,\n RuntimeCapability,\n RuntimeDiagnostic,\n RuntimeManifest,\n RuntimeManifestConfig,\n RuntimeManifestInput,\n} from './runtimeManifest';\nexport {\n createRuntimeManifest,\n defineRuntimeAction,\n defineRuntimeAdapter,\n defineRuntimeBinding,\n listRuntimeCapabilities,\n RUNTIME_CAPABILITIES,\n RUNTIME_MANIFEST_KIND,\n} from './runtimeManifest';\nexport type { RuntimeRendererProps } from './RuntimeRenderer';\nexport { RuntimeRenderer } from './RuntimeRenderer';\nexport {\n composeRuntimeNodePropsResolver,\n composeRuntimeRendererWrapNode,\n mergeRuntimeRendererConfig,\n type RuntimeAction,\n type RuntimeActionExecutor,\n type RuntimeActionHandler,\n type RuntimeActionHandlerArgs,\n type RuntimeActionHandlers,\n type RuntimeNodePropsResolver,\n type RuntimeRendererConfig,\n RuntimeRendererConfigProvider,\n type RuntimeRendererWrapArgs,\n type RuntimeResolveNodePropsArgs,\n useRuntimeRendererConfig,\n} from './RuntimeRendererConfig';\nexport { shouldRenderRuntimeRepeatEmptyState } from './runtimeRepeatEmptyState';\nexport type { RuntimeScreenProps } from './RuntimeScreen';\nexport { RuntimeScreen } from './RuntimeScreen';\nexport type {\n RuntimeScreenOperationLoaderExecutionResult,\n RuntimeScreenOperationLoaderState,\n} from './runtimeScreenLoaders';\nexport {\n createPendingRuntimeScreenOperationLoaderState,\n createRuntimeScreenLoaderRequestKey,\n executeRuntimeScreenOperationLoaders,\n resolveScreenOperationLoaders,\n useRuntimeScreenOperationLoaders,\n} from './runtimeScreenLoaders';\nexport type { RuntimeMemoryStateAdapterOptions } from './runtimeStateAdapter';\nexport { createRuntimeMemoryStateAdapter } from './runtimeStateAdapter';\n"]}
|
package/dist/registry.d.ts
CHANGED
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.tsx"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.tsx"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/registry.js
CHANGED
package/dist/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["export type { ComponentRegistry } from './componentRegistry';\nexport { createComponentRegistry } from './componentRegistry';\n"]}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { DbAdapter } from '@ankhorage/contracts';
|
|
1
2
|
import type { EndpointTestCredentialResolver, EndpointTestFetch } from '@ankhorage/data-sources';
|
|
2
3
|
import type { RuntimeBindingOperationExecutor } from './runtimeBindings';
|
|
3
4
|
export interface RuntimeDataSourceOperationExecutorOptions {
|
|
4
|
-
readonly fetch
|
|
5
|
+
readonly fetch?: EndpointTestFetch;
|
|
5
6
|
readonly credentialResolver?: EndpointTestCredentialResolver;
|
|
7
|
+
readonly databaseAdapters?: Readonly<Record<string, DbAdapter>>;
|
|
6
8
|
}
|
|
7
9
|
export declare function createRuntimeDataSourceOperationExecutor(options: RuntimeDataSourceOperationExecutorOptions): RuntimeBindingOperationExecutor;
|
|
8
10
|
//# sourceMappingURL=runtimeDataSourceOperations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimeDataSourceOperations.d.ts","sourceRoot":"","sources":["../src/runtimeDataSourceOperations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtimeDataSourceOperations.d.ts","sourceRoot":"","sources":["../src/runtimeDataSourceOperations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsC,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,KAAK,EAAE,8BAA8B,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGjG,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,mBAAmB,CAAC;AAGzE,MAAM,WAAW,yCAAyC;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,8BAA8B,CAAC;IAC7D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;CACjE;AAED,wBAAgB,wCAAwC,CACtD,OAAO,EAAE,yCAAyC,GACjD,+BAA+B,CAsCjC"}
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import { testEndpoint } from '@ankhorage/data-sources';
|
|
2
|
+
import { executeRuntimeDatabaseOperation } from './runtimeDatabaseOperationExecutor';
|
|
2
3
|
export function createRuntimeDataSourceOperationExecutor(options) {
|
|
3
4
|
return async ({ dataSource, endpoint, input, operation }) => {
|
|
4
5
|
if (endpoint === undefined) {
|
|
5
|
-
return
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
6
|
+
return missingEndpoint(operation.dataSourceId, operation.endpointId, operation.operationId);
|
|
7
|
+
}
|
|
8
|
+
const operationConfig = endpoint.operations[operation.operationId];
|
|
9
|
+
if (operationConfig === undefined) {
|
|
10
|
+
return missingOperation(operation.dataSourceId, endpoint.id, operation.operationId);
|
|
11
11
|
}
|
|
12
12
|
const values = asBindingValueRecord(input);
|
|
13
13
|
if (input !== undefined && values === undefined) {
|
|
14
|
-
return
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
return invalidInput(operation.dataSourceId, endpoint.id, operation.operationId);
|
|
15
|
+
}
|
|
16
|
+
if (operationConfig.protocol === 'database') {
|
|
17
|
+
return executeRuntimeDatabaseOperation({
|
|
18
|
+
dataSource,
|
|
19
|
+
operation: operationConfig,
|
|
20
|
+
input: values,
|
|
21
|
+
databaseAdapters: options.databaseAdapters,
|
|
22
|
+
});
|
|
20
23
|
}
|
|
21
24
|
const result = await testEndpoint({
|
|
22
25
|
credentialResolver: options.credentialResolver,
|
|
@@ -26,28 +29,30 @@ export function createRuntimeDataSourceOperationExecutor(options) {
|
|
|
26
29
|
operationId: operation.operationId,
|
|
27
30
|
values,
|
|
28
31
|
});
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
diagnostics: result.diagnostics,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
return {
|
|
36
|
-
ok: true,
|
|
37
|
-
data: result.data ?? null,
|
|
38
|
-
diagnostics: result.diagnostics,
|
|
39
|
-
};
|
|
32
|
+
return result.ok
|
|
33
|
+
? { ok: true, data: result.data ?? null, diagnostics: result.diagnostics }
|
|
34
|
+
: { ok: false, diagnostics: result.diagnostics };
|
|
40
35
|
};
|
|
41
36
|
}
|
|
42
|
-
function
|
|
43
|
-
return {
|
|
44
|
-
|
|
37
|
+
function missingEndpoint(dataSourceId, endpointId, operationId) {
|
|
38
|
+
return failure(dataSourceId, endpointId, operationId, 'missing-endpoint', `Endpoint '${endpointId ?? '<default>'}' could not be found.`);
|
|
39
|
+
}
|
|
40
|
+
function missingOperation(dataSourceId, endpointId, operationId) {
|
|
41
|
+
return failure(dataSourceId, endpointId, operationId, 'missing-operation', `Operation '${operationId}' could not be found.`);
|
|
42
|
+
}
|
|
43
|
+
function invalidInput(dataSourceId, endpointId, operationId) {
|
|
44
|
+
return failure(dataSourceId, endpointId, operationId, 'invalid-config', 'Operation input must resolve to an object.');
|
|
45
|
+
}
|
|
46
|
+
function failure(dataSourceId, endpointId, operationId, code, message) {
|
|
47
|
+
const diagnostic = {
|
|
48
|
+
code,
|
|
45
49
|
dataSourceId,
|
|
46
50
|
endpointId,
|
|
47
51
|
operationId,
|
|
48
52
|
message,
|
|
49
53
|
severity: 'error',
|
|
50
54
|
};
|
|
55
|
+
return { ok: false, diagnostics: [diagnostic] };
|
|
51
56
|
}
|
|
52
57
|
function asBindingValueRecord(value) {
|
|
53
58
|
return isBindingValueRecord(value) ? value : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimeDataSourceOperations.js","sourceRoot":"","sources":["../src/runtimeDataSourceOperations.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"runtimeDataSourceOperations.js","sourceRoot":"","sources":["../src/runtimeDataSourceOperations.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BindingValue, DataSourceDiagnostic, DbAdapter } from '@ankhorage/contracts';\nimport type { EndpointTestCredentialResolver, EndpointTestFetch } from '@ankhorage/data-sources';\nimport { testEndpoint } from '@ankhorage/data-sources';\n\nimport type { RuntimeBindingOperationExecutor } from './runtimeBindings';\nimport { executeRuntimeDatabaseOperation } from './runtimeDatabaseOperationExecutor';\n\nexport interface RuntimeDataSourceOperationExecutorOptions {\n readonly fetch?: EndpointTestFetch;\n readonly credentialResolver?: EndpointTestCredentialResolver;\n readonly databaseAdapters?: Readonly<Record<string, DbAdapter>>;\n}\n\nexport function createRuntimeDataSourceOperationExecutor(\n options: RuntimeDataSourceOperationExecutorOptions,\n): RuntimeBindingOperationExecutor {\n return async ({ dataSource, endpoint, input, operation }) => {\n if (endpoint === undefined) {\n return missingEndpoint(operation.dataSourceId, operation.endpointId, operation.operationId);\n }\n\n const operationConfig = endpoint.operations[operation.operationId];\n if (operationConfig === undefined) {\n return missingOperation(operation.dataSourceId, endpoint.id, operation.operationId);\n }\n\n const values = asBindingValueRecord(input);\n if (input !== undefined && values === undefined) {\n return invalidInput(operation.dataSourceId, endpoint.id, operation.operationId);\n }\n\n if (operationConfig.protocol === 'database') {\n return executeRuntimeDatabaseOperation({\n dataSource,\n operation: operationConfig,\n input: values,\n databaseAdapters: options.databaseAdapters,\n });\n }\n\n const result = await testEndpoint({\n credentialResolver: options.credentialResolver,\n dataSource,\n endpointId: endpoint.id,\n fetch: options.fetch,\n operationId: operation.operationId,\n values,\n });\n\n return result.ok\n ? { ok: true, data: result.data ?? null, diagnostics: result.diagnostics }\n : { ok: false, diagnostics: result.diagnostics };\n };\n}\n\nfunction missingEndpoint(\n dataSourceId: string,\n endpointId: string | undefined,\n operationId: string,\n) {\n return failure(\n dataSourceId,\n endpointId,\n operationId,\n 'missing-endpoint',\n `Endpoint '${endpointId ?? '<default>'}' could not be found.`,\n );\n}\n\nfunction missingOperation(dataSourceId: string, endpointId: string, operationId: string) {\n return failure(\n dataSourceId,\n endpointId,\n operationId,\n 'missing-operation',\n `Operation '${operationId}' could not be found.`,\n );\n}\n\nfunction invalidInput(dataSourceId: string, endpointId: string, operationId: string) {\n return failure(\n dataSourceId,\n endpointId,\n operationId,\n 'invalid-config',\n 'Operation input must resolve to an object.',\n );\n}\n\nfunction failure(\n dataSourceId: string,\n endpointId: string | undefined,\n operationId: string,\n code: string,\n message: string,\n) {\n const diagnostic: DataSourceDiagnostic = {\n code,\n dataSourceId,\n endpointId,\n operationId,\n message,\n severity: 'error',\n };\n return { ok: false as const, diagnostics: [diagnostic] };\n}\n\nfunction asBindingValueRecord(\n value: BindingValue | undefined,\n): Readonly<Record<string, BindingValue>> | undefined {\n return isBindingValueRecord(value) ? value : undefined;\n}\n\nfunction isBindingValueRecord(\n value: BindingValue | undefined,\n): value is Readonly<Record<string, BindingValue>> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BindingValue, DataOperationConfig, DataSourceConfig, DbAdapter } from '@ankhorage/contracts';
|
|
2
|
+
import type { RuntimeBindingOperationExecutionResult } from './runtimeBindings';
|
|
3
|
+
export declare function executeRuntimeDatabaseOperation(args: {
|
|
4
|
+
readonly dataSource: DataSourceConfig;
|
|
5
|
+
readonly operation: DataOperationConfig;
|
|
6
|
+
readonly input: Readonly<Record<string, BindingValue>> | undefined;
|
|
7
|
+
readonly databaseAdapters: Readonly<Record<string, DbAdapter>> | undefined;
|
|
8
|
+
}): Promise<RuntimeBindingOperationExecutionResult>;
|
|
9
|
+
//# sourceMappingURL=runtimeDatabaseOperationExecutor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtimeDatabaseOperationExecutor.d.ts","sourceRoot":"","sources":["../src/runtimeDatabaseOperationExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAEhB,SAAS,EAGV,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,sCAAsC,EAAE,MAAM,mBAAmB,CAAC;AAEhF,wBAAsB,+BAA+B,CAAC,IAAI,EAAE;IAC1D,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC;IACnE,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC;CAC5E,GAAG,OAAO,CAAC,sCAAsC,CAAC,CA0BlD"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
export async function executeRuntimeDatabaseOperation(args) {
|
|
2
|
+
const plan = resolveOperationPlan(args.dataSource, args.operation);
|
|
3
|
+
if (!plan.ok)
|
|
4
|
+
return plan.result;
|
|
5
|
+
const adapter = args.databaseAdapters?.[plan.adapterId];
|
|
6
|
+
if (adapter === undefined) {
|
|
7
|
+
return failure(args, 'missing-adapter', `Database adapter '${plan.adapterId}' is not available.`);
|
|
8
|
+
}
|
|
9
|
+
const input = args.input ?? {};
|
|
10
|
+
switch (plan.operation) {
|
|
11
|
+
case 'list':
|
|
12
|
+
return executeList(adapter, plan, input, args);
|
|
13
|
+
case 'read':
|
|
14
|
+
return executeRead(adapter, plan, input, args);
|
|
15
|
+
case 'create':
|
|
16
|
+
return executeCreate(adapter, plan, input, args);
|
|
17
|
+
case 'update':
|
|
18
|
+
return executeUpdate(adapter, plan, input, args);
|
|
19
|
+
case 'delete':
|
|
20
|
+
return executeDelete(adapter, plan, input, args);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function resolveOperationPlan(dataSource, operation) {
|
|
24
|
+
const metadata = asRecord(operation.metadata);
|
|
25
|
+
const adapterId = resolveAdapterId(dataSource);
|
|
26
|
+
const collection = metadata?.collection;
|
|
27
|
+
const operationKind = metadata?.operation;
|
|
28
|
+
const schema = metadata?.schema;
|
|
29
|
+
if (adapterId === undefined) {
|
|
30
|
+
return invalidPlan(dataSource, operation, 'Database operation source does not reference an adapter.');
|
|
31
|
+
}
|
|
32
|
+
if (typeof collection !== 'string' || collection.trim().length === 0) {
|
|
33
|
+
return invalidPlan(dataSource, operation, 'Database operation metadata requires a collection.');
|
|
34
|
+
}
|
|
35
|
+
if (!isGeneratedCrudOperation(operationKind)) {
|
|
36
|
+
return invalidPlan(dataSource, operation, 'Database operation metadata requires a generated CRUD operation.');
|
|
37
|
+
}
|
|
38
|
+
if (schema !== undefined && schema !== null && typeof schema !== 'string') {
|
|
39
|
+
return invalidPlan(dataSource, operation, 'Database operation schema metadata must be a string or null.');
|
|
40
|
+
}
|
|
41
|
+
const metadataAdapterId = metadata?.adapterId;
|
|
42
|
+
if (metadataAdapterId !== undefined && metadataAdapterId !== adapterId) {
|
|
43
|
+
return invalidPlan(dataSource, operation, 'Database operation adapter metadata does not match its data source.');
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
ok: true,
|
|
47
|
+
adapterId,
|
|
48
|
+
collection,
|
|
49
|
+
schema: typeof schema === 'string' ? schema : undefined,
|
|
50
|
+
operation: operationKind,
|
|
51
|
+
primaryKey: resolvePrimaryKey(operation),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
async function executeList(adapter, plan, input, args) {
|
|
55
|
+
const page = resolvePage(input);
|
|
56
|
+
if (!page.ok)
|
|
57
|
+
return failure(args, 'invalid-config', page.message);
|
|
58
|
+
const result = await adapter.select({
|
|
59
|
+
table: plan.collection,
|
|
60
|
+
schema: plan.schema,
|
|
61
|
+
page: page.value,
|
|
62
|
+
});
|
|
63
|
+
return resolveDbResult(args, result, (records) => records);
|
|
64
|
+
}
|
|
65
|
+
async function executeRead(adapter, plan, input, args) {
|
|
66
|
+
const identity = resolveIdentity(plan, input);
|
|
67
|
+
if (!identity.ok)
|
|
68
|
+
return failure(args, 'invalid-config', identity.message);
|
|
69
|
+
const result = await adapter.findById({
|
|
70
|
+
table: plan.collection,
|
|
71
|
+
schema: plan.schema,
|
|
72
|
+
id: identity.value,
|
|
73
|
+
idField: plan.primaryKey,
|
|
74
|
+
});
|
|
75
|
+
return resolveDbResult(args, result, (record) => record);
|
|
76
|
+
}
|
|
77
|
+
async function executeCreate(adapter, plan, input, args) {
|
|
78
|
+
const result = await adapter.insert({
|
|
79
|
+
table: plan.collection,
|
|
80
|
+
schema: plan.schema,
|
|
81
|
+
values: { ...input },
|
|
82
|
+
});
|
|
83
|
+
return resolveDbResult(args, result, (records) => records[0] ?? null);
|
|
84
|
+
}
|
|
85
|
+
async function executeUpdate(adapter, plan, input, args) {
|
|
86
|
+
const identity = resolveIdentity(plan, input);
|
|
87
|
+
if (!identity.ok)
|
|
88
|
+
return failure(args, 'invalid-config', identity.message);
|
|
89
|
+
const values = omitKey(input, plan.primaryKey);
|
|
90
|
+
if (Object.keys(values).length === 0) {
|
|
91
|
+
return failure(args, 'invalid-config', 'Generated update operation requires at least one value to update.');
|
|
92
|
+
}
|
|
93
|
+
const result = await adapter.update({
|
|
94
|
+
table: plan.collection,
|
|
95
|
+
schema: plan.schema,
|
|
96
|
+
values,
|
|
97
|
+
filters: [createIdentityFilter(plan.primaryKey, identity.value)],
|
|
98
|
+
});
|
|
99
|
+
return resolveDbResult(args, result, (records) => records[0] ?? null);
|
|
100
|
+
}
|
|
101
|
+
async function executeDelete(adapter, plan, input, args) {
|
|
102
|
+
const identity = resolveIdentity(plan, input);
|
|
103
|
+
if (!identity.ok)
|
|
104
|
+
return failure(args, 'invalid-config', identity.message);
|
|
105
|
+
const result = await adapter.delete({
|
|
106
|
+
table: plan.collection,
|
|
107
|
+
schema: plan.schema,
|
|
108
|
+
filters: [createIdentityFilter(plan.primaryKey, identity.value)],
|
|
109
|
+
});
|
|
110
|
+
return resolveDbResult(args, result, (records) => ({ deleted: records.length > 0 }));
|
|
111
|
+
}
|
|
112
|
+
function resolveDbResult(args, result, select) {
|
|
113
|
+
if (!result.ok)
|
|
114
|
+
return failure(args, 'database-operation-failed', result.error.message);
|
|
115
|
+
const value = toBindingValue(select(result.data));
|
|
116
|
+
if (value === undefined) {
|
|
117
|
+
return failure(args, 'invalid-config', 'Database adapter returned a non-serializable binding value.');
|
|
118
|
+
}
|
|
119
|
+
return { ok: true, data: value, diagnostics: [] };
|
|
120
|
+
}
|
|
121
|
+
function resolveAdapterId(dataSource) {
|
|
122
|
+
if (dataSource.kind === 'database')
|
|
123
|
+
return dataSource.adapter.id;
|
|
124
|
+
if (dataSource.origin === 'generated')
|
|
125
|
+
return dataSource.adapter.id;
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
function resolvePrimaryKey(operation) {
|
|
129
|
+
return operation.request?.parameters?.find((parameter) => parameter.location === 'path')?.name;
|
|
130
|
+
}
|
|
131
|
+
function resolveIdentity(plan, input) {
|
|
132
|
+
if (plan.primaryKey === undefined) {
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
message: 'Generated read/update/delete operation requires primary-key metadata.',
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const value = input[plan.primaryKey];
|
|
139
|
+
return typeof value === 'string' || (typeof value === 'number' && Number.isFinite(value))
|
|
140
|
+
? { ok: true, value }
|
|
141
|
+
: {
|
|
142
|
+
ok: false,
|
|
143
|
+
message: `Generated operation requires '${plan.primaryKey}' as a string or number.`,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function resolvePage(input) {
|
|
147
|
+
const { limit, offset } = input;
|
|
148
|
+
if (!isOptionalPageNumber(limit) || !isOptionalPageNumber(offset)) {
|
|
149
|
+
return {
|
|
150
|
+
ok: false,
|
|
151
|
+
message: 'Generated list operation limit/offset must be non-negative integers.',
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (limit === undefined && offset === undefined)
|
|
155
|
+
return { ok: true, value: undefined };
|
|
156
|
+
return { ok: true, value: { limit, offset } };
|
|
157
|
+
}
|
|
158
|
+
function isOptionalPageNumber(value) {
|
|
159
|
+
return (value === undefined || (typeof value === 'number' && Number.isInteger(value) && value >= 0));
|
|
160
|
+
}
|
|
161
|
+
function createIdentityFilter(field, value) {
|
|
162
|
+
return { field: field ?? 'id', operator: 'eq', value };
|
|
163
|
+
}
|
|
164
|
+
function omitKey(input, key) {
|
|
165
|
+
const values = {};
|
|
166
|
+
for (const [field, value] of Object.entries(input)) {
|
|
167
|
+
if (field !== key)
|
|
168
|
+
values[field] = value;
|
|
169
|
+
}
|
|
170
|
+
return values;
|
|
171
|
+
}
|
|
172
|
+
function isGeneratedCrudOperation(value) {
|
|
173
|
+
return (value === 'list' ||
|
|
174
|
+
value === 'read' ||
|
|
175
|
+
value === 'create' ||
|
|
176
|
+
value === 'update' ||
|
|
177
|
+
value === 'delete');
|
|
178
|
+
}
|
|
179
|
+
function invalidPlan(dataSource, operation, message) {
|
|
180
|
+
return {
|
|
181
|
+
ok: false,
|
|
182
|
+
result: failure({ dataSource, operation }, 'invalid-config', message),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function failure(args, code, message) {
|
|
186
|
+
const diagnostic = {
|
|
187
|
+
code,
|
|
188
|
+
dataSourceId: args.dataSource.id,
|
|
189
|
+
endpointId: args.operation.endpointId,
|
|
190
|
+
operationId: args.operation.id,
|
|
191
|
+
message,
|
|
192
|
+
severity: 'error',
|
|
193
|
+
};
|
|
194
|
+
return { ok: false, diagnostics: [diagnostic] };
|
|
195
|
+
}
|
|
196
|
+
function asRecord(value) {
|
|
197
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
198
|
+
? value
|
|
199
|
+
: undefined;
|
|
200
|
+
}
|
|
201
|
+
function toBindingValue(value) {
|
|
202
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
203
|
+
return value;
|
|
204
|
+
if (typeof value === 'number')
|
|
205
|
+
return Number.isFinite(value) ? value : undefined;
|
|
206
|
+
if (Array.isArray(value)) {
|
|
207
|
+
const items = [];
|
|
208
|
+
for (const item of value) {
|
|
209
|
+
const converted = toBindingValue(item);
|
|
210
|
+
if (converted === undefined)
|
|
211
|
+
return undefined;
|
|
212
|
+
items.push(converted);
|
|
213
|
+
}
|
|
214
|
+
return items;
|
|
215
|
+
}
|
|
216
|
+
const record = asRecord(value);
|
|
217
|
+
if (record === undefined)
|
|
218
|
+
return undefined;
|
|
219
|
+
const converted = {};
|
|
220
|
+
for (const [key, item] of Object.entries(record)) {
|
|
221
|
+
const bindingValue = toBindingValue(item);
|
|
222
|
+
if (bindingValue === undefined)
|
|
223
|
+
return undefined;
|
|
224
|
+
converted[key] = bindingValue;
|
|
225
|
+
}
|
|
226
|
+
return converted;
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=runtimeDatabaseOperationExecutor.js.map
|