@astrale-os/sdk 0.6.0-beta.10 → 0.6.0-beta.11
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/README.md +54 -8
- package/dist/application/define.d.ts +5 -5
- package/dist/application/define.js +13 -13
- package/dist/application/domain.d.ts +28 -0
- package/dist/application/index.d.ts +3 -3
- package/dist/application/index.js +1 -1
- package/dist/application/routes/admission.d.ts +2 -2
- package/dist/application/routes/admission.js +1 -1
- package/dist/application/routes/route.d.ts +2 -2
- package/dist/deployment/adapter/adapter.d.ts +59 -10
- package/dist/deployment/adapter/bundle/bundle.d.ts +36 -0
- package/dist/deployment/adapter/bundle/file.d.ts +10 -0
- package/dist/deployment/adapter/bundle/index.d.ts +2 -0
- package/dist/deployment/adapter/define.d.ts +25 -3
- package/dist/deployment/adapter/define.js +101 -24
- package/dist/deployment/adapter/index.d.ts +5 -3
- package/dist/deployment/adapter/legacy/adapter.d.ts +50 -0
- package/dist/deployment/adapter/{deploy → legacy/deploy}/context.d.ts +6 -0
- package/dist/deployment/adapter/legacy/deploy/index.d.ts +2 -0
- package/dist/deployment/adapter/legacy/deploy/result.d.ts +90 -0
- package/dist/deployment/adapter/legacy/deploy/result.js +1 -0
- package/dist/deployment/adapter/legacy/index.d.ts +24 -0
- package/dist/deployment/adapter/legacy/index.js +1 -0
- package/dist/deployment/adapter/legacy/prepare/artifact.d.ts +43 -0
- package/dist/deployment/adapter/legacy/prepare/artifact.js +1 -0
- package/dist/deployment/adapter/legacy/prepare/context.d.ts +36 -0
- package/dist/deployment/adapter/legacy/prepare/context.js +1 -0
- package/dist/deployment/adapter/legacy/prepare/index.d.ts +2 -0
- package/dist/deployment/adapter/legacy/prepare/index.js +1 -0
- package/dist/deployment/adapter/release/context.d.ts +75 -0
- package/dist/deployment/adapter/release/context.js +1 -0
- package/dist/deployment/adapter/release/index.d.ts +2 -0
- package/dist/deployment/adapter/release/index.js +1 -0
- package/dist/deployment/adapter/release/result.d.ts +56 -0
- package/dist/deployment/adapter/release/result.js +1 -0
- package/dist/deployment/address/configuration.d.ts +83 -0
- package/dist/deployment/address/configuration.js +262 -0
- package/dist/deployment/address/fingerprint.d.ts +5 -0
- package/dist/deployment/address/fingerprint.js +27 -0
- package/dist/deployment/address/index.d.ts +5 -0
- package/dist/deployment/address/index.js +4 -0
- package/dist/deployment/address/label.d.ts +42 -0
- package/dist/deployment/address/label.js +80 -0
- package/dist/deployment/address/line.d.ts +29 -0
- package/dist/deployment/address/line.js +53 -0
- package/dist/deployment/address/record.d.ts +52 -0
- package/dist/deployment/address/record.js +104 -0
- package/dist/deployment/address/summary.d.ts +26 -0
- package/dist/deployment/address/summary.js +1 -0
- package/dist/deployment/address/vectors.d.ts +60 -0
- package/dist/deployment/address/vectors.js +517 -0
- package/dist/deployment/build/build.d.ts +2 -2
- package/dist/deployment/build/compile.d.ts +4 -4
- package/dist/deployment/build/compile.js +17 -17
- package/dist/deployment/build/index.d.ts +1 -0
- package/dist/deployment/build/index.js +1 -0
- package/dist/deployment/build/manifest.d.ts +54 -0
- package/dist/deployment/build/manifest.js +108 -0
- package/dist/deployment/build/material.js +2 -2
- package/dist/deployment/build/schema.d.ts +2 -2
- package/dist/deployment/deploy.d.ts +10 -10
- package/dist/deployment/deploy.js +3 -3
- package/dist/deployment/deployment.d.ts +9 -4
- package/dist/deployment/index.d.ts +4 -4
- package/dist/deployment/index.js +1 -1
- package/dist/deployment/release/addressing.d.ts +9 -1
- package/dist/deployment/release/assemble.d.ts +6 -3
- package/dist/deployment/release/assemble.js +12 -10
- package/dist/deployment/release/index.d.ts +2 -0
- package/dist/deployment/release/index.js +2 -0
- package/dist/deployment/release/legacy/admission.d.ts +3 -0
- package/dist/deployment/release/legacy/admission.js +8 -0
- package/dist/deployment/release/legacy/assemble.d.ts +5 -0
- package/dist/deployment/release/legacy/assemble.js +20 -0
- package/dist/deployment/release/legacy/index.d.ts +30 -0
- package/dist/deployment/release/legacy/index.js +29 -0
- package/dist/deployment/release/legacy/release.d.ts +12 -0
- package/dist/deployment/release/legacy/release.js +1 -0
- package/dist/deployment/release/{publication → legacy}/seal.d.ts +4 -4
- package/dist/deployment/release/legacy/seal.js +17 -0
- package/dist/deployment/release/release.d.ts +17 -6
- package/dist/deployment/release/runtime.d.ts +2 -0
- package/dist/deployment/release/runtime.js +2 -0
- package/dist/deployment/release/seal.d.ts +14 -0
- package/dist/deployment/release/seal.js +22 -0
- package/dist/deployment/release/{publication → served}/callables.d.ts +2 -2
- package/dist/deployment/release/{publication → served}/callables.js +2 -2
- package/dist/deployment/release/served/index.d.ts +12 -0
- package/dist/deployment/release/served/index.js +22 -0
- package/dist/deployment/release/{publication → served}/views.d.ts +2 -2
- package/dist/deployment/runtime/admission.d.ts +2 -2
- package/dist/deployment/runtime/admission.js +5 -5
- package/dist/deployment/verify/index.d.ts +2 -1
- package/dist/deployment/verify/index.js +1 -0
- package/dist/deployment/verify/preflight/artifact.d.ts +1 -1
- package/dist/deployment/verify/preflight/bundle.d.ts +18 -0
- package/dist/deployment/verify/preflight/bundle.js +71 -0
- package/dist/deployment/verify/preflight/index.d.ts +2 -1
- package/dist/deployment/verify/preflight/index.js +1 -0
- package/dist/deployment/verify/preflight/publication.d.ts +2 -2
- package/dist/deployment/verify/preflight/publication.js +4 -4
- package/dist/deployment/verify/readiness/deployment.js +4 -2
- package/dist/deployment/verify/readiness/index.d.ts +1 -1
- package/dist/deployment/verify/readiness/publication.d.ts +2 -2
- package/dist/deployment/verify/readiness/publication.js +1 -1
- package/dist/execution/identity/delivery.d.ts +1 -1
- package/dist/execution/identity/delivery.js +1 -1
- package/dist/execution/identity/identity.d.ts +1 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/invocation/admission/authentication.d.ts +1 -1
- package/dist/execution/invocation/admission/authority.d.ts +2 -1
- package/dist/execution/invocation/admission/authority.js +1 -0
- package/dist/execution/invocation/invocation.js +1 -1
- package/dist/execution/node/serve.d.ts +2 -2
- package/dist/execution/node/serve.js +1 -1
- package/dist/execution/runtime/load.d.ts +1 -1
- package/dist/execution/runtime/load.js +1 -1
- package/dist/execution/serve.d.ts +2 -2
- package/dist/execution/service/publication/installation.d.ts +1 -1
- package/dist/execution/service/release.d.ts +1 -1
- package/dist/execution/service/release.js +1 -1
- package/dist/execution/service/service.d.ts +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/platform/release/index.d.ts +27 -0
- package/dist/platform/release/index.js +27 -0
- package/dist/project/admit.js +2 -2
- package/dist/project/define.d.ts +4 -4
- package/dist/project/define.js +9 -6
- package/dist/project/index.d.ts +1 -1
- package/dist/project/project.d.ts +6 -6
- package/dist/testing/dataset/define.d.ts +1 -1
- package/dist/testing/load.js +1 -1
- package/dist/tooling/cli/arguments.d.ts +1 -0
- package/dist/tooling/cli/arguments.js +7 -2
- package/dist/tooling/cli/build.d.ts +55 -0
- package/dist/tooling/cli/build.js +77 -0
- package/dist/tooling/cli/deploy-mode.d.ts +67 -0
- package/dist/tooling/cli/deploy-mode.js +124 -0
- package/dist/tooling/cli/deploy-result.d.ts +82 -0
- package/dist/tooling/cli/deploy-result.js +63 -0
- package/dist/tooling/cli/development/candidate.d.ts +3 -2
- package/dist/tooling/cli/development/candidate.js +5 -4
- package/dist/tooling/cli/development/report.d.ts +5 -2
- package/dist/tooling/cli/development/view.d.ts +1 -1
- package/dist/tooling/cli/environment-release.d.ts +5 -2
- package/dist/tooling/cli/evidence.d.ts +5 -2
- package/dist/tooling/cli/help.js +20 -10
- package/dist/tooling/cli/index.d.ts +2 -0
- package/dist/tooling/cli/installation/reconcile.d.ts +1 -1
- package/dist/tooling/cli/legacy/deploy-result.d.ts +26 -0
- package/dist/tooling/cli/legacy/deploy-result.js +35 -0
- package/dist/tooling/cli/legacy/stable-target-adapter.d.ts +19 -0
- package/dist/tooling/cli/legacy/stable-target-adapter.js +14 -0
- package/dist/tooling/cli/legacy/uploaded-build.d.ts +11 -0
- package/dist/tooling/cli/legacy/uploaded-build.js +22 -0
- package/dist/tooling/cli/log.d.ts +5 -0
- package/dist/tooling/cli/log.js +9 -0
- package/dist/tooling/cli/orchestrate.js +75 -15
- package/dist/tooling/cli/project.d.ts +3 -3
- package/dist/tooling/linter/implementations/source/callable-requirements.d.ts +1 -1
- package/dist/tooling/linter/implementations/source/callable-requirements.js +10 -10
- package/dist/tooling/linter/implementations/source/dependencies.js +4 -4
- package/dist/tooling/linter/implementations/source/global.js +1 -1
- package/dist/tooling/linter/implementations/source/mutations.js +17 -17
- package/dist/tooling/linter/implementations/source/providers.js +5 -5
- package/dist/tooling/linter/implementations/source/views.js +2 -2
- package/dist/tooling/linter/policy/generated.js +16 -16
- package/dist/tooling/packaging/declarations/ownership.js +1 -1
- package/dist/tooling/packaging/finalize.d.ts +1 -1
- package/dist/tooling/packaging/finalize.js +1 -1
- package/package.json +17 -5
- package/dist/application/application.d.ts +0 -28
- package/dist/deployment/adapter/deploy/index.d.ts +0 -2
- package/dist/deployment/adapter/deploy/result.d.ts +0 -50
- package/dist/deployment/adapter/prepare/artifact.d.ts +0 -33
- package/dist/deployment/adapter/prepare/context.d.ts +0 -23
- package/dist/deployment/adapter/prepare/index.d.ts +0 -2
- package/dist/deployment/release/publication/index.d.ts +0 -6
- package/dist/deployment/release/publication/index.js +0 -6
- package/dist/deployment/release/publication/manifest.d.ts +0 -3
- package/dist/deployment/release/publication/manifest.js +0 -5
- package/dist/deployment/release/publication/requirements.d.ts +0 -3
- package/dist/deployment/release/publication/requirements.js +0 -3
- package/dist/deployment/release/publication/seal.js +0 -39
- package/dist/platform/publication/index.d.ts +0 -2
- package/dist/platform/publication/index.js +0 -2
- /package/dist/application/{application.js → domain.js} +0 -0
- /package/dist/deployment/adapter/{deploy/context.js → bundle/bundle.js} +0 -0
- /package/dist/deployment/adapter/{deploy/index.js → bundle/file.js} +0 -0
- /package/dist/deployment/adapter/{prepare → bundle}/index.js +0 -0
- /package/dist/deployment/adapter/{deploy/result.js → legacy/adapter.js} +0 -0
- /package/dist/deployment/adapter/{prepare → legacy/deploy}/context.js +0 -0
- /package/dist/deployment/adapter/{prepare/artifact.js → legacy/deploy/index.js} +0 -0
- /package/dist/deployment/release/{publication → served}/routes.d.ts +0 -0
- /package/dist/deployment/release/{publication → served}/routes.js +0 -0
- /package/dist/deployment/release/{publication → served}/views.js +0 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# SDK
|
|
2
2
|
|
|
3
|
-
Schema-first SDK for authoring and deploying Astrale
|
|
3
|
+
Schema-first SDK for authoring and deploying Astrale Domains. The public surface separates
|
|
4
4
|
single-step Actions, explicit multi-step Workflows, provider-neutral Integrations, concrete Providers, graph
|
|
5
|
-
authoring,
|
|
5
|
+
authoring, Domain composition, Deployment, and Execution without exposing DSL callable
|
|
6
6
|
topology in implementation files.
|
|
7
7
|
|
|
8
8
|
[](https://github.com/astrale-os/sdk/actions/workflows/ci.yml)
|
|
@@ -17,7 +17,7 @@ npm install @astrale-os/sdk
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Zod schemas cross the SDK and Kernel compiler boundary by runtime identity. The SDK therefore
|
|
20
|
-
declares one exact, non-optional Zod peer. If
|
|
20
|
+
declares one exact, non-optional Zod peer. If a Domain declares Zod directly, it must use the
|
|
21
21
|
same exact version rather than a range; a second physical Zod runtime is not an admitted authoring
|
|
22
22
|
environment.
|
|
23
23
|
|
|
@@ -67,9 +67,10 @@ original issuer discovery endpoints and keys available; unadopted instances cont
|
|
|
67
67
|
previous bindings. Deployment readiness checks the exact new Worker version separately from issuer
|
|
68
68
|
discovery. No uninstall or identity rotation is involved.
|
|
69
69
|
|
|
70
|
-
At the provider-neutral release boundary,
|
|
71
|
-
`addressing('https://services.example.com', { publicUrl: 'https://services-v2.example.com' })
|
|
72
|
-
|
|
70
|
+
At the provider-neutral release boundary, this stable-target path uses
|
|
71
|
+
`addressing('https://services.example.com', { publicUrl: 'https://services-v2.example.com' })` with
|
|
72
|
+
`legacy.assemble`. That split is deprecated with direct mode and goes with it: an immutable
|
|
73
|
+
deployment's URL is its issuer, so `assemble(build, buildDigest, url)` takes the URL alone.
|
|
73
74
|
|
|
74
75
|
## Handler authority and dependencies
|
|
75
76
|
|
|
@@ -135,7 +136,7 @@ Error declarations are not yet published in the installed Kernel Schema.
|
|
|
135
136
|
### Core Identity requirements
|
|
136
137
|
|
|
137
138
|
Use `requirements({ core: [{ subject, functions, classes, authority }] })` to declare capabilities
|
|
138
|
-
for an Identity in the
|
|
139
|
+
for an Identity in the Domain's local Core. `subject` is the resolved Core Node; each entry
|
|
139
140
|
must request at least one capability. The top-level `functions`, `classes`, and `authority` members
|
|
140
141
|
describe capabilities for the Domain principal.
|
|
141
142
|
|
|
@@ -316,6 +317,48 @@ await session.graph.get('@order-id') // Kernel callable: the source credential
|
|
|
316
317
|
| Session with `exchange` | the declaring Domain, for Domain callables | ✅ with the source credential | ✅ Policy evaluated against the identity |
|
|
317
318
|
| `session.exchange(issuer)` held by a second Session | that Domain | ✅ as that Domain | only what that Domain may use |
|
|
318
319
|
|
|
320
|
+
## Deployment addresses
|
|
321
|
+
|
|
322
|
+
`@astrale-os/sdk/deployment/address` derives the one immutable URL of a deployment,
|
|
323
|
+
`https://<line>-<content>.<routingDomain>`, from its inputs alone. Whoever deploys and whoever
|
|
324
|
+
hosts compute it with the same pure, runtime-safe functions, so a host can refuse an address it
|
|
325
|
+
did not derive.
|
|
326
|
+
|
|
327
|
+
- **Line.** `deploymentLine({ origin, environment, addressing })` is shared by every deployment of
|
|
328
|
+
an origin in an environment. Its 16-character fingerprint, the first 80 bits of
|
|
329
|
+
`sha256(origin ‖ 0x00 ‖ environment)` in base32, makes it unique. A `readable` line (platform
|
|
330
|
+
Domains) prefixes it with a cosmetic part, so `agencies.example.com` in `staging` gives
|
|
331
|
+
`agencies-staging-354iwg4avm6wdmrs`. An `opaque` line (tenant Domains) is the fingerprint alone.
|
|
332
|
+
- **Content.** `deploymentContent(buildDigest, configuration)` covers the build and the
|
|
333
|
+
`FrozenConfigurationV1`: the plain variables and execution settings (with the durable Workflow
|
|
334
|
+
options, when declared), the services and dispatch namespaces it binds, and the names of the
|
|
335
|
+
bound secrets, never their values. A changed variable or binding gives another URL, and a rotated
|
|
336
|
+
secret keeps the URL. `configurationDigest` gives the full digest that a deployment record keeps. It checks
|
|
337
|
+
canonical form only: the host refuses settings no Worker runs under when it encodes
|
|
338
|
+
`ASTRALE_SETTINGS` (`encodeWorkerSettings`), before it uploads anything.
|
|
339
|
+
- **Label.** `deploymentLabel(line, content)` is at most 57 characters. `DEPLOYMENT_LABEL`
|
|
340
|
+
recognizes it, never a legacy UUID or stable Worker name, and `parseDeploymentLabel` splits it
|
|
341
|
+
and refuses anything longer than 57 characters.
|
|
342
|
+
- **Record.** `acceptDeploymentRecord` admits a `DeploymentRecordV1` only when its provider
|
|
343
|
+
script is the label that its own fields derive. A host admits the record a deploy declares with
|
|
344
|
+
it before storing it, so every stored record decodes.
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
import {
|
|
348
|
+
deploymentContent,
|
|
349
|
+
deploymentLabel,
|
|
350
|
+
deploymentLine,
|
|
351
|
+
deploymentUrl,
|
|
352
|
+
} from '@astrale-os/sdk/deployment/address'
|
|
353
|
+
|
|
354
|
+
const line = deploymentLine({ origin, environment, addressing: 'opaque' })
|
|
355
|
+
const url = deploymentUrl(deploymentLabel(line, deploymentContent(build, configuration)), routingDomain)
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
`@astrale-os/sdk/deployment/address/vectors` holds the conformance vectors: Worker uploads and
|
|
359
|
+
configurations with the manifest, build digest, label and URL each one gives. Every host that
|
|
360
|
+
recomputes an address tests against them.
|
|
361
|
+
|
|
319
362
|
## License
|
|
320
363
|
|
|
321
364
|
Apache License 2.0 — see [LICENSE](LICENSE) for details.
|
|
@@ -338,10 +381,13 @@ routes: {
|
|
|
338
381
|
```
|
|
339
382
|
|
|
340
383
|
These requirements are publication metadata, so changing them updates the publication ETag without
|
|
341
|
-
changing the
|
|
384
|
+
changing the Domain's business Schema. They require the `shell` handshake. Origins must use
|
|
342
385
|
HTTPS without credentials, paths, queries, fragments, or wildcards; authoring normalizes and sorts
|
|
343
386
|
them. Supporting hosts admit them per mount and execute the existing `browser.openExternal`
|
|
344
387
|
intent. Nested Views cannot expand their parent's grant.
|
|
345
388
|
|
|
346
389
|
For the unified authentication facade and coordinated consumer update, see
|
|
347
390
|
[the Auth API migration guide](docs/auth-api-migration.md).
|
|
391
|
+
|
|
392
|
+
The authored composition formerly called an Application is now a Domain definition: see
|
|
393
|
+
[the Domain definition migration guide](docs/domain-definition-migration.md).
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type { schema } from '../platform/schema/index.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DomainDefinition } from './domain.js';
|
|
3
3
|
import type { Requirements } from './requirements/index.js';
|
|
4
4
|
import type { Routes } from './routes/index.js';
|
|
5
5
|
import type { Runtime } from './runtime/index.js';
|
|
6
6
|
import type { Frontend } from './view/index.js';
|
|
7
|
-
export interface
|
|
7
|
+
export interface DomainDefinitionInput<Schema extends schema.DomainSchema, RuntimeValue extends Runtime<Schema>, FrontendValue extends Frontend<Schema> | undefined, RoutesValue extends Routes | undefined, RequirementsValue extends Requirements | undefined> {
|
|
8
8
|
readonly schema: Schema;
|
|
9
9
|
readonly runtime: RuntimeValue;
|
|
10
10
|
readonly frontend?: FrontendValue;
|
|
11
11
|
readonly routes?: RoutesValue;
|
|
12
12
|
readonly requirements?: RequirementsValue;
|
|
13
13
|
}
|
|
14
|
-
/** Capture one inert authored
|
|
15
|
-
export declare function
|
|
16
|
-
export declare function
|
|
14
|
+
/** Capture one inert authored Domain without resolving, compiling, loading, or deploying it. */
|
|
15
|
+
export declare function defineDomain<const Schema extends schema.DomainSchema, const RuntimeValue extends Runtime<Schema>, const FrontendValue extends Frontend<Schema> | undefined = undefined, const RoutesValue extends Routes | undefined = undefined, const RequirementsValue extends Requirements | undefined = undefined>(input: DomainDefinitionInput<Schema, RuntimeValue, FrontendValue, RoutesValue, RequirementsValue>): DomainDefinition<Schema, RuntimeValue, FrontendValue, RoutesValue, RequirementsValue>;
|
|
16
|
+
export declare function isDomainDefinition(input: unknown): input is DomainDefinition;
|
|
@@ -2,39 +2,39 @@ import { isRequirements } from './requirements/index.js';
|
|
|
2
2
|
import { isRoutes } from './routes/index.js';
|
|
3
3
|
import { isRuntime } from './runtime/index.js';
|
|
4
4
|
import { isFrontend } from './view/index.js';
|
|
5
|
-
const
|
|
6
|
-
/** Capture one inert authored
|
|
7
|
-
export function
|
|
5
|
+
const admittedDomainDefinitions = new WeakSet();
|
|
6
|
+
/** Capture one inert authored Domain without resolving, compiling, loading, or deploying it. */
|
|
7
|
+
export function defineDomain(input) {
|
|
8
8
|
if (input === null || typeof input !== 'object' || Array.isArray(input))
|
|
9
9
|
invalid();
|
|
10
10
|
const allowed = new Set(['schema', 'runtime', 'frontend', 'routes', 'requirements']);
|
|
11
11
|
if (Reflect.ownKeys(input).some((key) => !allowed.has(key)))
|
|
12
12
|
invalid();
|
|
13
13
|
if (!isRuntime(input.runtime))
|
|
14
|
-
throw new TypeError('
|
|
14
|
+
throw new TypeError('Domain Runtime is not admitted.');
|
|
15
15
|
if (input.frontend !== undefined &&
|
|
16
16
|
(!isFrontend(input.frontend) || input.frontend.schema !== input.schema)) {
|
|
17
|
-
throw new TypeError('
|
|
17
|
+
throw new TypeError('Domain Frontend is not admitted for its exact Schema.');
|
|
18
18
|
}
|
|
19
19
|
if (input.routes !== undefined && !isRoutes(input.routes)) {
|
|
20
|
-
throw new TypeError('
|
|
20
|
+
throw new TypeError('Domain routes are not admitted.');
|
|
21
21
|
}
|
|
22
22
|
if (input.requirements !== undefined && !isRequirements(input.requirements)) {
|
|
23
|
-
throw new TypeError('
|
|
23
|
+
throw new TypeError('Domain requirements are not admitted.');
|
|
24
24
|
}
|
|
25
|
-
const
|
|
25
|
+
const domain = Object.freeze({
|
|
26
26
|
schema: input.schema,
|
|
27
27
|
runtime: input.runtime,
|
|
28
28
|
...(input.frontend === undefined ? {} : { frontend: input.frontend }),
|
|
29
29
|
...(input.routes === undefined ? {} : { routes: input.routes }),
|
|
30
30
|
...(input.requirements === undefined ? {} : { requirements: input.requirements }),
|
|
31
31
|
});
|
|
32
|
-
|
|
33
|
-
return
|
|
32
|
+
admittedDomainDefinitions.add(domain);
|
|
33
|
+
return domain;
|
|
34
34
|
}
|
|
35
|
-
export function
|
|
36
|
-
return input !== null && typeof input === 'object' &&
|
|
35
|
+
export function isDomainDefinition(input) {
|
|
36
|
+
return input !== null && typeof input === 'object' && admittedDomainDefinitions.has(input);
|
|
37
37
|
}
|
|
38
38
|
function invalid() {
|
|
39
|
-
throw new TypeError('
|
|
39
|
+
throw new TypeError('Domain definition may contain only schema, runtime, frontend, routes, and requirements.');
|
|
40
40
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { schema } from '../platform/schema/index.js';
|
|
2
|
+
import type { Requirements } from './requirements/index.js';
|
|
3
|
+
import type { Routes } from './routes/index.js';
|
|
4
|
+
import type { Runtime, SchemaOfRuntime as RuntimeSchemaOf } from './runtime/index.js';
|
|
5
|
+
import type { Frontend } from './view/index.js';
|
|
6
|
+
declare const DOMAIN_DEFINITION_IDENTITY: unique symbol;
|
|
7
|
+
declare const DOMAIN_DEFINITION_SCHEMA: unique symbol;
|
|
8
|
+
/** Schema-independent type witness shared by every admitted Domain definition. */
|
|
9
|
+
export interface DomainDefinitionIdentity {
|
|
10
|
+
readonly [DOMAIN_DEFINITION_IDENTITY]: true;
|
|
11
|
+
}
|
|
12
|
+
/** Inert source/build composition of one Domain: its exact Schema and authored Runtime. */
|
|
13
|
+
export interface DomainDefinition<Schema extends schema.DomainSchema = schema.DomainSchema, RuntimeValue extends Runtime<Schema> = Runtime<Schema>, FrontendValue extends Frontend<Schema> | undefined = undefined, RoutesValue extends Routes | undefined = undefined, RequirementsValue extends Requirements | undefined = undefined> extends DomainDefinitionIdentity {
|
|
14
|
+
readonly schema: Schema;
|
|
15
|
+
readonly runtime: RuntimeValue;
|
|
16
|
+
readonly frontend?: FrontendValue;
|
|
17
|
+
readonly routes?: RoutesValue;
|
|
18
|
+
readonly requirements?: RequirementsValue;
|
|
19
|
+
readonly [DOMAIN_DEFINITION_SCHEMA]: (schema: Schema) => Schema;
|
|
20
|
+
}
|
|
21
|
+
export type SchemaOfDomainDefinition<Value> = Value extends {
|
|
22
|
+
readonly schema: infer Schema;
|
|
23
|
+
} ? Extract<Schema, schema.DomainSchema> : never;
|
|
24
|
+
export type RuntimeOfDomainDefinition<Value> = Value extends {
|
|
25
|
+
readonly runtime: infer RuntimeValue;
|
|
26
|
+
} ? Extract<RuntimeValue, Runtime> : never;
|
|
27
|
+
export type SchemaOfRuntime<Value> = RuntimeSchemaOf<Value>;
|
|
28
|
+
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
1
|
+
export { defineDomain, isDomainDefinition } from './define.js';
|
|
2
|
+
export type { DomainDefinitionInput } from './define.js';
|
|
3
3
|
export { requirements } from './requirements/index.js';
|
|
4
4
|
export type { AuthorityRequirements, AuthorityRequirementsInput, ClassOperation, ClassRequirement, ClassRequirementInput, CoreRequirement, CoreRequirementInput, FunctionRequirementTarget, Requirements, RequirementsInput, } from './requirements/index.js';
|
|
5
5
|
export { route, routes } from './routes/index.js';
|
|
6
6
|
export type { Route, RouteInput, RouteTarget, Routes } from './routes/index.js';
|
|
7
7
|
export { defineFrontend, external, vite } from './view/index.js';
|
|
8
8
|
export type { Frontend, FrontendInput, FrontendSource, IframeRequirements, ViewHostRequirements, } from './view/index.js';
|
|
9
|
-
export type {
|
|
9
|
+
export type { DomainDefinition, DomainDefinitionIdentity, RuntimeOfDomainDefinition, SchemaOfDomainDefinition, SchemaOfRuntime, } from './domain.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { defineDomain, isDomainDefinition } from './define.js';
|
|
2
2
|
export { requirements } from './requirements/index.js';
|
|
3
3
|
export { route, routes } from './routes/index.js';
|
|
4
4
|
export { defineFrontend, external, vite } from './view/index.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { release } from '@astrale-os/kernel-protocol';
|
|
2
2
|
import type { RuntimeRegistry } from '../runtime/index.js';
|
|
3
3
|
import type { Routes } from './collection.js';
|
|
4
4
|
/** Lower recipe identities to canonical callable keys after Runtime admission. */
|
|
5
|
-
export declare function admit(input: Routes | undefined, registry: RuntimeRegistry): readonly
|
|
5
|
+
export declare function admit(input: Routes | undefined, registry: RuntimeRegistry): readonly release.HttpRouteDeclaration[];
|
|
@@ -4,7 +4,7 @@ export function admit(input, registry) {
|
|
|
4
4
|
if (input === undefined)
|
|
5
5
|
return Object.freeze([]);
|
|
6
6
|
if (!isRoutes(input))
|
|
7
|
-
throw new TypeError('
|
|
7
|
+
throw new TypeError('Domain routes are not admitted.');
|
|
8
8
|
return Object.freeze(input.entries.map(({ target, ...declaration }) => {
|
|
9
9
|
const implementation = registry.implementations.find(({ definition }) => definition === target);
|
|
10
10
|
if (implementation === undefined) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { release } from '@astrale-os/kernel-protocol';
|
|
2
2
|
export interface RouteTarget {
|
|
3
3
|
readonly kind: 'action' | 'workflow';
|
|
4
4
|
readonly address: string;
|
|
5
5
|
}
|
|
6
|
-
export type RouteInput = Omit<
|
|
6
|
+
export type RouteInput = Omit<release.HttpRouteDeclaration, 'callable'>;
|
|
7
7
|
/** One provider-neutral HTTP route targeting an admitted Action or Workflow recipe. */
|
|
8
8
|
export interface Route<Target extends RouteTarget = RouteTarget> extends RouteInput {
|
|
9
9
|
readonly target: Target;
|
|
@@ -1,27 +1,76 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
1
|
+
import type { DeploymentSummaryV1, FrozenConfigurationV1 } from '../address/index.js';
|
|
2
|
+
import type { Bundler } from './bundle/index.js';
|
|
3
|
+
import type { ArtifactSource, DeployContext, DeployResult, InstallationTarget, PrepareContext } from './legacy/index.js';
|
|
4
|
+
import type { ConfigureContext, ListContext, Placement, PlacementContext, ReleaseDeployContext, ReleaseDeployResult, RetainContext } from './release/index.js';
|
|
5
|
+
/** What `admit` receives when `defineProject` binds an adapter to one Environment. */
|
|
7
6
|
export interface AdapterEnvironmentContext {
|
|
8
7
|
readonly environment: string;
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Deploy-time installation, which the canonical path refuses (CT33). Replacement:
|
|
10
|
+
* `astrale domain install <url> -i <instance>` after `astrale-domain deploy <environment>`.
|
|
11
|
+
*/
|
|
9
12
|
readonly installation?: InstallationTarget;
|
|
10
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* A provider adapter (adapter interface v2). It bundles a Build without any Environment, freezes
|
|
16
|
+
* an Environment's configuration, says where the host places that Environment's deployments, and
|
|
17
|
+
* deploys one sealed release as one immutable deployment, created or reused. It never installs:
|
|
18
|
+
* `astrale domain install <url>` installs a deployment by its URL.
|
|
19
|
+
*
|
|
20
|
+
* `prepare` and `deploy` remain only for an adapter that also serves Environments on the legacy
|
|
21
|
+
* direct-mode path (CT33); an adapter declares both or neither.
|
|
22
|
+
*/
|
|
11
23
|
export interface Adapter<Parameters extends object = object> {
|
|
12
24
|
readonly kind: 'adapter';
|
|
13
25
|
readonly name: string;
|
|
14
26
|
readonly version: string;
|
|
27
|
+
/**
|
|
28
|
+
* Produces the environment-free bytes `astrale-domain build` identifies by their build digest
|
|
29
|
+
* and `deployRelease` receives as its Bundle. Adapters that share one bundler share one build.
|
|
30
|
+
*/
|
|
31
|
+
readonly bundler: Bundler;
|
|
32
|
+
/** Refuse parameters that cannot serve this Environment, before any effect. */
|
|
15
33
|
admit?(parameters: Parameters, context: AdapterEnvironmentContext): void;
|
|
16
|
-
|
|
17
|
-
|
|
34
|
+
/** Freeze what a deployment of this Environment binds beside its build. Pure. */
|
|
35
|
+
configure(parameters: Parameters, context: ConfigureContext): FrozenConfigurationV1;
|
|
36
|
+
/** Where the host places this Environment's deployments. No effect at the host. */
|
|
37
|
+
placement(parameters: Parameters, context: PlacementContext): Promise<Placement>;
|
|
38
|
+
/** Create, or reuse, the immutable deployment of one sealed release. */
|
|
39
|
+
deployRelease(parameters: Parameters, context: ReleaseDeployContext): Promise<ReleaseDeployResult>;
|
|
40
|
+
/** The deployments of one origin the host keeps for the caller. */
|
|
41
|
+
list?(parameters: Parameters, context: ListContext): Promise<readonly DeploymentSummaryV1[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Keep one published deployment where the host has no registry principal to mark it (a platform
|
|
44
|
+
* namespace). Called only after its Publication commits. Absent: the registry marks it (Admin's
|
|
45
|
+
* Services).
|
|
46
|
+
*/
|
|
47
|
+
retain?(parameters: Parameters, context: RetainContext): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* @deprecated Legacy direct-mode path (CT33) only: place a build at a stable target. Replacement:
|
|
50
|
+
* `bundler`, `configure` and `placement`. Deleted with the legacy path (D10).
|
|
51
|
+
*/
|
|
52
|
+
prepare?(parameters: Parameters, context: PrepareContext): Promise<ArtifactSource>;
|
|
53
|
+
/**
|
|
54
|
+
* @deprecated Legacy direct-mode path (CT33) only: replace a stable target's code in place.
|
|
55
|
+
* Replacement: `deployRelease`. Deleted with the legacy path (D10).
|
|
56
|
+
*/
|
|
57
|
+
deploy?(parameters: Parameters, context: DeployContext): Promise<DeployResult>;
|
|
18
58
|
readonly secretsFile?: (parameters: Parameters) => string | undefined;
|
|
19
59
|
}
|
|
60
|
+
/** What `defineAdapter` admits for an `Adapter` (adapter interface v2). */
|
|
20
61
|
export interface AdapterInput<Parameters extends object> {
|
|
21
62
|
readonly name: string;
|
|
22
63
|
readonly version: string;
|
|
64
|
+
readonly bundler: Bundler;
|
|
23
65
|
admit?(parameters: Parameters, context: AdapterEnvironmentContext): void;
|
|
24
|
-
|
|
25
|
-
|
|
66
|
+
configure(parameters: Parameters, context: ConfigureContext): FrozenConfigurationV1;
|
|
67
|
+
placement(parameters: Parameters, context: PlacementContext): Promise<Placement>;
|
|
68
|
+
deployRelease(parameters: Parameters, context: ReleaseDeployContext): Promise<ReleaseDeployResult>;
|
|
69
|
+
list?(parameters: Parameters, context: ListContext): Promise<readonly DeploymentSummaryV1[]>;
|
|
70
|
+
retain?(parameters: Parameters, context: RetainContext): Promise<void>;
|
|
71
|
+
/** @deprecated Legacy direct-mode path (CT33) only. Replacement: `configure`, `placement`. */
|
|
72
|
+
prepare?(parameters: Parameters, context: PrepareContext): Promise<ArtifactSource>;
|
|
73
|
+
/** @deprecated Legacy direct-mode path (CT33) only. Replacement: `deployRelease`. */
|
|
74
|
+
deploy?(parameters: Parameters, context: DeployContext): Promise<DeployResult>;
|
|
26
75
|
readonly secretsFile?: (parameters: Parameters) => string | undefined;
|
|
27
76
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Build, BuildDigest, BuildManifestV1 } from '../../build/index.js';
|
|
2
|
+
import type { ResolvedRuntimeReference } from '../../runtime/index.js';
|
|
3
|
+
import type { ArtifactFile, PreparedArtifactFile } from './file.js';
|
|
4
|
+
/**
|
|
5
|
+
* Produces the environment-free bytes of one Build. It takes no Environment, address, key or
|
|
6
|
+
* secret, which is what makes its build digest identical in every Environment. Adapters that share
|
|
7
|
+
* a bundler share their build.
|
|
8
|
+
*/
|
|
9
|
+
export interface Bundler {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly version: string;
|
|
12
|
+
bundle(context: BundleContext): Promise<BundleSource>;
|
|
13
|
+
}
|
|
14
|
+
export interface BundleContext<BuildValue extends Build = Build> {
|
|
15
|
+
readonly projectDir: string;
|
|
16
|
+
readonly build: BuildValue;
|
|
17
|
+
readonly runtime: ResolvedRuntimeReference;
|
|
18
|
+
/** Parent-owned lifecycle cancellation shared by every bundling process. */
|
|
19
|
+
readonly signal: AbortSignal;
|
|
20
|
+
/** Optional observer of authored paths read outside the Domain/Runtime module graph. */
|
|
21
|
+
readonly recordSource?: (path: string) => void;
|
|
22
|
+
}
|
|
23
|
+
/** Untrusted bundler output admitted by verify/preflight. */
|
|
24
|
+
export interface BundleSource {
|
|
25
|
+
readonly entrypoint: string;
|
|
26
|
+
readonly files: readonly ArtifactFile[];
|
|
27
|
+
}
|
|
28
|
+
/** Exact environment-free bytes of one Build, identified by their build digest. */
|
|
29
|
+
export interface Bundle<BuildValue extends Build = Build> {
|
|
30
|
+
readonly kind: 'bundle';
|
|
31
|
+
readonly build: BuildValue;
|
|
32
|
+
readonly manifest: BuildManifestV1;
|
|
33
|
+
readonly digest: BuildDigest;
|
|
34
|
+
readonly entrypoint: string;
|
|
35
|
+
readonly files: readonly PreparedArtifactFile[];
|
|
36
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** One file a bundler or a legacy preparation produced, before admission. */
|
|
2
|
+
export interface ArtifactFile {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
readonly content: Uint8Array;
|
|
5
|
+
}
|
|
6
|
+
/** One admitted file: a detached copy of its bytes on every read. */
|
|
7
|
+
export interface PreparedArtifactFile {
|
|
8
|
+
readonly path: string;
|
|
9
|
+
bytes(): Uint8Array;
|
|
10
|
+
}
|
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
import type { Deployment } from '../deployment.js';
|
|
2
2
|
import type { Adapter, AdapterInput } from './adapter.js';
|
|
3
|
-
|
|
3
|
+
import type { LegacyAdapter, LegacyAdapterInput } from './legacy/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Capture one receiver-bound provider adapter (adapter interface v2): a required `bundler`,
|
|
6
|
+
* `configure`, `placement` and `deployRelease`, optionally `list` and `retain`, and `prepare` with
|
|
7
|
+
* `deploy` only while it also serves the legacy direct-mode path.
|
|
8
|
+
*/
|
|
4
9
|
export declare function defineAdapter<Parameters extends object>(input: AdapterInput<Parameters>): Adapter<Parameters>;
|
|
10
|
+
/**
|
|
11
|
+
* Capture one receiver-bound adapter on the contract before interface v2: its required `bundler`,
|
|
12
|
+
* `prepare` and `deploy`.
|
|
13
|
+
*
|
|
14
|
+
* @deprecated Every Environment such an adapter deploys is on the legacy direct-mode path (CT33).
|
|
15
|
+
* Declare adapter interface v2 instead: `configure`, `placement` and `deployRelease` beside the
|
|
16
|
+
* same `bundler`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function defineAdapter<Parameters extends object>(input: LegacyAdapterInput<Parameters>): LegacyAdapter<Parameters>;
|
|
5
19
|
/** Bind one provider adapter to the parameters of one Project Environment. */
|
|
6
|
-
export declare function defineDeployment<const Parameters extends object>(adapter: Adapter<Parameters>, parameters: Parameters): Deployment<Parameters
|
|
7
|
-
|
|
20
|
+
export declare function defineDeployment<const Parameters extends object>(adapter: Adapter<Parameters>, parameters: Parameters): Deployment<Parameters, Adapter<Parameters>>;
|
|
21
|
+
/**
|
|
22
|
+
* Bind one adapter on the contract before interface v2 to the parameters of one Environment.
|
|
23
|
+
*
|
|
24
|
+
* @deprecated The Environment is on the legacy direct-mode path (CT33). Replacement: an adapter
|
|
25
|
+
* that implements adapter interface v2.
|
|
26
|
+
*/
|
|
27
|
+
export declare function defineDeployment<const Parameters extends object>(adapter: LegacyAdapter<Parameters>, parameters: Parameters): Deployment<Parameters, LegacyAdapter<Parameters>>;
|
|
28
|
+
/** Whether `defineAdapter` admitted this value, on either contract. */
|
|
29
|
+
export declare function isAdapter(input: unknown): input is Adapter | LegacyAdapter;
|
|
@@ -1,29 +1,78 @@
|
|
|
1
1
|
import { captureDeployment } from '../deployment.js';
|
|
2
2
|
const admittedAdapters = new WeakSet();
|
|
3
|
-
|
|
3
|
+
const admittedBundlers = new WeakMap();
|
|
4
|
+
/** Every field an adapter definition may declare, in either contract. */
|
|
5
|
+
const FIELDS = [
|
|
6
|
+
'name',
|
|
7
|
+
'version',
|
|
8
|
+
'bundler',
|
|
9
|
+
'admit',
|
|
10
|
+
'configure',
|
|
11
|
+
'placement',
|
|
12
|
+
'deployRelease',
|
|
13
|
+
'list',
|
|
14
|
+
'retain',
|
|
15
|
+
'prepare',
|
|
16
|
+
'deploy',
|
|
17
|
+
'secretsFile',
|
|
18
|
+
];
|
|
19
|
+
/** The operations that make a definition adapter interface v2. */
|
|
20
|
+
const RELEASE_OPERATIONS = ['configure', 'placement', 'deployRelease'];
|
|
21
|
+
const OPTIONAL_RELEASE_OPERATIONS = ['list', 'retain'];
|
|
22
|
+
/** The operations of the legacy direct-mode path. */
|
|
23
|
+
const STABLE_TARGET_OPERATIONS = ['prepare', 'deploy'];
|
|
24
|
+
/** Every operation an adapter may declare, in the order an admitted adapter lists them. */
|
|
25
|
+
const OPERATIONS = FIELDS.filter((key) => key !== 'name' && key !== 'version' && key !== 'bundler');
|
|
4
26
|
export function defineAdapter(input) {
|
|
5
27
|
const value = record(input, 'Adapter definition');
|
|
6
|
-
|
|
28
|
+
if (Reflect.ownKeys(value).some((key) => !FIELDS.includes(key))) {
|
|
29
|
+
invalidFields();
|
|
30
|
+
}
|
|
31
|
+
const declared = (key) => value[key] !== undefined;
|
|
32
|
+
const release = [...RELEASE_OPERATIONS, ...OPTIONAL_RELEASE_OPERATIONS].some(declared);
|
|
33
|
+
// A legacy definition names both operations, as it always had to; v2 treats undefined as absent.
|
|
34
|
+
const stableTarget = STABLE_TARGET_OPERATIONS.filter((key) => release ? declared(key) : Object.hasOwn(value, key));
|
|
35
|
+
if (!release && stableTarget.length !== STABLE_TARGET_OPERATIONS.length)
|
|
36
|
+
invalidFields();
|
|
7
37
|
const name = stableName(input.name);
|
|
8
38
|
const version = stableName(input.version);
|
|
39
|
+
if (release)
|
|
40
|
+
admitRelease(name, value, stableTarget.length);
|
|
41
|
+
if (value.bundler === undefined)
|
|
42
|
+
missingBundler(name);
|
|
43
|
+
const bundler = admitBundler(input.bundler);
|
|
9
44
|
const receiver = Object.freeze({ ...input });
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
45
|
+
const required = new Set([...(release ? RELEASE_OPERATIONS : []), ...stableTarget]);
|
|
46
|
+
const operations = Object.fromEntries(OPERATIONS.filter((key) => required.has(key) || declared(key)).map((key) => [
|
|
47
|
+
key,
|
|
48
|
+
capture(receiver, key),
|
|
49
|
+
]));
|
|
14
50
|
const adapter = Object.freeze({
|
|
15
51
|
kind: 'adapter',
|
|
16
52
|
name,
|
|
17
53
|
version,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
deploy,
|
|
21
|
-
...(secretsFile === undefined ? {} : { secretsFile }),
|
|
54
|
+
bundler,
|
|
55
|
+
...operations,
|
|
22
56
|
});
|
|
23
57
|
admittedAdapters.add(adapter);
|
|
24
58
|
return adapter;
|
|
25
59
|
}
|
|
26
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* An adapter interface v2 definition implements configure, placement and deployRelease, and keeps
|
|
62
|
+
* prepare with deploy, or neither.
|
|
63
|
+
*/
|
|
64
|
+
function admitRelease(name, value, stableTargetOperations) {
|
|
65
|
+
const missing = RELEASE_OPERATIONS.filter((key) => value[key] === undefined);
|
|
66
|
+
if (missing.length > 0) {
|
|
67
|
+
throw new TypeError(`Adapter ${name} declares part of adapter interface v2 without ${missing.join(', ')}: ` +
|
|
68
|
+
'an adapter that deploys immutable deployments implements configure, placement and ' +
|
|
69
|
+
'deployRelease.');
|
|
70
|
+
}
|
|
71
|
+
if (stableTargetOperations === 1) {
|
|
72
|
+
throw new TypeError(`Adapter ${name} declares only one of prepare and deploy: an adapter that keeps the legacy ` +
|
|
73
|
+
'direct-mode path declares both.');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
27
76
|
export function defineDeployment(adapter, parameters) {
|
|
28
77
|
if (!isAdapter(adapter))
|
|
29
78
|
throw new TypeError('Deployment Adapter is not admitted.');
|
|
@@ -32,12 +81,39 @@ export function defineDeployment(adapter, parameters) {
|
|
|
32
81
|
}
|
|
33
82
|
return captureDeployment(adapter, Object.freeze({ ...parameters }));
|
|
34
83
|
}
|
|
84
|
+
/** Whether `defineAdapter` admitted this value, on either contract. */
|
|
35
85
|
export function isAdapter(input) {
|
|
36
86
|
return input !== null && typeof input === 'object' && admittedAdapters.has(input);
|
|
37
87
|
}
|
|
38
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Capture one receiver-bound bundler; its id and version name the bytes it produces. Adapters that
|
|
90
|
+
* declare one bundler object receive one admitted Bundler, so `astrale-domain build` bundles once
|
|
91
|
+
* for all of them.
|
|
92
|
+
*/
|
|
93
|
+
function admitBundler(input) {
|
|
94
|
+
const value = record(input, 'Bundler');
|
|
95
|
+
if (Reflect.ownKeys(value).some((key) => key !== 'id' && key !== 'version' && key !== 'bundle') ||
|
|
96
|
+
typeof input.bundle !== 'function') {
|
|
97
|
+
throw new TypeError('Bundler must declare exactly id, version and bundle.');
|
|
98
|
+
}
|
|
99
|
+
const admitted = admittedBundlers.get(value);
|
|
100
|
+
if (admitted !== undefined &&
|
|
101
|
+
admitted.declared === input.bundle &&
|
|
102
|
+
admitted.bundler.id === input.id &&
|
|
103
|
+
admitted.bundler.version === input.version) {
|
|
104
|
+
return admitted.bundler;
|
|
105
|
+
}
|
|
106
|
+
const bundler = Object.freeze({
|
|
107
|
+
id: stableName(input.id, 'Bundler id'),
|
|
108
|
+
version: stableName(input.version, 'Bundler version'),
|
|
109
|
+
bundle: input.bundle.bind(input),
|
|
110
|
+
});
|
|
111
|
+
admittedBundlers.set(value, { declared: input.bundle, bundler });
|
|
112
|
+
return bundler;
|
|
113
|
+
}
|
|
114
|
+
function stableName(input, label = 'Adapter name') {
|
|
39
115
|
if (typeof input !== 'string' || input.length === 0 || input.trim() !== input) {
|
|
40
|
-
throw new TypeError(
|
|
116
|
+
throw new TypeError(`${label} must be a non-empty stable string.`);
|
|
41
117
|
}
|
|
42
118
|
return input;
|
|
43
119
|
}
|
|
@@ -47,20 +123,21 @@ function record(input, label) {
|
|
|
47
123
|
}
|
|
48
124
|
return input;
|
|
49
125
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
126
|
+
/** Every adapter, on either contract, declares the bundler of the bytes it deploys. */
|
|
127
|
+
function missingBundler(name) {
|
|
128
|
+
throw new TypeError(`Adapter ${name} declares no bundler. ` +
|
|
129
|
+
'Every adapter declares `bundler`: the bundler of the environment-free bytes ' +
|
|
130
|
+
'`astrale-domain build` identifies by their build digest and `astrale-domain deploy` hands ' +
|
|
131
|
+
'to the adapter as its Bundle (a Cloudflare Worker adapter declares ' +
|
|
132
|
+
'`cloudflareWorkerBundler` from `@astrale-os/adapter-cloudflare/build`).');
|
|
133
|
+
}
|
|
134
|
+
function invalidFields() {
|
|
135
|
+
throw new TypeError('Adapter definition contains missing or unknown fields.');
|
|
56
136
|
}
|
|
57
137
|
function capture(receiver, key) {
|
|
58
|
-
const method = receiver
|
|
138
|
+
const method = Reflect.get(receiver, key);
|
|
59
139
|
if (typeof method !== 'function') {
|
|
60
|
-
throw new TypeError(`Adapter ${
|
|
140
|
+
throw new TypeError(`Adapter ${key} operation is invalid.`);
|
|
61
141
|
}
|
|
62
142
|
return method.bind(receiver);
|
|
63
143
|
}
|
|
64
|
-
function optional(receiver, key) {
|
|
65
|
-
return receiver[key] === undefined ? undefined : capture(receiver, key);
|
|
66
|
-
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export type { Adapter, AdapterEnvironmentContext, AdapterInput
|
|
1
|
+
export type { Adapter, AdapterEnvironmentContext, AdapterInput } from './adapter.js';
|
|
2
2
|
export { defineAdapter, defineDeployment, isAdapter } from './define.js';
|
|
3
|
-
export type * from './
|
|
4
|
-
export type * from './
|
|
3
|
+
export type * from './bundle/index.js';
|
|
4
|
+
export type * from './release/index.js';
|
|
5
|
+
/** @deprecated The contract before adapter interface v2; see `./legacy/index.ts`. */
|
|
6
|
+
export type * from './legacy/index.js';
|