@astrale-os/sdk 0.5.0-beta.23 → 0.5.0-beta.25
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/dist/application/action/context.d.ts +1 -1
- package/dist/application/integration/client.d.ts +2 -0
- package/dist/application/integration/client.js +5 -3
- package/dist/application/integration/operation.d.ts +3 -0
- package/dist/application/mutation/execution/execute.d.ts +6 -4
- package/dist/application/mutation/execution/execute.js +6 -1
- package/dist/application/mutation/execution/executor.d.ts +2 -1
- package/dist/application/mutation/execution/executor.js +3 -3
- package/dist/application/query/execution/execute.d.ts +3 -7
- package/dist/application/query/execution/executor.d.ts +2 -1
- package/dist/application/query/execution/executor.js +7 -2
- package/dist/application/runtime/authoring.d.ts +1 -1
- package/dist/application/runtime/define.d.ts +7 -6
- package/dist/application/runtime/initialize.d.ts +6 -1
- package/dist/application/runtime/runtime.d.ts +2 -2
- package/dist/deployment/build/admission.d.ts +10 -2
- package/dist/deployment/build/admission.js +10 -4
- package/dist/deployment/build/compile.js +3 -2
- package/dist/deployment/build/material.js +45 -14
- package/dist/deployment/release/publication/seal.js +2 -2
- package/dist/deployment/verify/preflight/publication.js +2 -2
- package/dist/execution/invocation/dispatch/context.js +3 -3
- package/dist/execution/invocation/integration/call.d.ts +2 -1
- package/dist/execution/invocation/integration/call.js +3 -1
- package/dist/execution/invocation/integration/clients.d.ts +2 -1
- package/dist/execution/invocation/integration/clients.js +2 -2
- package/dist/execution/runtime/initialize.js +1 -1
- package/dist/execution/runtime/load.d.ts +1 -1
- package/dist/execution/runtime/load.js +3 -10
- package/dist/tooling/cli/arguments.d.ts +1 -9
- package/dist/tooling/cli/arguments.js +4 -89
- package/dist/tooling/cli/index.d.ts +1 -1
- package/dist/tooling/cli/index.js +1 -1
- package/dist/tooling/cli/log.d.ts +1 -1
- package/dist/tooling/cli/log.js +1 -1
- package/dist/tooling/cli/orchestrate.js +2 -32
- package/dist/tooling/linter/implementations/source/global.js +14 -7
- package/dist/tooling/linter/implementations/source/mutations.js +27 -40
- package/dist/tooling/linter/implementations/source/providers.js +90 -99
- package/dist/tooling/linter/policy/generated.js +2 -2
- package/package.json +6 -6
- package/dist/tooling/cli/publish.d.ts +0 -34
- package/dist/tooling/cli/publish.js +0 -270
|
@@ -54,7 +54,7 @@ type SelfOf<Callable> = Callable extends ResolvedMethod<unknown, unknown, false>
|
|
|
54
54
|
};
|
|
55
55
|
/** Exact single-step Action context derived from one resolved callable. */
|
|
56
56
|
export type ActionContext<Callable extends ResolvedCallable, DomainValue extends Domain = Domain, Definitions extends Integrations = Readonly<Record<never, never>>> = {
|
|
57
|
-
/** Exact
|
|
57
|
+
/** Exact admitted Domain retained by the Build being executed. */
|
|
58
58
|
readonly domain: DomainValue;
|
|
59
59
|
readonly input: CallableInputOf<Callable>;
|
|
60
60
|
readonly integrations: IntegrationClients<Definitions>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BoundClientSession } from '../../platform/client/session/index.js';
|
|
1
2
|
import type { IntegrationClients, Integrations } from './integration.js';
|
|
2
3
|
import type { IntegrationReplayDecision } from './operation.js';
|
|
3
4
|
import type { Providers } from './provider.js';
|
|
@@ -5,6 +6,7 @@ export interface IntegrationCallCoordinates {
|
|
|
5
6
|
readonly callId: string;
|
|
6
7
|
readonly signal: AbortSignal;
|
|
7
8
|
readonly deadline: number;
|
|
9
|
+
readonly invoke?: BoundClientSession['invoke'];
|
|
8
10
|
}
|
|
9
11
|
export interface IntegrationAttempt<Output> {
|
|
10
12
|
readonly integration: string;
|
|
@@ -78,19 +78,21 @@ function admitCoordinates(input) {
|
|
|
78
78
|
if (input === null || typeof input !== 'object' || Array.isArray(input))
|
|
79
79
|
invalidCoordinates();
|
|
80
80
|
const keys = Reflect.ownKeys(input);
|
|
81
|
-
if (keys.length !== 3 ||
|
|
82
|
-
!keys.every((key) => key === 'callId' || key === 'signal' || key === 'deadline') ||
|
|
81
|
+
if ((keys.length !== 3 && keys.length !== 4) ||
|
|
82
|
+
!keys.every((key) => key === 'callId' || key === 'signal' || key === 'deadline' || key === 'invoke') ||
|
|
83
83
|
typeof input.callId !== 'string' ||
|
|
84
84
|
input.callId.length === 0 ||
|
|
85
85
|
input.callId.trim() !== input.callId ||
|
|
86
86
|
!(input.signal instanceof AbortSignal) ||
|
|
87
|
-
!Number.isFinite(input.deadline)
|
|
87
|
+
!Number.isFinite(input.deadline) ||
|
|
88
|
+
(input.invoke !== undefined && typeof input.invoke !== 'function')) {
|
|
88
89
|
invalidCoordinates();
|
|
89
90
|
}
|
|
90
91
|
return Object.freeze({
|
|
91
92
|
callId: input.callId,
|
|
92
93
|
signal: input.signal,
|
|
93
94
|
deadline: input.deadline,
|
|
95
|
+
...(input.invoke === undefined ? {} : { invoke: input.invoke }),
|
|
94
96
|
});
|
|
95
97
|
}
|
|
96
98
|
function invalidCoordinates() {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BoundClientSession } from '../../platform/client/session/index.js';
|
|
1
2
|
declare const INTEGRATION_OPERATION: unique symbol;
|
|
2
3
|
export type IntegrationReplayDecision = {
|
|
3
4
|
readonly kind: 'safe';
|
|
@@ -17,6 +18,8 @@ export interface IntegrationExecution {
|
|
|
17
18
|
readonly signal: AbortSignal;
|
|
18
19
|
readonly deadline: number;
|
|
19
20
|
readonly idempotencyKey?: string;
|
|
21
|
+
/** Exact caller-bound invocation capability; absent for an anonymous invocation. */
|
|
22
|
+
readonly invoke?: BoundClientSession['invoke'];
|
|
20
23
|
}
|
|
21
24
|
export interface IntegrationOperation<Input = unknown, Output = unknown> {
|
|
22
25
|
readonly replay: IntegrationReplay<Input>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { GraphApi } from '../../../platform/client/index.js';
|
|
2
|
+
import type { Domain } from '../../../platform/schema/index.js';
|
|
2
3
|
import type { Mutation } from '../mutation.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
4
|
+
/** Canonical caller-scoped graph capability required by Mutation execution. */
|
|
5
|
+
export type MutationClient = Pick<GraphApi, 'mutate'>;
|
|
6
6
|
export declare function executeMutation<Input, Output>(client: MutationClient, definition: Mutation<Input, Output>, input: Input): Promise<Output>;
|
|
7
|
+
/** Private Runtime binding; public callers use executeMutation with an explicit Client. */
|
|
8
|
+
export declare function executeMutationWithExpected<Input, Output>(client: MutationClient, definition: Mutation<Input, Output>, input: Input, expected?: Domain['closure']): Promise<Output>;
|
|
@@ -3,12 +3,17 @@ import { richMutationBuilder } from '../authoring/index.js';
|
|
|
3
3
|
import { mutationFailure } from '../failure.js';
|
|
4
4
|
import { projectMutation } from './projection.js';
|
|
5
5
|
export async function executeMutation(client, definition, input) {
|
|
6
|
+
return executeMutationWithExpected(client, definition, input);
|
|
7
|
+
}
|
|
8
|
+
/** Private Runtime binding; public callers use executeMutation with an explicit Client. */
|
|
9
|
+
export async function executeMutationWithExpected(client, definition, input, expected) {
|
|
6
10
|
if (client === null || typeof client !== 'object' || typeof client.mutate !== 'function') {
|
|
7
11
|
throw new TypeError('Mutation execution requires a Client mutate capability.');
|
|
8
12
|
}
|
|
9
13
|
try {
|
|
10
14
|
const ast = MutationAST.build((builder) => definition.change(richMutationBuilder(builder), input));
|
|
11
|
-
|
|
15
|
+
const result = await client.mutate(ast, expected === undefined ? undefined : { expected });
|
|
16
|
+
return projectMutation(definition, result, input);
|
|
12
17
|
}
|
|
13
18
|
catch (cause) {
|
|
14
19
|
const expected = mutationFailure(cause);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Domain } from '../../../platform/schema/index.js';
|
|
1
2
|
import type { Mutation } from '../mutation.js';
|
|
2
3
|
import type { MutationClient } from './execute.js';
|
|
3
4
|
/** Invocation-bound executor for authored Mutation definitions. */
|
|
@@ -5,4 +6,4 @@ export interface MutationExecutor {
|
|
|
5
6
|
<Input, Output>(definition: Mutation<Input, Output>, input: Input): Promise<Output>;
|
|
6
7
|
}
|
|
7
8
|
/** Private Runtime binding; public consumers use executeMutation(client, definition, input). */
|
|
8
|
-
export declare function bindMutation(client: MutationClient): MutationExecutor;
|
|
9
|
+
export declare function bindMutation(client: MutationClient, expected: Domain['closure']): MutationExecutor;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { executeMutationWithExpected } from './execute.js';
|
|
2
2
|
/** Private Runtime binding; public consumers use executeMutation(client, definition, input). */
|
|
3
|
-
export function bindMutation(client) {
|
|
4
|
-
return (definition, input) =>
|
|
3
|
+
export function bindMutation(client, expected) {
|
|
4
|
+
return (definition, input) => executeMutationWithExpected(client, definition, input, expected);
|
|
5
5
|
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { QueryAST, QueryResultFor } from '@astrale-os/kernel-core/graph/query';
|
|
1
|
+
import type { GraphApi } from '../../../platform/client/index.js';
|
|
3
2
|
import type { CompositeQuery } from '../composite/index.js';
|
|
4
3
|
import type { QueryDefinition } from '../query.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
readonly page: QueryPageRequest;
|
|
8
|
-
}): Promise<QueryResponse<QueryResultFor<Ast>>>;
|
|
9
|
-
}
|
|
4
|
+
/** Canonical caller-scoped graph capability required by Query execution. */
|
|
5
|
+
export type QueryClient = Pick<GraphApi, 'query'>;
|
|
10
6
|
export declare function executeQuery<Input, Output>(client: QueryClient, definition: QueryDefinition<Input, Output>, input: Input): Promise<Output>;
|
|
11
7
|
export type ExecutableCompositeQuery = CompositeQuery<unknown, unknown, unknown>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Domain } from '../../../platform/schema/index.js';
|
|
1
2
|
import type { QueryDefinition } from '../query.js';
|
|
2
3
|
import type { QueryClient } from './execute.js';
|
|
3
4
|
/** Invocation-bound executor for authored Query definitions. */
|
|
@@ -5,4 +6,4 @@ export interface QueryExecutor {
|
|
|
5
6
|
<Input, Output>(definition: QueryDefinition<Input, Output>, input: Input): Promise<Output>;
|
|
6
7
|
}
|
|
7
8
|
/** Private Runtime binding; public consumers use executeQuery(client, definition, input). */
|
|
8
|
-
export declare function bindQuery(client: QueryClient): QueryExecutor;
|
|
9
|
+
export declare function bindQuery(client: QueryClient, expected: Domain['closure']): QueryExecutor;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { executeQuery } from './execute.js';
|
|
2
2
|
/** Private Runtime binding; public consumers use executeQuery(client, definition, input). */
|
|
3
|
-
export function bindQuery(client) {
|
|
4
|
-
|
|
3
|
+
export function bindQuery(client, expected) {
|
|
4
|
+
const bound = Object.freeze({
|
|
5
|
+
query(ast, options) {
|
|
6
|
+
return client.query(ast, { ...options, expected });
|
|
7
|
+
},
|
|
8
|
+
});
|
|
9
|
+
return (definition, input) => executeQuery(bound, definition, input);
|
|
5
10
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { defineRuntime } from './define.js';
|
|
2
2
|
export type { RuntimeInput } from './define.js';
|
|
3
|
-
export type { RuntimeInitialization, RuntimeInitializer } from './initialize.js';
|
|
3
|
+
export type { RuntimeInitialization, RuntimeInitializationContext, RuntimeInitializer, } from './initialize.js';
|
|
4
4
|
export type { RuntimeIntegrations } from './integrations.js';
|
|
5
5
|
export type { Runtime } from './runtime.js';
|
|
@@ -2,26 +2,27 @@ import type { schema } from '../../platform/schema/index.js';
|
|
|
2
2
|
import type { ActionDefinition } from '../action/index.js';
|
|
3
3
|
import type { Providers } from '../integration/index.js';
|
|
4
4
|
import type { WorkflowDefinition } from '../workflow/index.js';
|
|
5
|
-
import type { RuntimeInitializer } from './initialize.js';
|
|
5
|
+
import type { RuntimeInitialization, RuntimeInitializer } from './initialize.js';
|
|
6
6
|
import type { RuntimeIntegrations } from './integrations.js';
|
|
7
7
|
import type { Runtime } from './runtime.js';
|
|
8
|
-
type
|
|
8
|
+
type RuntimeInitializerValue = (...input: never[]) => RuntimeInitialization | Promise<RuntimeInitialization>;
|
|
9
|
+
type AnyRuntimeInitializer<Schema extends schema.DomainSchema> = RuntimeInitializer<never, RuntimeInitialization, Schema>;
|
|
9
10
|
type Same<Left, Right> = [Left] extends [Right] ? ([Right] extends [Left] ? true : false) : false;
|
|
10
11
|
type ActionSchema<Value> = Value extends ActionDefinition<infer Schema, infer _Address, infer _Services> ? Schema : never;
|
|
11
12
|
type WorkflowSchema<Value> = Value extends WorkflowDefinition<infer Schema, infer _Address, infer _Services> ? Schema : never;
|
|
12
13
|
type RecipeIntegrations<Value> = Value extends ActionDefinition<infer _Schema, infer _Address, infer Definitions> ? Definitions : Value extends WorkflowDefinition<infer _Schema, infer _Address, infer Definitions> ? Definitions : never;
|
|
13
14
|
type AdmitsRecipeSchema<Schema extends schema.DomainSchema, Actions extends readonly unknown[], Workflows extends readonly unknown[]> = [Actions[number] | Workflows[number]] extends [never] ? unknown : Same<ActionSchema<Actions[number]> | WorkflowSchema<Workflows[number]>, Schema> extends true ? unknown : never;
|
|
14
|
-
type InitializationOf<Initialize extends
|
|
15
|
+
type InitializationOf<Initialize extends RuntimeInitializerValue> = Awaited<ReturnType<Initialize>>;
|
|
15
16
|
type AdmitsRecipeIntegrations<Definitions extends RuntimeIntegrations, Recipe> = RecipeIntegrations<Recipe> extends infer Required extends RuntimeIntegrations ? Exclude<keyof Required, keyof Definitions> extends never ? Required extends Pick<Definitions, Extract<keyof Required, keyof Definitions>> ? true : false : false : false;
|
|
16
17
|
type AdmitsIntegrations<Definitions extends RuntimeIntegrations, Actions extends readonly unknown[], Workflows extends readonly unknown[]> = [Actions[number] | Workflows[number]] extends [never] ? unknown : false extends AdmitsRecipeIntegrations<Definitions, Actions[number] | Workflows[number]> ? never : unknown;
|
|
17
|
-
type AdmitsProviders<Integrations extends RuntimeIntegrations, Initialize extends
|
|
18
|
-
export interface RuntimeInput<Integrations extends RuntimeIntegrations, Initialize extends
|
|
18
|
+
type AdmitsProviders<Integrations extends RuntimeIntegrations, Initialize extends RuntimeInitializerValue> = Same<InitializationOf<Initialize>['providers'], Providers<Integrations>> extends true ? unknown : never;
|
|
19
|
+
export interface RuntimeInput<Integrations extends RuntimeIntegrations, Initialize extends RuntimeInitializerValue, Actions extends readonly unknown[], Workflows extends readonly unknown[]> {
|
|
19
20
|
readonly integrations: Integrations;
|
|
20
21
|
readonly initialize: Initialize;
|
|
21
22
|
readonly actions: Actions;
|
|
22
23
|
readonly workflows: Workflows;
|
|
23
24
|
}
|
|
24
25
|
/** Define one inert Runtime declaration; realization requires an exact loaded DSL Domain. */
|
|
25
|
-
export declare function defineRuntime<Schema extends schema.DomainSchema>(): <const Integrations extends RuntimeIntegrations, Initialize extends AnyRuntimeInitializer
|
|
26
|
+
export declare function defineRuntime<Schema extends schema.DomainSchema>(): <const Integrations extends RuntimeIntegrations, Initialize extends AnyRuntimeInitializer<Schema>, const Actions extends readonly unknown[], const Workflows extends readonly unknown[]>(input: RuntimeInput<Integrations, Initialize, Actions, Workflows> & AdmitsRecipeSchema<Schema, Actions, Workflows> & AdmitsIntegrations<Integrations, Actions, Workflows> & AdmitsProviders<Integrations, Initialize>) => Runtime<Schema, Integrations, Initialize, Actions, Workflows>;
|
|
26
27
|
export declare function isRuntime(input: unknown): input is Runtime;
|
|
27
28
|
export {};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import type { schema } from '../../platform/schema/index.js';
|
|
1
2
|
/** Exact values created once from one adapter environment for a realized Runtime. */
|
|
2
3
|
export interface RuntimeInitialization<ProviderValues = unknown> {
|
|
3
4
|
readonly providers: ProviderValues;
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
+
/** Exact loaded Domain available while Providers are constructed once. */
|
|
7
|
+
export interface RuntimeInitializationContext<Schema extends schema.DomainSchema> {
|
|
8
|
+
readonly domain: schema.DomainOf<Schema>;
|
|
9
|
+
}
|
|
10
|
+
export type RuntimeInitializer<Environment = unknown, Initialization extends RuntimeInitialization = RuntimeInitialization, Schema extends schema.DomainSchema = schema.DomainSchema> = (environment: Environment, context: RuntimeInitializationContext<Schema>) => Initialization | Promise<Initialization>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Domain, schema } from '../../platform/schema/index.js';
|
|
2
2
|
import type { RuntimeAction } from './actions.js';
|
|
3
|
-
import type { RuntimeInitializer } from './initialize.js';
|
|
3
|
+
import type { RuntimeInitialization, RuntimeInitializer } from './initialize.js';
|
|
4
4
|
import type { RuntimeIntegrations } from './integrations.js';
|
|
5
5
|
import type { RuntimeWorkflow } from './workflows.js';
|
|
6
6
|
export type RuntimeImplementation = RuntimeAction | RuntimeWorkflow;
|
|
7
7
|
declare const RUNTIME_SCHEMA: unique symbol;
|
|
8
8
|
/** Inert authored Runtime declaration; exact Domain association occurs during realization. */
|
|
9
|
-
export interface Runtime<Schema extends schema.DomainSchema = schema.DomainSchema, Integrations extends RuntimeIntegrations = RuntimeIntegrations, Initialize extends RuntimeInitializer<never> = RuntimeInitializer<never>, Actions extends readonly unknown[] = readonly unknown[], Workflows extends readonly unknown[] = readonly unknown[]> {
|
|
9
|
+
export interface Runtime<Schema extends schema.DomainSchema = schema.DomainSchema, Integrations extends RuntimeIntegrations = RuntimeIntegrations, Initialize extends RuntimeInitializer<never, RuntimeInitialization, Schema> = RuntimeInitializer<never, RuntimeInitialization, Schema>, Actions extends readonly unknown[] = readonly unknown[], Workflows extends readonly unknown[] = readonly unknown[]> {
|
|
10
10
|
readonly kind: 'runtime';
|
|
11
11
|
readonly integrations: Integrations;
|
|
12
12
|
readonly initialize: Initialize;
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
import type { RuntimeRegistry } from '../../application/runtime/index.js';
|
|
2
|
+
import type { Domain } from '../../platform/schema/index.js';
|
|
1
3
|
import type { Build } from './build.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
+
interface BuildEvidence {
|
|
5
|
+
readonly domain: Domain;
|
|
6
|
+
readonly registry: RuntimeRegistry;
|
|
7
|
+
}
|
|
8
|
+
/** Retain package ownership and realization evidence for one admitted Build. */
|
|
9
|
+
export declare function admitBuild<Value extends Build>(build: Value, evidence: BuildEvidence): Value;
|
|
4
10
|
export declare function isBuild(input: unknown): input is Build;
|
|
11
|
+
export declare function evidenceOf(build: Build): BuildEvidence;
|
|
12
|
+
export {};
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
const admittedBuilds = new
|
|
2
|
-
/** Retain package ownership
|
|
3
|
-
export function admitBuild(build) {
|
|
4
|
-
admittedBuilds.
|
|
1
|
+
const admittedBuilds = new WeakMap();
|
|
2
|
+
/** Retain package ownership and realization evidence for one admitted Build. */
|
|
3
|
+
export function admitBuild(build, evidence) {
|
|
4
|
+
admittedBuilds.set(build, Object.freeze({ domain: evidence.domain, registry: evidence.registry }));
|
|
5
5
|
return build;
|
|
6
6
|
}
|
|
7
7
|
export function isBuild(input) {
|
|
8
8
|
return input !== null && typeof input === 'object' && admittedBuilds.has(input);
|
|
9
9
|
}
|
|
10
|
+
export function evidenceOf(build) {
|
|
11
|
+
const evidence = admittedBuilds.get(build);
|
|
12
|
+
if (evidence === undefined)
|
|
13
|
+
throw new TypeError('Build is not admitted.');
|
|
14
|
+
return evidence;
|
|
15
|
+
}
|
|
@@ -38,7 +38,7 @@ export function compile(application) {
|
|
|
38
38
|
routes: plan,
|
|
39
39
|
...(frontend === undefined ? {} : { frontend }),
|
|
40
40
|
});
|
|
41
|
-
return admitBuild(build);
|
|
41
|
+
return admitBuild(build, { domain, registry });
|
|
42
42
|
}
|
|
43
43
|
function compileRequirements(domain, input, sourceBundle) {
|
|
44
44
|
for (const key of input?.callables ?? []) {
|
|
@@ -74,7 +74,8 @@ function requireDirectDependency(domain, key, label) {
|
|
|
74
74
|
catch {
|
|
75
75
|
throw new TypeError(`${label} requirement is invalid.`);
|
|
76
76
|
}
|
|
77
|
-
if (origin === domain.origin ||
|
|
77
|
+
if (origin === domain.origin ||
|
|
78
|
+
!Object.values(domain.dependencies).some((dependency) => dependency.origin === origin)) {
|
|
78
79
|
throw new TypeError(`${label} requirement must target an exact direct dependency.`);
|
|
79
80
|
}
|
|
80
81
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as bundle from '@astrale-os/kernel-dsl/v1/bundle/transport';
|
|
2
2
|
import { load as loadCompiledSchema } from '@astrale-os/kernel-dsl/v1/compiled/loader';
|
|
3
3
|
import { revision } from '@astrale-os/kernel-dsl/v1/schema/revision';
|
|
4
|
+
import { equal } from '@astrale-os/kernel-dsl/value';
|
|
4
5
|
import * as artifact from '@astrale-os/kernel-protocol/artifact';
|
|
5
6
|
import { BUNDLE_MEDIA_TYPE } from '@astrale-os/kernel-protocol/publication/bundle';
|
|
6
7
|
import { admitRequirements, validateRequirements, } from '@astrale-os/kernel-protocol/publication/requirements';
|
|
8
|
+
import * as routes from '@astrale-os/kernel-protocol/routes';
|
|
7
9
|
import { admitRuntimeRegistry, isRuntime } from '../../application/runtime/index.js';
|
|
8
10
|
import { admitBuild, isBuild } from './admission.js';
|
|
9
11
|
/** Detach the provider-neutral, runtime-free material embedded into generated execution code. */
|
|
@@ -50,6 +52,7 @@ export function restoreBuild(input, runtime) {
|
|
|
50
52
|
const identified = artifact.identify(bytes, BUNDLE_MEDIA_TYPE);
|
|
51
53
|
if (identified.digest !== input.schema.bundle.ref.digest ||
|
|
52
54
|
identified.mediaType !== input.schema.bundle.ref.mediaType ||
|
|
55
|
+
identified.size !== input.schema.bundle.ref.size ||
|
|
53
56
|
decoded.root.origin !== input.schema.compiled.root.origin ||
|
|
54
57
|
revision(decoded.root) !== input.schema.compiled.root.revision) {
|
|
55
58
|
invalid();
|
|
@@ -62,32 +65,60 @@ export function restoreBuild(input, runtime) {
|
|
|
62
65
|
}
|
|
63
66
|
const requirements = admitRequirements(input.requirements);
|
|
64
67
|
validateRequirements(decoded.root, decoded.closure, requirements);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
68
|
+
const plan = admitRoutePlan(input.routes, domain);
|
|
69
|
+
const compiled = deepFreeze(input.schema.compiled);
|
|
70
|
+
const bundleRef = deepFreeze(input.schema.bundle.ref);
|
|
71
|
+
const frontend = input.frontend === undefined ? undefined : deepFreeze(input.frontend);
|
|
70
72
|
const detached = new Uint8Array(bytes);
|
|
71
73
|
const build = Object.freeze({
|
|
72
74
|
kind: 'build',
|
|
73
75
|
schema: Object.freeze({
|
|
74
|
-
compiled
|
|
76
|
+
compiled,
|
|
75
77
|
bundle: Object.freeze({
|
|
76
|
-
ref:
|
|
78
|
+
ref: bundleRef,
|
|
77
79
|
bytes: () => new Uint8Array(detached),
|
|
78
80
|
}),
|
|
79
81
|
}),
|
|
80
82
|
runtime,
|
|
81
83
|
callables: Object.freeze([...input.callables]),
|
|
82
84
|
requirements,
|
|
83
|
-
routes:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
routes: plan,
|
|
86
|
+
...(frontend === undefined ? {} : { frontend }),
|
|
87
|
+
});
|
|
88
|
+
return admitBuild(build, { domain, registry });
|
|
89
|
+
}
|
|
90
|
+
function admitRoutePlan(input, domain) {
|
|
91
|
+
if (input.origin !== domain.origin ||
|
|
92
|
+
input.revision !== domain.revision ||
|
|
93
|
+
!Array.isArray(input.entries)) {
|
|
94
|
+
invalid();
|
|
95
|
+
}
|
|
96
|
+
const declarations = input.entries.map((entry) => {
|
|
97
|
+
if (entry === null || typeof entry !== 'object' || Array.isArray(entry))
|
|
98
|
+
invalid();
|
|
99
|
+
const { target, auth: _auth, output: _output, default: isDefault, ...declaration } = entry;
|
|
100
|
+
return {
|
|
101
|
+
...declaration,
|
|
102
|
+
...(isDefault ? { default: true } : {}),
|
|
103
|
+
...(target?.kind === 'method' && target.dispatch === 'instance'
|
|
104
|
+
? { receiver: target.receiver }
|
|
105
|
+
: {}),
|
|
106
|
+
};
|
|
89
107
|
});
|
|
90
|
-
|
|
108
|
+
const admitted = routes.compile({ domain, routes: declarations });
|
|
109
|
+
if (!equal(admitted, input))
|
|
110
|
+
invalid();
|
|
111
|
+
return admitted;
|
|
112
|
+
}
|
|
113
|
+
function deepFreeze(input, seen = new WeakSet()) {
|
|
114
|
+
if (input !== null && typeof input === 'object' && !seen.has(input)) {
|
|
115
|
+
seen.add(input);
|
|
116
|
+
for (const value of Object.values(input))
|
|
117
|
+
deepFreeze(value, seen);
|
|
118
|
+
if (!Object.isFrozen(input))
|
|
119
|
+
Object.freeze(input);
|
|
120
|
+
}
|
|
121
|
+
return input;
|
|
91
122
|
}
|
|
92
123
|
function invalid() {
|
|
93
124
|
throw new TypeError('Generated Build material is invalid.');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { load as loadCompiledSchema } from '@astrale-os/kernel-dsl/v1/compiled/loader';
|
|
2
1
|
import * as publication from '@astrale-os/kernel-protocol/publication';
|
|
3
2
|
import * as protocolRoutes from '@astrale-os/kernel-protocol/routes';
|
|
3
|
+
import { evidenceOf } from '../../build/admission.js';
|
|
4
4
|
import { callables } from './callables.js';
|
|
5
5
|
import { manifest } from './manifest.js';
|
|
6
6
|
import { requirements } from './requirements.js';
|
|
@@ -32,7 +32,7 @@ export function seal(build, addressing) {
|
|
|
32
32
|
delivery: publication.placeDelivery({ path: DELIVERY_PATH, authentication: { kind: 'public' } }, addressing.issuer, new URL(BUNDLE_PATH, addressing.issuer).href),
|
|
33
33
|
routes: routes(build, addressing),
|
|
34
34
|
});
|
|
35
|
-
const domain =
|
|
35
|
+
const { domain } = evidenceOf(build);
|
|
36
36
|
return Object.freeze({
|
|
37
37
|
publication: sealed,
|
|
38
38
|
routes: protocolRoutes.bind(build.routes, sealed, domain),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { load as loadCompiledSchema } from '@astrale-os/kernel-dsl/v1/compiled/loader';
|
|
2
1
|
import { publication as protocolPublication, routes } from '@astrale-os/kernel-protocol';
|
|
2
|
+
import { evidenceOf } from '../../build/admission.js';
|
|
3
3
|
import { assemble } from '../../release/index.js';
|
|
4
4
|
/** Verify locally assemblable Publication evidence before any provider mutation. */
|
|
5
5
|
export function publication(artifact) {
|
|
@@ -8,7 +8,7 @@ export function publication(artifact) {
|
|
|
8
8
|
const release = assemble(artifact.build, artifact.addressing.addressing);
|
|
9
9
|
const admitted = protocolPublication.accept(release.publication);
|
|
10
10
|
protocolPublication.verifyBundleBytes(admitted, artifact.build.schema.bundle.bytes());
|
|
11
|
-
const domain =
|
|
11
|
+
const { domain } = evidenceOf(artifact.build);
|
|
12
12
|
routes.verifyTable(release.routes, admitted, domain);
|
|
13
13
|
return release;
|
|
14
14
|
}
|
|
@@ -21,10 +21,10 @@ export function context(request, runtime, authentication, self) {
|
|
|
21
21
|
...(client === null
|
|
22
22
|
? {}
|
|
23
23
|
: {
|
|
24
|
-
query: bindQuery(client),
|
|
25
|
-
mutate: bindMutation(client),
|
|
24
|
+
query: bindQuery(client, runtime.loaded.domain.closure),
|
|
25
|
+
mutate: bindMutation(client, runtime.loaded.domain.closure),
|
|
26
26
|
}),
|
|
27
|
-
integrations: clients(runtime, request.context),
|
|
27
|
+
integrations: clients(runtime, request.context, client),
|
|
28
28
|
execution,
|
|
29
29
|
...(self === undefined ? {} : { self }),
|
|
30
30
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { InvocationContext } from '@astrale-os/kernel-server';
|
|
2
2
|
import type { IntegrationInvocationOwner } from '../../../application/integration/index.js';
|
|
3
|
+
import type { BoundClientSession } from '../../../platform/client/session/index.js';
|
|
3
4
|
/** One invocation-owned logical Integration call sequence. */
|
|
4
|
-
export declare function calls(context: InvocationContext): IntegrationInvocationOwner;
|
|
5
|
+
export declare function calls(context: InvocationContext, client?: BoundClientSession | null): IntegrationInvocationOwner;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { active } from '../lifecycle/index.js';
|
|
2
2
|
/** One invocation-owned logical Integration call sequence. */
|
|
3
|
-
export function calls(context) {
|
|
3
|
+
export function calls(context, client = null) {
|
|
4
4
|
const prefix = context.idempotencyKey ?? context.invocation;
|
|
5
|
+
const invoke = client?.invoke.bind(client);
|
|
5
6
|
let sequence = 0;
|
|
6
7
|
return Object.freeze({
|
|
7
8
|
invoke(call) {
|
|
@@ -11,6 +12,7 @@ export function calls(context) {
|
|
|
11
12
|
callId: `${prefix}:${sequence}`,
|
|
12
13
|
signal: context.execution.signal,
|
|
13
14
|
deadline: context.execution.deadline,
|
|
15
|
+
...(invoke === undefined ? {} : { invoke }),
|
|
14
16
|
});
|
|
15
17
|
},
|
|
16
18
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { InvocationContext } from '@astrale-os/kernel-server';
|
|
2
2
|
import type { IntegrationClients, Integrations } from '../../../application/integration/index.js';
|
|
3
|
+
import type { BoundClientSession } from '../../../platform/client/session/index.js';
|
|
3
4
|
import type { InitializedRuntime } from '../../runtime/index.js';
|
|
4
|
-
export declare function clients(runtime: InitializedRuntime, context: InvocationContext): IntegrationClients<Integrations>;
|
|
5
|
+
export declare function clients(runtime: InitializedRuntime, context: InvocationContext, client: BoundClientSession | null): IntegrationClients<Integrations>;
|
|
@@ -7,7 +7,7 @@ export async function initialize(loaded, environment) {
|
|
|
7
7
|
throw new TypeError('Runtime initialization requires an admitted loaded Runtime.');
|
|
8
8
|
}
|
|
9
9
|
const runtime = loaded.release.build.runtime;
|
|
10
|
-
const initialization = providers(await runtime.initialize(environment));
|
|
10
|
+
const initialization = providers(await runtime.initialize(environment, Object.freeze({ domain: loaded.domain })));
|
|
11
11
|
const clients = integrations(runtime.integrations, initialization.providers);
|
|
12
12
|
return Object.freeze({ loaded, initialization, clients });
|
|
13
13
|
}
|
|
@@ -7,5 +7,5 @@ export interface LoadedRuntime<BuildValue extends Build = Build> {
|
|
|
7
7
|
readonly domain: Domain;
|
|
8
8
|
readonly registry: RuntimeRegistry;
|
|
9
9
|
}
|
|
10
|
-
/** Load
|
|
10
|
+
/** Load one execution Runtime from the exact evidence retained by its admitted Build. */
|
|
11
11
|
export declare function load<const BuildValue extends Build>(release: Release<BuildValue>): LoadedRuntime<BuildValue>;
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { admitRuntimeRegistry } from '../../application/runtime/index.js';
|
|
1
|
+
import { evidenceOf } from '../../deployment/build/admission.js';
|
|
3
2
|
import { isRelease } from '../../deployment/release/admission.js';
|
|
4
3
|
import { capture } from './admission.js';
|
|
5
|
-
/** Load
|
|
4
|
+
/** Load one execution Runtime from the exact evidence retained by its admitted Build. */
|
|
6
5
|
export function load(release) {
|
|
7
6
|
if (!isRelease(release))
|
|
8
7
|
throw new TypeError('Runtime loading requires an admitted Release.');
|
|
9
|
-
const domain =
|
|
10
|
-
const registry = admitRuntimeRegistry(domain, release.build.runtime);
|
|
11
|
-
const actual = registry.implementations.map(({ callable }) => callable.key).sort();
|
|
12
|
-
if (actual.length !== release.build.callables.length ||
|
|
13
|
-
actual.some((key, index) => key !== release.build.callables[index])) {
|
|
14
|
-
throw new TypeError('Runtime registry differs from its compiled Build callable set.');
|
|
15
|
-
}
|
|
8
|
+
const { domain, registry } = evidenceOf(release.build);
|
|
16
9
|
return capture(Object.freeze({ release, domain, registry }));
|
|
17
10
|
}
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import type { LintReportFormat } from '../linter/index.js';
|
|
2
2
|
export interface ParsedArgs {
|
|
3
|
-
readonly command: 'dev' | 'build' | 'deploy' | '
|
|
3
|
+
readonly command: 'dev' | 'build' | 'deploy' | 'lint' | 'package';
|
|
4
4
|
readonly env: string;
|
|
5
5
|
readonly watch: boolean;
|
|
6
6
|
readonly fix?: boolean;
|
|
7
7
|
readonly format?: LintReportFormat;
|
|
8
|
-
readonly dryRun?: boolean;
|
|
9
|
-
readonly schemaOnly?: boolean;
|
|
10
|
-
readonly otp?: string;
|
|
11
|
-
readonly skipSchema?: boolean;
|
|
12
8
|
readonly port?: number;
|
|
13
9
|
readonly host?: string;
|
|
14
|
-
readonly publish?: boolean;
|
|
15
|
-
readonly name?: string;
|
|
16
|
-
readonly installByDefault?: boolean;
|
|
17
|
-
readonly publicUrl?: string;
|
|
18
10
|
}
|
|
19
11
|
/** Parse the frozen `astrale-domain` command grammar without performing effects. */
|
|
20
12
|
export declare function parseArgs(argv: readonly string[]): ParsedArgs;
|