@astrale-os/sdk 0.5.0-beta.24 → 0.5.0-beta.26
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/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/compile.js +2 -1
- 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/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
|
@@ -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;
|
|
@@ -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
|
}
|
|
@@ -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
|
}
|
|
@@ -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;
|
|
@@ -3,16 +3,8 @@ export function parseArgs(argv) {
|
|
|
3
3
|
const [command, ...rest] = argv;
|
|
4
4
|
const watch = rest.includes('--watch');
|
|
5
5
|
const fix = rest.includes('--fix');
|
|
6
|
-
const publish = rest.includes('--publish');
|
|
7
|
-
const installByDefault = rest.includes('--install-by-default');
|
|
8
|
-
const dryRun = rest.includes('--dry-run');
|
|
9
|
-
const schemaOnly = rest.includes('--schema');
|
|
10
|
-
const skipSchema = rest.includes('--skip-schema');
|
|
11
6
|
let port;
|
|
12
7
|
let host;
|
|
13
|
-
let name;
|
|
14
|
-
let publicUrl;
|
|
15
|
-
let otp;
|
|
16
8
|
let format;
|
|
17
9
|
let environment;
|
|
18
10
|
const cleaned = [];
|
|
@@ -37,24 +29,6 @@ export function parseArgs(argv) {
|
|
|
37
29
|
else if (argument.startsWith('--host=')) {
|
|
38
30
|
host = normalizeHost(argument.slice('--host='.length));
|
|
39
31
|
}
|
|
40
|
-
else if (argument === '--name') {
|
|
41
|
-
name = requiredValue('--name', rest[++index]);
|
|
42
|
-
}
|
|
43
|
-
else if (argument.startsWith('--name=')) {
|
|
44
|
-
name = requiredValue('--name', argument.slice('--name='.length));
|
|
45
|
-
}
|
|
46
|
-
else if (argument === '--public-url') {
|
|
47
|
-
publicUrl = requiredValue('--public-url', rest[++index]);
|
|
48
|
-
}
|
|
49
|
-
else if (argument.startsWith('--public-url=')) {
|
|
50
|
-
publicUrl = requiredValue('--public-url', argument.slice('--public-url='.length));
|
|
51
|
-
}
|
|
52
|
-
else if (argument === '--otp') {
|
|
53
|
-
otp = requiredValue('--otp', rest[++index]);
|
|
54
|
-
}
|
|
55
|
-
else if (argument.startsWith('--otp=')) {
|
|
56
|
-
otp = requiredValue('--otp', argument.slice('--otp='.length));
|
|
57
|
-
}
|
|
58
32
|
else if (argument === '--format') {
|
|
59
33
|
format = lintFormat(rest[++index]);
|
|
60
34
|
}
|
|
@@ -67,13 +41,7 @@ export function parseArgs(argv) {
|
|
|
67
41
|
else if (argument.startsWith('--environment=')) {
|
|
68
42
|
environment = requiredValue('--environment', argument.slice('--environment='.length));
|
|
69
43
|
}
|
|
70
|
-
else if (argument === '--watch' ||
|
|
71
|
-
argument === '--fix' ||
|
|
72
|
-
argument === '--publish' ||
|
|
73
|
-
argument === '--install-by-default' ||
|
|
74
|
-
argument === '--dry-run' ||
|
|
75
|
-
argument === '--schema' ||
|
|
76
|
-
argument === '--skip-schema') {
|
|
44
|
+
else if (argument === '--watch' || argument === '--fix') {
|
|
77
45
|
continue;
|
|
78
46
|
}
|
|
79
47
|
else if (argument.startsWith('-')) {
|
|
@@ -83,53 +51,24 @@ export function parseArgs(argv) {
|
|
|
83
51
|
cleaned.push(argument);
|
|
84
52
|
}
|
|
85
53
|
}
|
|
86
|
-
if (dryRun && command !== 'publish') {
|
|
87
|
-
throw new Error('`--dry-run` is only valid for `publish`.');
|
|
88
|
-
}
|
|
89
|
-
if (otp !== undefined && !['publish', 'deploy', 'prod'].includes(command ?? '')) {
|
|
90
|
-
throw new Error('`--otp` is only valid for the publish / deploy commands.');
|
|
91
|
-
}
|
|
92
|
-
if (schemaOnly && command !== 'publish') {
|
|
93
|
-
throw new Error('`--schema` is only valid for `publish`.');
|
|
94
|
-
}
|
|
95
|
-
if (schemaOnly && skipSchema) {
|
|
96
|
-
throw new Error('`--schema` (schema only) and `--skip-schema` (catalog only) are mutually exclusive.');
|
|
97
|
-
}
|
|
98
54
|
if (fix && command !== 'lint')
|
|
99
55
|
throw new Error('`--fix` is only valid for `lint`.');
|
|
100
56
|
if (format !== undefined && command !== 'lint') {
|
|
101
57
|
throw new Error('`--format` is only valid for `lint`.');
|
|
102
58
|
}
|
|
103
|
-
if (watch && !['dev', 'deploy'
|
|
59
|
+
if (watch && !['dev', 'deploy'].includes(command ?? '')) {
|
|
104
60
|
throw new Error('`--watch` is only valid for the dev / deploy commands.');
|
|
105
61
|
}
|
|
106
62
|
if ((port !== undefined || host !== undefined) && command !== 'dev') {
|
|
107
63
|
throw new Error('`--port` and `--host` are only valid for `dev`.');
|
|
108
64
|
}
|
|
109
|
-
if (
|
|
110
|
-
throw new Error('`--
|
|
111
|
-
}
|
|
112
|
-
if (publicUrl !== undefined && command !== 'publish') {
|
|
113
|
-
throw new Error('`--public-url` is only valid for `publish`.');
|
|
114
|
-
}
|
|
115
|
-
if (environment !== undefined && !['dev', 'deploy', 'publish'].includes(command ?? '')) {
|
|
116
|
-
throw new Error('`--environment` is only valid for dev, deploy, or publish.');
|
|
117
|
-
}
|
|
118
|
-
if ((name !== undefined || installByDefault || skipSchema || otp !== undefined) &&
|
|
119
|
-
command !== 'publish' &&
|
|
120
|
-
!(['deploy', 'prod'].includes(command ?? '') && publish)) {
|
|
121
|
-
throw new Error('Publish options require `publish` or a deploy command with `--publish`.');
|
|
65
|
+
if (environment !== undefined && !['dev', 'deploy'].includes(command ?? '')) {
|
|
66
|
+
throw new Error('`--environment` is only valid for dev or deploy.');
|
|
122
67
|
}
|
|
123
68
|
const positionals = cleaned.filter((argument) => !argument.startsWith('-'));
|
|
124
69
|
if (environment !== undefined && positionals.length > 0) {
|
|
125
70
|
throw new Error('Choose either a positional environment or `--environment`, not both.');
|
|
126
71
|
}
|
|
127
|
-
const publication = {
|
|
128
|
-
...(name !== undefined ? { name } : {}),
|
|
129
|
-
...(installByDefault ? { installByDefault } : {}),
|
|
130
|
-
...(otp !== undefined ? { otp } : {}),
|
|
131
|
-
...(skipSchema ? { skipSchema } : {}),
|
|
132
|
-
};
|
|
133
72
|
switch (command) {
|
|
134
73
|
case 'dev':
|
|
135
74
|
if (positionals.length > 1)
|
|
@@ -141,16 +80,6 @@ export function parseArgs(argv) {
|
|
|
141
80
|
...(port !== undefined ? { port } : {}),
|
|
142
81
|
...(host !== undefined ? { host } : {}),
|
|
143
82
|
};
|
|
144
|
-
case 'prod':
|
|
145
|
-
if (positionals.length > 0)
|
|
146
|
-
throw new Error('`prod` does not accept an environment.');
|
|
147
|
-
return {
|
|
148
|
-
command: 'deploy',
|
|
149
|
-
env: 'prod',
|
|
150
|
-
watch,
|
|
151
|
-
...(publish ? { publish } : {}),
|
|
152
|
-
...publication,
|
|
153
|
-
};
|
|
154
83
|
case 'deploy': {
|
|
155
84
|
if (positionals.length > 1)
|
|
156
85
|
throw new Error('`deploy` accepts exactly one environment.');
|
|
@@ -161,22 +90,8 @@ export function parseArgs(argv) {
|
|
|
161
90
|
command: 'deploy',
|
|
162
91
|
env,
|
|
163
92
|
watch,
|
|
164
|
-
...(publish ? { publish } : {}),
|
|
165
|
-
...publication,
|
|
166
93
|
};
|
|
167
94
|
}
|
|
168
|
-
case 'publish':
|
|
169
|
-
if (positionals.length > 1)
|
|
170
|
-
throw new Error('`publish` accepts at most one environment.');
|
|
171
|
-
return {
|
|
172
|
-
command: 'publish',
|
|
173
|
-
env: environment ?? positionals[0] ?? 'prod',
|
|
174
|
-
watch: false,
|
|
175
|
-
...publication,
|
|
176
|
-
...(publicUrl !== undefined ? { publicUrl } : {}),
|
|
177
|
-
...(dryRun ? { dryRun } : {}),
|
|
178
|
-
...(schemaOnly ? { schemaOnly } : {}),
|
|
179
|
-
};
|
|
180
95
|
case 'build':
|
|
181
96
|
if (positionals.length > 0)
|
|
182
97
|
throw new Error('`build` does not accept positional arguments.');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@astrale-os/sdk/cli` — the `astrale-domain` CLI
|
|
3
|
-
* (dev | build | deploy |
|
|
3
|
+
* (dev | build | deploy | lint | package) and its explicit dotenv boundary.
|
|
4
4
|
*
|
|
5
5
|
* Node-only: the CLI imports `node:fs`/`node:module`/`node:url` and runs under
|
|
6
6
|
* Bun (it imports the project's `astrale.config.ts` directly). This subpath is
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@astrale-os/sdk/cli` — the `astrale-domain` CLI
|
|
3
|
-
* (dev | build | deploy |
|
|
3
|
+
* (dev | build | deploy | lint | package) and its explicit dotenv boundary.
|
|
4
4
|
*
|
|
5
5
|
* Node-only: the CLI imports `node:fs`/`node:module`/`node:url` and runs under
|
|
6
6
|
* Bun (it imports the project's `astrale.config.ts` directly). This subpath is
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** CLI output helpers
|
|
1
|
+
/** CLI output helpers and ANSI colours for the one project command owner. */
|
|
2
2
|
export declare const GREEN = "\u001B[32m";
|
|
3
3
|
export declare const DIM = "\u001B[2m";
|
|
4
4
|
export declare const BOLD = "\u001B[1m";
|
package/dist/tooling/cli/log.js
CHANGED
|
@@ -7,7 +7,6 @@ import { parseArgs } from './arguments.js';
|
|
|
7
7
|
import { BunRequiredError } from './bun.js';
|
|
8
8
|
import { loadDeclaredSecrets } from './dotenv.js';
|
|
9
9
|
import { error, info } from './log.js';
|
|
10
|
-
import { publishSchema, runRelease, runReleaseAfterDeploy } from './publish.js';
|
|
11
10
|
const CONFIG_NAMES = ['astrale.config.ts', 'astrale.config.js', 'astrale.config.mjs'];
|
|
12
11
|
export async function run(argv) {
|
|
13
12
|
if (argv.includes('--help') || argv.includes('-h')) {
|
|
@@ -29,13 +28,6 @@ export async function run(argv) {
|
|
|
29
28
|
info(`Packaged ${result.declarations} public declarations (${result.replacements} references normalized).`);
|
|
30
29
|
return 0;
|
|
31
30
|
}
|
|
32
|
-
if (parsed.command === 'publish' && parsed.schemaOnly) {
|
|
33
|
-
return publishSchema({
|
|
34
|
-
projectDir: process.cwd(),
|
|
35
|
-
dryRun: parsed.dryRun ?? false,
|
|
36
|
-
...(parsed.otp === undefined ? {} : { otp: parsed.otp }),
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
31
|
if (!process.versions.bun) {
|
|
40
32
|
throw new BunRequiredError();
|
|
41
33
|
}
|
|
@@ -46,18 +38,6 @@ export async function run(argv) {
|
|
|
46
38
|
return 1;
|
|
47
39
|
}
|
|
48
40
|
const deployment = await loadDeployment(configPath);
|
|
49
|
-
if (parsed.command === 'publish') {
|
|
50
|
-
return runRelease({
|
|
51
|
-
projectDir,
|
|
52
|
-
origin: deployment.application.schema.origin,
|
|
53
|
-
skipSchema: parsed.skipSchema ?? false,
|
|
54
|
-
dryRun: parsed.dryRun ?? false,
|
|
55
|
-
...(parsed.name === undefined ? {} : { name: parsed.name }),
|
|
56
|
-
...(parsed.publicUrl === undefined ? {} : { publicUrl: parsed.publicUrl }),
|
|
57
|
-
...(parsed.otp === undefined ? {} : { otp: parsed.otp }),
|
|
58
|
-
...(parsed.installByDefault ? { installByDefault: true } : {}),
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
41
|
const adapter = deployment.adapter;
|
|
62
42
|
const build = compile(deployment.application);
|
|
63
43
|
const resolved = await resolveRuntime(deployment.entrypoint, (path) => importModule(resolve(dirname(configPath), path)));
|
|
@@ -89,17 +69,7 @@ export async function run(argv) {
|
|
|
89
69
|
return 1;
|
|
90
70
|
}
|
|
91
71
|
info(`Ready: ${result.release.addressing.issuer}`);
|
|
92
|
-
|
|
93
|
-
return 0;
|
|
94
|
-
return runReleaseAfterDeploy({
|
|
95
|
-
projectDir,
|
|
96
|
-
origin: result.release.publication.origin,
|
|
97
|
-
deployedUrl: result.release.addressing.issuer,
|
|
98
|
-
skipSchema: parsed.skipSchema ?? false,
|
|
99
|
-
...(parsed.name === undefined ? {} : { name: parsed.name }),
|
|
100
|
-
...(parsed.otp === undefined ? {} : { otp: parsed.otp }),
|
|
101
|
-
...(parsed.installByDefault ? { installByDefault: true } : {}),
|
|
102
|
-
});
|
|
72
|
+
return 0;
|
|
103
73
|
}
|
|
104
74
|
async function watch(adapter, parameters, artifact, secrets, parsed, projectDir) {
|
|
105
75
|
const handle = await adapter.watch(parameters, {
|
|
@@ -202,5 +172,5 @@ function signals() {
|
|
|
202
172
|
function usage(message) {
|
|
203
173
|
if (message !== undefined)
|
|
204
174
|
error(message);
|
|
205
|
-
process.stderr.write('Usage: astrale-domain <dev|build|deploy|
|
|
175
|
+
process.stderr.write('Usage: astrale-domain <dev|build|deploy|lint|package> [environment]\n');
|
|
206
176
|
}
|
|
@@ -571,21 +571,28 @@ export const globalRules = [
|
|
|
571
571
|
const dependencies = propertyExpression(object, 'dependencies');
|
|
572
572
|
if (!dependencies)
|
|
573
573
|
continue;
|
|
574
|
-
if (!ts.
|
|
575
|
-
evidence.push(ambiguity(file, dependencies, 'Schema dependencies are not a static
|
|
574
|
+
if (!ts.isObjectLiteralExpression(dependencies)) {
|
|
575
|
+
evidence.push(ambiguity(file, dependencies, 'Schema dependencies are not a static object.'));
|
|
576
576
|
continue;
|
|
577
577
|
}
|
|
578
|
-
for (const
|
|
578
|
+
for (const property of dependencies.properties) {
|
|
579
|
+
const element = ts.isPropertyAssignment(property)
|
|
580
|
+
? property.initializer
|
|
581
|
+
: ts.isShorthandPropertyAssignment(property)
|
|
582
|
+
? property.name
|
|
583
|
+
: undefined;
|
|
584
|
+
if (element === undefined) {
|
|
585
|
+
evidence.push(ambiguity(file, property, 'Schema dependency is not one statically aliased Domain facade.'));
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
579
588
|
const symbol = importedSymbol(file, unwrap(element));
|
|
580
|
-
if (
|
|
581
|
-
symbol?.module === '@astrale-os/sdk/schema/kernel') &&
|
|
582
|
-
symbol.name === 'KernelSchema') {
|
|
589
|
+
if (symbol?.module === '@astrale-os/sdk/schema' && symbol.name === 'KernelSchema') {
|
|
583
590
|
continue;
|
|
584
591
|
}
|
|
585
592
|
if (symbol && isForeignDomain(symbol.module))
|
|
586
593
|
dependencyPackages.add(packageRoot(symbol.module));
|
|
587
594
|
else
|
|
588
|
-
evidence.push(ambiguity(file,
|
|
595
|
+
evidence.push(ambiguity(file, property, 'Schema dependency cannot be mapped to one foreign Domain facade.'));
|
|
589
596
|
}
|
|
590
597
|
}
|
|
591
598
|
}
|