@astrale-os/sdk 0.5.0-beta.99 → 0.6.0-beta.1
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 +165 -2
- package/dist/application/action/action.d.ts +7 -4
- package/dist/application/action/authoring.d.ts +2 -1
- package/dist/application/action/context.d.ts +18 -13
- package/dist/application/action/define.d.ts +5 -1
- package/dist/application/action/define.js +6 -1
- package/dist/application/action/index.d.ts +2 -1
- package/dist/application/dependency/index.d.ts +1 -0
- package/dist/application/dependency/invoker.d.ts +26 -0
- package/dist/application/error/error.d.ts +23 -0
- package/dist/application/error/error.js +87 -0
- package/dist/application/error/index.d.ts +2 -0
- package/dist/application/error/index.js +1 -0
- package/dist/application/index.d.ts +2 -2
- package/dist/application/integration/authentication.d.ts +10 -0
- package/dist/application/integration/authentication.typecheck.js +18 -0
- package/dist/application/integration/client.d.ts +2 -0
- package/dist/application/integration/client.js +19 -2
- package/dist/application/integration/index.d.ts +1 -0
- package/dist/application/integration/operation.d.ts +3 -0
- package/dist/application/mutation/authoring/builder.js +2 -2
- package/dist/application/mutation/authoring/endpoint.d.ts +3 -3
- package/dist/application/mutation/authoring/endpoint.js +9 -0
- package/dist/application/mutation/failure.js +13 -7
- package/dist/application/mutation/index.d.ts +1 -0
- package/dist/application/requirements/{profiles.d.ts → core.d.ts} +5 -3
- package/dist/application/requirements/{profiles.js → core.js} +6 -6
- package/dist/application/requirements/index.d.ts +4 -4
- package/dist/application/requirements/index.js +5 -5
- package/dist/application/requirements/requirement.d.ts +3 -2
- package/dist/application/runtime/authoring.d.ts +1 -0
- package/dist/application/runtime/callables.js +2 -2
- package/dist/application/runtime/declarations.d.ts +43 -0
- package/dist/application/runtime/define.d.ts +2 -1
- package/dist/application/view/index.d.ts +1 -1
- package/dist/application/view/route.d.ts +12 -0
- package/dist/application/view/route.js +5 -1
- package/dist/application/workflow/authoring.d.ts +1 -0
- package/dist/application/workflow/context.d.ts +2 -1
- package/dist/application/workflow/define.d.ts +5 -1
- package/dist/application/workflow/define.js +6 -1
- package/dist/application/workflow/index.d.ts +1 -0
- package/dist/application/workflow/runner/runner.d.ts +3 -2
- package/dist/application/workflow/workflow.d.ts +4 -3
- package/dist/deployment/adapter/adapter.d.ts +12 -7
- package/dist/deployment/adapter/define.d.ts +5 -2
- package/dist/deployment/adapter/define.js +15 -17
- package/dist/deployment/adapter/deploy/context.d.ts +6 -0
- package/dist/deployment/adapter/deploy/result.d.ts +2 -0
- package/dist/deployment/adapter/index.d.ts +2 -3
- package/dist/deployment/adapter/index.js +1 -1
- package/dist/deployment/adapter/prepare/context.d.ts +13 -5
- package/dist/deployment/authoring.d.ts +1 -1
- package/dist/deployment/build/compile.js +21 -19
- package/dist/deployment/build/frontend/compilation.d.ts +2 -1
- package/dist/deployment/build/frontend/compilation.js +1 -0
- package/dist/deployment/build/material.js +5 -5
- package/dist/deployment/deploy.d.ts +10 -4
- package/dist/deployment/deploy.js +5 -5
- package/dist/deployment/deployment.d.ts +8 -5
- package/dist/deployment/deployment.js +10 -1
- package/dist/deployment/index.d.ts +5 -4
- package/dist/deployment/index.js +3 -2
- package/dist/deployment/release/addressing.d.ts +6 -2
- package/dist/deployment/release/addressing.js +9 -4
- package/dist/deployment/release/publication/callables.js +1 -1
- package/dist/deployment/release/publication/index.d.ts +1 -1
- package/dist/deployment/release/publication/index.js +1 -1
- package/dist/deployment/release/publication/routes.js +1 -1
- package/dist/deployment/release/publication/seal.d.ts +0 -1
- package/dist/deployment/release/publication/seal.js +4 -5
- package/dist/deployment/release/publication/views.js +2 -1
- package/dist/deployment/verify/preflight/artifact.js +1 -1
- package/dist/deployment/verify/readiness/deployment.js +7 -3
- package/dist/deployment/verify/readiness/identity.js +1 -1
- package/dist/deployment/verify/readiness/publication.js +2 -2
- package/dist/execution/identity/authentication.js +0 -1
- package/dist/execution/identity/exchange.d.ts +1 -0
- package/dist/execution/identity/exchange.js +1 -1
- package/dist/execution/identity/jwks.js +1 -1
- package/dist/execution/invocation/admission/authentication.d.ts +6 -3
- package/dist/execution/invocation/admission/authentication.js +16 -6
- package/dist/execution/invocation/admission/authority.d.ts +2 -2
- package/dist/execution/invocation/dependency/bind.d.ts +5 -0
- package/dist/execution/invocation/dependency/bind.js +68 -0
- package/dist/execution/invocation/dependency/index.d.ts +1 -0
- package/dist/execution/invocation/dependency/index.js +1 -0
- package/dist/execution/invocation/dispatch/action.js +19 -2
- package/dist/execution/invocation/dispatch/context.d.ts +4 -4
- package/dist/execution/invocation/dispatch/context.js +29 -9
- package/dist/execution/invocation/dispatch/workflow.js +17 -4
- package/dist/execution/invocation/integration/authentication.d.ts +5 -0
- package/dist/execution/invocation/integration/authentication.js +53 -0
- package/dist/execution/invocation/integration/call.d.ts +7 -1
- package/dist/execution/invocation/integration/call.js +8 -3
- package/dist/execution/invocation/integration/clients.d.ts +2 -2
- package/dist/execution/invocation/integration/clients.js +2 -2
- package/dist/execution/invocation/lifecycle/active.js +30 -5
- package/dist/execution/invocation/result/errors.d.ts +1 -0
- package/dist/execution/invocation/result/errors.js +15 -10
- package/dist/execution/service/create.js +3 -1
- package/dist/execution/service/service.d.ts +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/platform/auth/index.d.ts +1 -1
- package/dist/platform/auth/index.js +0 -1
- package/dist/platform/graph/alias.d.ts +6 -0
- package/dist/platform/graph/alias.js +6 -0
- package/dist/platform/graph/document/index.d.ts +2 -1
- package/dist/platform/graph/document/index.js +2 -1
- package/dist/platform/graph/index.d.ts +2 -1
- package/dist/platform/graph/index.js +2 -1
- package/dist/platform/schema/class-authoring.d.ts +37 -0
- package/dist/platform/schema/class-authoring.js +20 -0
- package/dist/platform/schema/class-icon.d.ts +15 -0
- package/dist/platform/schema/class-icon.js +46 -0
- package/dist/platform/schema/error.d.ts +11 -0
- package/dist/platform/schema/error.js +34 -0
- package/dist/platform/schema/errors/index.d.ts +3 -0
- package/dist/platform/schema/errors/index.js +2 -0
- package/dist/platform/schema/icons/index.d.ts +2 -0
- package/dist/platform/schema/icons/index.js +2 -0
- package/dist/platform/schema/index.d.ts +20 -13
- package/dist/platform/schema/index.js +9 -4
- package/dist/platform/schema/kernel.d.ts +22 -0
- package/dist/platform/schema/kernel.js +5 -0
- package/dist/platform/schema/node-id.d.ts +3 -0
- package/dist/platform/schema/node-id.js +6 -0
- package/dist/platform/schema/property.d.ts +12 -0
- package/dist/platform/schema/property.js +3 -0
- package/dist/platform/schema/schema-authoring.d.ts +48 -0
- package/dist/platform/schema/schema-authoring.js +3 -0
- package/dist/platform/schema/state-property.d.ts +11 -0
- package/dist/platform/schema/state-property.js +3 -0
- package/dist/project/admit.d.ts +4 -0
- package/dist/project/admit.js +22 -0
- package/dist/project/define.d.ts +12 -0
- package/dist/project/define.js +106 -0
- package/dist/project/index.d.ts +4 -0
- package/dist/project/index.js +2 -0
- package/dist/project/project.d.ts +24 -0
- package/dist/project/project.js +1 -0
- package/dist/testing/dataset/admission.d.ts +13 -0
- package/dist/testing/dataset/admission.js +107 -0
- package/dist/testing/dataset/builder.d.ts +42 -0
- package/dist/testing/dataset/builder.js +127 -0
- package/dist/testing/dataset/codec.d.ts +6 -0
- package/dist/testing/dataset/codec.js +113 -0
- package/dist/testing/dataset/dataset.d.ts +58 -0
- package/dist/testing/dataset/dataset.js +2 -0
- package/dist/testing/dataset/define.d.ts +33 -0
- package/dist/testing/dataset/define.js +105 -0
- package/dist/testing/dataset/index.d.ts +8 -0
- package/dist/testing/dataset/index.js +4 -0
- package/dist/testing/dataset/references.d.ts +14 -0
- package/dist/testing/dataset/references.js +56 -0
- package/dist/testing/index.d.ts +9 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/load.d.ts +14 -0
- package/dist/testing/load.js +44 -0
- package/dist/testing/reference.d.ts +11 -0
- package/dist/testing/reference.js +19 -0
- package/dist/testing/tests.d.ts +12 -0
- package/dist/testing/tests.js +31 -0
- package/dist/tooling/cli/arguments.d.ts +7 -4
- package/dist/tooling/cli/arguments.js +82 -107
- package/dist/tooling/cli/astrale/authority.d.ts +5 -0
- package/dist/tooling/cli/astrale/authority.js +11 -0
- package/dist/tooling/cli/astrale/executable.d.ts +2 -0
- package/dist/tooling/cli/astrale/executable.js +47 -0
- package/dist/tooling/cli/astrale/failure.d.ts +6 -0
- package/dist/tooling/cli/astrale/failure.js +48 -0
- package/dist/tooling/cli/astrale/instance.d.ts +11 -0
- package/dist/tooling/cli/astrale/instance.js +52 -0
- package/dist/tooling/cli/astrale/process.d.ts +13 -0
- package/dist/tooling/cli/astrale/process.js +94 -0
- package/dist/tooling/cli/astrale/version.d.ts +18 -0
- package/dist/tooling/cli/astrale/version.js +55 -0
- package/dist/tooling/cli/bun.js +1 -1
- package/dist/tooling/cli/credential.d.ts +2 -0
- package/dist/tooling/cli/credential.js +57 -0
- package/dist/tooling/cli/deprecations.d.ts +9 -0
- package/dist/tooling/cli/deprecations.js +15 -0
- package/dist/tooling/cli/development/candidate.d.ts +25 -0
- package/dist/tooling/cli/development/candidate.js +176 -0
- package/dist/tooling/cli/development/deployment.d.ts +16 -0
- package/dist/tooling/cli/development/deployment.js +39 -0
- package/dist/tooling/cli/development/develop.d.ts +4 -3
- package/dist/tooling/cli/development/develop.js +129 -290
- package/dist/tooling/cli/development/lease.d.ts +18 -0
- package/dist/tooling/cli/development/lease.js +163 -0
- package/dist/tooling/cli/development/lifecycle.js +4 -0
- package/dist/tooling/cli/development/project-imports.d.ts +22 -0
- package/dist/tooling/cli/development/project-imports.js +39 -0
- package/dist/tooling/cli/development/project-lock.d.ts +3 -4
- package/dist/tooling/cli/development/project-lock.js +14 -166
- package/dist/tooling/cli/development/release-evidence.d.ts +4 -0
- package/dist/tooling/cli/development/release-evidence.js +10 -0
- package/dist/tooling/cli/development/report.d.ts +6 -0
- package/dist/tooling/cli/development/report.js +14 -0
- package/dist/tooling/cli/development/source-watch.js +53 -5
- package/dist/tooling/cli/development/sources.d.ts +7 -0
- package/dist/tooling/cli/development/sources.js +48 -0
- package/dist/tooling/cli/development/target-lock.d.ts +16 -0
- package/dist/tooling/cli/development/target-lock.js +68 -0
- package/dist/tooling/cli/development/view.d.ts +28 -0
- package/dist/tooling/cli/development/view.js +151 -0
- package/dist/tooling/cli/environment-release.d.ts +21 -0
- package/dist/tooling/cli/environment-release.js +46 -0
- package/dist/tooling/cli/evidence.d.ts +11 -0
- package/dist/tooling/cli/evidence.js +53 -0
- package/dist/tooling/cli/help.js +78 -34
- package/dist/tooling/cli/index.d.ts +1 -1
- package/dist/tooling/cli/index.js +1 -1
- package/dist/tooling/cli/installation/index.d.ts +2 -0
- package/dist/tooling/cli/installation/index.js +1 -0
- package/dist/tooling/cli/installation/observation.d.ts +10 -0
- package/dist/tooling/cli/installation/observation.js +44 -0
- package/dist/tooling/cli/installation/reconcile.d.ts +32 -0
- package/dist/tooling/cli/installation/reconcile.js +122 -0
- package/dist/tooling/cli/orchestrate.js +88 -45
- package/dist/tooling/cli/project.d.ts +17 -0
- package/dist/tooling/cli/project.js +18 -0
- package/dist/tooling/cli/test.d.ts +12 -0
- package/dist/tooling/cli/test.js +47 -0
- package/dist/tooling/cli/upgrade/index.d.ts +6 -0
- package/dist/tooling/cli/upgrade/index.js +115 -0
- package/dist/tooling/cli/upgrade/manifest.d.ts +18 -0
- package/dist/tooling/cli/upgrade/manifest.js +77 -0
- package/dist/tooling/cli/upgrade/process.d.ts +2 -0
- package/dist/tooling/cli/upgrade/process.js +57 -0
- package/dist/tooling/linter/adapters/typescript/imports.js +2 -0
- package/dist/tooling/linter/adapters/typescript/index.d.ts +1 -0
- package/dist/tooling/linter/adapters/typescript/index.js +1 -0
- package/dist/tooling/linter/adapters/typescript/query-collection-type.js +4 -51
- package/dist/tooling/linter/adapters/typescript/type-analysis.d.ts +9 -0
- package/dist/tooling/linter/adapters/typescript/type-analysis.js +55 -0
- package/dist/tooling/linter/implementations/source/callable-requirements.d.ts +28 -0
- package/dist/tooling/linter/implementations/source/callable-requirements.js +234 -0
- package/dist/tooling/linter/implementations/source/dependencies.d.ts +2 -0
- package/dist/tooling/linter/implementations/source/dependencies.js +219 -0
- package/dist/tooling/linter/implementations/source/global.js +52 -2
- package/dist/tooling/linter/implementations/source/mutations.js +520 -38
- package/dist/tooling/linter/implementations/source/providers.js +19 -164
- package/dist/tooling/linter/implementations/source/schema.js +454 -2
- package/dist/tooling/linter/implementations/source/verifiers.js +2 -0
- package/dist/tooling/linter/implementations/source/workflows.js +8 -35
- package/dist/tooling/linter/policy/generated.js +2 -2
- package/dist/tooling/linter/requirements/registry.js +9 -3
- package/dist/tooling/packaging/declarations/normalize.js +3 -38
- package/dist/tooling/packaging/declarations/paths.d.ts +5 -0
- package/dist/tooling/packaging/declarations/paths.js +38 -0
- package/dist/tooling/packaging/finalize.d.ts +13 -0
- package/dist/tooling/packaging/finalize.js +62 -0
- package/dist/tooling/packaging/index.d.ts +2 -0
- package/dist/tooling/packaging/index.js +1 -0
- package/dist/tooling/packaging/javascript.d.ts +3 -0
- package/dist/tooling/packaging/javascript.js +45 -2
- package/dist/tooling/packaging/packaging.d.ts +2 -5
- package/dist/tooling/packaging/packaging.js +6 -30
- package/package.json +42 -12
- package/CHANGELOG.md +0 -1506
- package/dist/deployment/adapter/development/context.d.ts +0 -18
- package/dist/deployment/adapter/development/index.d.ts +0 -4
- package/dist/deployment/adapter/development/input.d.ts +0 -6
- package/dist/deployment/adapter/development/placement.d.ts +0 -15
- package/dist/deployment/adapter/development/session.d.ts +0 -9
- /package/dist/{deployment/adapter/development → application/dependency}/index.js +0 -0
- /package/dist/{deployment/adapter/development/context.js → application/dependency/invoker.js} +0 -0
- /package/dist/{deployment/adapter/development/input.js → application/integration/authentication.js} +0 -0
- /package/dist/{deployment/adapter/development/placement.js → application/integration/authentication.typecheck.d.ts} +0 -0
- /package/dist/{deployment/adapter/development/session.js → application/runtime/declarations.js} +0 -0
|
@@ -1,27 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { error, info } from '../log.js';
|
|
1
|
+
import { rm, rmdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { resolveAstraleInstanceIssuer } from '../astrale/instance.js';
|
|
4
|
+
import { resolveCompatibleAstrale } from '../astrale/version.js';
|
|
5
|
+
import { loadPrivateCredentialFile } from '../credential.js';
|
|
6
|
+
import { deprecationWarnings } from '../deprecations.js';
|
|
7
|
+
import { loadPrivateSecretsFile } from '../dotenv.js';
|
|
8
|
+
import { error, info, warn } from '../log.js';
|
|
9
|
+
import { DevelopmentCandidateBuilder, discoverRuntimePath, sameDeploymentCandidate, sameEnvironment, } from './candidate.js';
|
|
10
|
+
import { deployDevelopmentCandidate } from './deployment.js';
|
|
9
11
|
import { DevelopmentLifecycle } from './lifecycle.js';
|
|
10
12
|
import { acquireProjectLock } from './project-lock.js';
|
|
11
13
|
import { LatestRebuild } from './rebuild.js';
|
|
12
|
-
import {
|
|
14
|
+
import { developmentReleaseEvidence } from './release-evidence.js';
|
|
15
|
+
import { reportDevelopmentDeployment } from './report.js';
|
|
16
|
+
import { DevelopmentSessionFileWriter } from './session-file.js';
|
|
13
17
|
import { watchSources } from './source-watch.js';
|
|
14
|
-
|
|
18
|
+
import { acquireDevelopmentTargetLock } from './target-lock.js';
|
|
19
|
+
import { DevelopmentView } from './view.js';
|
|
20
|
+
/** Watch one Project Environment and serialize complete remote deployment generations. */
|
|
15
21
|
export async function develop(input) {
|
|
16
22
|
const lifecycle = new DevelopmentLifecycle();
|
|
17
23
|
let sessionFile;
|
|
18
24
|
let lock;
|
|
19
|
-
let
|
|
25
|
+
let targetLock;
|
|
26
|
+
let view;
|
|
27
|
+
let installationExecutable;
|
|
28
|
+
let installationIssuer;
|
|
20
29
|
let sourceWatch;
|
|
21
30
|
let rebuild;
|
|
31
|
+
let current;
|
|
32
|
+
let lastEvidence;
|
|
22
33
|
let failure;
|
|
23
|
-
|
|
24
|
-
let watcherFailure;
|
|
34
|
+
const cleanup = [];
|
|
25
35
|
try {
|
|
26
36
|
if (input.sessionFile !== undefined) {
|
|
27
37
|
sessionFile = await DevelopmentSessionFileWriter.create(input.sessionFile);
|
|
@@ -33,103 +43,110 @@ export async function develop(input) {
|
|
|
33
43
|
const overrideSecrets = input.secretsFile === undefined
|
|
34
44
|
? undefined
|
|
35
45
|
: Object.freeze(loadPrivateSecretsFile(input.secretsFile));
|
|
46
|
+
const credential = input.credentialFile === undefined
|
|
47
|
+
? undefined
|
|
48
|
+
: loadPrivateCredentialFile(input.credentialFile);
|
|
36
49
|
const runtimePath = await discoverRuntimePath(input.configPath);
|
|
37
|
-
const builder = new
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
let rebuildActive = false;
|
|
42
|
-
let updatePrevious;
|
|
43
|
-
let placementSequence = 0;
|
|
44
|
-
const publishSessionPhase = async () => {
|
|
45
|
-
if (sessionFile === undefined || sessionEvidence === undefined)
|
|
46
|
-
return;
|
|
47
|
-
await sessionFile.transition(placementReady ? (rebuildActive ? 'updating' : 'ready') : 'recovering', sessionEvidence);
|
|
48
|
-
};
|
|
49
|
-
const adapter = current.adapter;
|
|
50
|
-
const parameters = current.parameters;
|
|
51
|
-
let restartReported = false;
|
|
52
|
-
info(`Domain: ${current.artifact.build.schema.compiled.root.origin}`);
|
|
53
|
-
session = await adapter.develop(parameters, {
|
|
54
|
-
projectDir: input.projectDir,
|
|
55
|
-
environment: input.environment,
|
|
56
|
-
artifact: current.artifact,
|
|
57
|
-
secrets: current.secrets,
|
|
58
|
-
overrides: input.overrides,
|
|
59
|
-
signal: lifecycle.signal,
|
|
60
|
-
async onRecovering() {
|
|
61
|
-
placementReady = false;
|
|
62
|
-
await publishSessionPhase();
|
|
63
|
-
},
|
|
64
|
-
async onPlacement(placement) {
|
|
65
|
-
if (sessionFile !== undefined) {
|
|
66
|
-
sessionEvidence = coherentSessionEvidence(updatePrevious === undefined ? [current.artifact] : [current.artifact, updatePrevious], placement);
|
|
67
|
-
placementReady = true;
|
|
68
|
-
placementSequence += 1;
|
|
69
|
-
await publishSessionPhase();
|
|
70
|
-
}
|
|
71
|
-
info(`Public: ${placement.releaseUrl}`);
|
|
72
|
-
if (placement.localUrl !== undefined)
|
|
73
|
-
info(`Runtime: ${placement.localUrl}`);
|
|
74
|
-
},
|
|
50
|
+
const builder = new DevelopmentCandidateBuilder({
|
|
51
|
+
...input,
|
|
52
|
+
runtimePath,
|
|
53
|
+
overrideSecrets,
|
|
75
54
|
});
|
|
55
|
+
current = await builder.prepare(lifecycle.signal);
|
|
56
|
+
if (credential !== undefined && current.installation?.identity !== undefined) {
|
|
57
|
+
throw new TypeError('--credential-file cannot be combined with the Environment installation identity.');
|
|
58
|
+
}
|
|
59
|
+
if (sessionFile !== undefined && (current.installation === undefined || input.deployOnly)) {
|
|
60
|
+
throw new TypeError('--session-file requires an Environment installation that is active for this development session.');
|
|
61
|
+
}
|
|
62
|
+
info(`Domain: ${current.artifact.build.schema.compiled.root.origin}`);
|
|
63
|
+
for (const warning of deprecationWarnings(current.artifact.build))
|
|
64
|
+
warn(warning);
|
|
65
|
+
if (current.installation !== undefined && !input.deployOnly) {
|
|
66
|
+
installationExecutable = await resolveCompatibleAstrale({
|
|
67
|
+
projectDir: input.projectDir,
|
|
68
|
+
signal: lifecycle.signal,
|
|
69
|
+
});
|
|
70
|
+
installationIssuer = await resolveAstraleInstanceIssuer({
|
|
71
|
+
executable: installationExecutable,
|
|
72
|
+
projectDir: input.projectDir,
|
|
73
|
+
instance: current.installation.instance,
|
|
74
|
+
signal: lifecycle.signal,
|
|
75
|
+
});
|
|
76
|
+
targetLock = await acquireDevelopmentTargetLock({
|
|
77
|
+
issuer: installationIssuer,
|
|
78
|
+
origin: current.artifact.build.schema.compiled.root.origin,
|
|
79
|
+
});
|
|
80
|
+
view = new DevelopmentView({
|
|
81
|
+
executable: installationExecutable,
|
|
82
|
+
projectDir: input.projectDir,
|
|
83
|
+
instance: current.installation.instance,
|
|
84
|
+
...(credential === undefined
|
|
85
|
+
? { identity: input.identity ?? current.installation.identity }
|
|
86
|
+
: { credential }),
|
|
87
|
+
});
|
|
88
|
+
if (current.artifact.build.frontend !== undefined)
|
|
89
|
+
await view.prepare(lifecycle.signal);
|
|
90
|
+
}
|
|
91
|
+
const first = await deployDevelopmentCandidate(current, { ...input, credential, installationExecutable }, lifecycle.signal);
|
|
92
|
+
lastEvidence =
|
|
93
|
+
first.installation === undefined ? undefined : developmentReleaseEvidence(first.installation);
|
|
94
|
+
await sessionFile?.transition('ready', lastEvidence);
|
|
95
|
+
reportDevelopmentDeployment(first.deployment, first.installation, current.adapter, input);
|
|
96
|
+
await refreshView(view, first.deployment.release, lifecycle.signal);
|
|
97
|
+
let restartReported = false;
|
|
76
98
|
rebuild = new LatestRebuild({
|
|
77
99
|
async prepare(_ignored, signal) {
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
info(`Rebuilding: ${input.environment}`);
|
|
101
|
+
if (lastEvidence !== undefined)
|
|
102
|
+
await sessionFile?.transition('updating', lastEvidence);
|
|
80
103
|
return builder.prepare(signal);
|
|
81
104
|
},
|
|
82
|
-
async commit(candidate) {
|
|
83
|
-
if (candidate
|
|
84
|
-
candidate.adapter.version !== adapter.version ||
|
|
85
|
-
stable(candidate.parameters) !== stable(parameters)) {
|
|
105
|
+
async commit(candidate, signal) {
|
|
106
|
+
if (!sameEnvironment(current, candidate)) {
|
|
86
107
|
restartReported = true;
|
|
87
|
-
throw new Error('
|
|
108
|
+
throw new Error('Project Environment configuration changed; restart pnpm dev to apply it.');
|
|
88
109
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
current = candidate;
|
|
93
|
-
try {
|
|
94
|
-
await session.update({ artifact: candidate.artifact, secrets: candidate.secrets });
|
|
95
|
-
if (sessionFile !== undefined) {
|
|
96
|
-
if (placementSequence === beforePlacement || sessionEvidence === undefined) {
|
|
97
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_EVIDENCE_INCOHERENT', 'Development adapter completed an update without reporting installed Release evidence.');
|
|
98
|
-
}
|
|
99
|
-
assertEvidenceMatches(candidate.artifact, sessionEvidence);
|
|
100
|
-
}
|
|
101
|
-
rebuildActive = false;
|
|
102
|
-
await publishSessionPhase();
|
|
110
|
+
if (sameDeploymentCandidate(current, candidate)) {
|
|
111
|
+
current = candidate;
|
|
112
|
+
await sessionFile?.transition('ready', lastEvidence);
|
|
103
113
|
sourceWatch?.update(candidate.sources);
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
catch (cause) {
|
|
107
|
-
current = previous;
|
|
108
|
-
if (sessionFile !== undefined &&
|
|
109
|
-
sessionEvidence !== undefined &&
|
|
110
|
-
!evidenceMatches(previous.artifact, sessionEvidence)) {
|
|
111
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_EVIDENCE_INCOHERENT', 'Development adapter rejected an update without restoring prior installed Release evidence.', { cause });
|
|
112
|
-
}
|
|
113
|
-
throw cause;
|
|
114
|
+
return;
|
|
114
115
|
}
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
if (installationIssuer !== undefined && candidate.installation !== undefined) {
|
|
117
|
+
await resolveAstraleInstanceIssuer({
|
|
118
|
+
executable: installationExecutable,
|
|
119
|
+
projectDir: input.projectDir,
|
|
120
|
+
instance: candidate.installation.instance,
|
|
121
|
+
expectedIssuer: installationIssuer,
|
|
122
|
+
signal,
|
|
123
|
+
});
|
|
117
124
|
}
|
|
125
|
+
if (candidate.artifact.build.frontend !== undefined)
|
|
126
|
+
await view?.prepare(signal);
|
|
127
|
+
const deployed = await deployDevelopmentCandidate(candidate, { ...input, credential, installationExecutable }, signal);
|
|
128
|
+
current = candidate;
|
|
129
|
+
lastEvidence =
|
|
130
|
+
deployed.installation === undefined
|
|
131
|
+
? undefined
|
|
132
|
+
: developmentReleaseEvidence(deployed.installation);
|
|
133
|
+
await sessionFile?.transition('ready', lastEvidence);
|
|
134
|
+
sourceWatch?.update(candidate.sources);
|
|
135
|
+
info(`Updated: ${candidate.artifact.build.schema.compiled.root.revision}`);
|
|
136
|
+
reportDevelopmentDeployment(deployed.deployment, deployed.installation, candidate.adapter, input);
|
|
137
|
+
await refreshView(view, deployed.deployment.release, signal);
|
|
118
138
|
},
|
|
119
139
|
async failed(cause) {
|
|
120
|
-
rebuildActive = false;
|
|
121
|
-
if (cause instanceof DevelopmentSessionFileError) {
|
|
122
|
-
watcherFailure = cause;
|
|
123
|
-
lifecycle.stop(cause);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
140
|
error(cause instanceof Error ? cause.message : String(cause));
|
|
141
|
+
if (lastEvidence === undefined)
|
|
142
|
+
return;
|
|
127
143
|
try {
|
|
128
|
-
await
|
|
144
|
+
await sessionFile?.transition('recovering', lastEvidence);
|
|
129
145
|
}
|
|
130
146
|
catch (sessionCause) {
|
|
131
|
-
|
|
132
|
-
|
|
147
|
+
const terminal = new AggregateError([cause, sessionCause], 'Development rebuild failed and session evidence could not be recovered.');
|
|
148
|
+
failure ??= terminal;
|
|
149
|
+
lifecycle.stop(terminal);
|
|
133
150
|
}
|
|
134
151
|
},
|
|
135
152
|
});
|
|
@@ -142,46 +159,38 @@ export async function develop(input) {
|
|
|
142
159
|
if (restartReported)
|
|
143
160
|
return;
|
|
144
161
|
restartReported = true;
|
|
145
|
-
error('
|
|
162
|
+
error('Project Environment configuration changed; restart pnpm dev to apply it.');
|
|
146
163
|
},
|
|
147
164
|
onError: (cause) => {
|
|
148
|
-
|
|
165
|
+
failure = cause;
|
|
149
166
|
lifecycle.stop(cause);
|
|
150
167
|
},
|
|
151
168
|
});
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
]);
|
|
158
|
-
if (completed === 'session' && !lifecycle.signal.aborted) {
|
|
159
|
-
throw new Error('Development provider stopped unexpectedly.');
|
|
160
|
-
}
|
|
161
|
-
if (watcherFailure !== undefined)
|
|
162
|
-
throw watcherFailure;
|
|
169
|
+
info('Ready: watching for remote deployments');
|
|
170
|
+
// Edits made while the first build/deployment was in flight predate this watcher.
|
|
171
|
+
// Catch up once; artifact deduplication prevents an unchanged second deployment.
|
|
172
|
+
rebuild.invalidate();
|
|
173
|
+
await lifecycle.stopped;
|
|
163
174
|
}
|
|
164
175
|
catch (cause) {
|
|
165
|
-
failed = true;
|
|
166
176
|
failure = cause;
|
|
167
177
|
}
|
|
168
178
|
lifecycle.stop(failure);
|
|
169
|
-
const cleanup = [];
|
|
170
179
|
try {
|
|
171
|
-
await sessionFile?.transition('stopping');
|
|
180
|
+
await sessionFile?.transition('stopping', lastEvidence);
|
|
172
181
|
}
|
|
173
182
|
catch (cause) {
|
|
174
|
-
failed = true;
|
|
175
183
|
failure ??= cause;
|
|
176
184
|
}
|
|
177
185
|
for (const operation of [
|
|
178
186
|
() => sourceWatch?.stop(),
|
|
179
187
|
() => rebuild?.stop(failure),
|
|
180
|
-
() =>
|
|
188
|
+
() => view?.close(AbortSignal.timeout(30_000)),
|
|
181
189
|
() => rm(join(input.projectDir, '.astrale', 'development', input.environment, 'source'), {
|
|
182
190
|
recursive: true,
|
|
183
191
|
force: true,
|
|
184
192
|
}),
|
|
193
|
+
() => targetLock?.release(),
|
|
185
194
|
() => lock?.release(),
|
|
186
195
|
]) {
|
|
187
196
|
try {
|
|
@@ -205,13 +214,13 @@ export async function develop(input) {
|
|
|
205
214
|
}
|
|
206
215
|
}
|
|
207
216
|
try {
|
|
208
|
-
await sessionFile?.transition(
|
|
217
|
+
await sessionFile?.transition(failure === undefined && cleanup.length === 0 ? 'stopped' : 'failed');
|
|
209
218
|
}
|
|
210
219
|
catch (cause) {
|
|
211
220
|
cleanup.push(cause);
|
|
212
221
|
}
|
|
213
222
|
lifecycle.dispose();
|
|
214
|
-
if (
|
|
223
|
+
if (failure !== undefined) {
|
|
215
224
|
if (cleanup.length > 0)
|
|
216
225
|
error(new AggregateError(cleanup, 'Development cleanup failed.').message);
|
|
217
226
|
throw failure;
|
|
@@ -220,185 +229,15 @@ export async function develop(input) {
|
|
|
220
229
|
throw new AggregateError(cleanup, 'Development cleanup failed.');
|
|
221
230
|
return 0;
|
|
222
231
|
}
|
|
223
|
-
function
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_EVIDENCE_INCOHERENT', '--session-file requires an adapter that reports exact installed Release evidence.');
|
|
227
|
-
}
|
|
228
|
-
let issuer;
|
|
229
|
-
try {
|
|
230
|
-
issuer = new URL(placement.releaseUrl).origin;
|
|
231
|
-
}
|
|
232
|
-
catch (cause) {
|
|
233
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_EVIDENCE_INCOHERENT', 'Development adapter reported an invalid Release URL.', { cause });
|
|
234
|
-
}
|
|
235
|
-
if (placement.releaseUrl !== issuer) {
|
|
236
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_EVIDENCE_INCOHERENT', 'Development adapter reported a non-canonical Release URL.');
|
|
237
|
-
}
|
|
238
|
-
let matches = false;
|
|
232
|
+
async function refreshView(view, release, signal) {
|
|
233
|
+
if (view === undefined)
|
|
234
|
+
return;
|
|
239
235
|
try {
|
|
240
|
-
|
|
236
|
+
const pageUrl = await view.refresh(release, signal);
|
|
237
|
+
if (pageUrl !== undefined)
|
|
238
|
+
info(`View: ${pageUrl}`);
|
|
241
239
|
}
|
|
242
240
|
catch (cause) {
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
if (evidence.issuer !== issuer || !matches) {
|
|
246
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_EVIDENCE_INCOHERENT', 'Development adapter installed Release evidence does not match the current artifact and placement.');
|
|
247
|
-
}
|
|
248
|
-
return evidence;
|
|
249
|
-
}
|
|
250
|
-
function assertEvidenceMatches(artifact, evidence) {
|
|
251
|
-
if (!evidenceMatches(artifact, evidence)) {
|
|
252
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_EVIDENCE_INCOHERENT', 'Development adapter installed Release evidence does not match the committed artifact.');
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
function evidenceMatches(artifact, evidence) {
|
|
256
|
-
const root = artifact.build.schema.compiled.root;
|
|
257
|
-
const release = assemble(artifact.build, addressing(evidence.issuer));
|
|
258
|
-
return (evidence.origin === root.origin &&
|
|
259
|
-
evidence.revision === root.revision &&
|
|
260
|
-
evidence.etag === release.publication.etag);
|
|
261
|
-
}
|
|
262
|
-
class ProjectBuilder {
|
|
263
|
-
#configPath;
|
|
264
|
-
#projectDir;
|
|
265
|
-
#environment;
|
|
266
|
-
#runtimePath;
|
|
267
|
-
#overrideSecrets;
|
|
268
|
-
#generation = 0;
|
|
269
|
-
constructor(input) {
|
|
270
|
-
this.#configPath = input.configPath;
|
|
271
|
-
this.#projectDir = input.projectDir;
|
|
272
|
-
this.#environment = input.environment;
|
|
273
|
-
this.#runtimePath = input.runtimePath;
|
|
274
|
-
this.#overrideSecrets = input.overrideSecrets;
|
|
275
|
-
}
|
|
276
|
-
async prepare(signal) {
|
|
277
|
-
throwIfAborted(signal);
|
|
278
|
-
const directory = join(this.#projectDir, '.astrale', 'development', this.#environment, 'source', String(++this.#generation));
|
|
279
|
-
await mkdir(directory, { recursive: true });
|
|
280
|
-
const bridge = join(directory, 'bridge.ts');
|
|
281
|
-
const configImport = moduleSpecifier(dirname(bridge), this.#configPath);
|
|
282
|
-
const runtimeImport = moduleSpecifier(dirname(bridge), resolve(dirname(this.#configPath), this.#runtimePath));
|
|
283
|
-
await writeFile(bridge, `export { default as deployment } from ${JSON.stringify(configImport)}\n` +
|
|
284
|
-
`export { default as runtime } from ${JSON.stringify(runtimeImport)}\n`);
|
|
285
|
-
try {
|
|
286
|
-
const built = await bun().build({
|
|
287
|
-
entrypoints: [bridge],
|
|
288
|
-
outdir: directory,
|
|
289
|
-
naming: 'application.mjs',
|
|
290
|
-
target: 'bun',
|
|
291
|
-
format: 'esm',
|
|
292
|
-
packages: 'external',
|
|
293
|
-
splitting: false,
|
|
294
|
-
sourcemap: 'inline',
|
|
295
|
-
metafile: true,
|
|
296
|
-
});
|
|
297
|
-
throwIfAborted(signal);
|
|
298
|
-
const output = built.outputs.find((candidate) => candidate.path.endsWith('application.mjs'));
|
|
299
|
-
if (output === undefined)
|
|
300
|
-
throw new Error('Authored Application rebuild produced no module.');
|
|
301
|
-
const loaded = (await import(`${pathToFileURL(output.path).href}?development=${this.#generation}`));
|
|
302
|
-
if (Object.keys(loaded).some((key) => key !== 'deployment' && key !== 'runtime')) {
|
|
303
|
-
throw new TypeError('Development bridge produced unexpected exports.');
|
|
304
|
-
}
|
|
305
|
-
const deployment = loaded.deployment;
|
|
306
|
-
if (!isDeployment(deployment)) {
|
|
307
|
-
throw new TypeError('astrale.config.ts default export must be created by deploy().');
|
|
308
|
-
}
|
|
309
|
-
const admitted = deployment;
|
|
310
|
-
const resolved = await resolveRuntime(admitted.entrypoint, async (path) => {
|
|
311
|
-
if (path !== this.#runtimePath) {
|
|
312
|
-
throw new Error('Runtime entrypoint changed; restart pnpm dev to apply it.');
|
|
313
|
-
}
|
|
314
|
-
return Object.freeze({ default: loaded.runtime });
|
|
315
|
-
});
|
|
316
|
-
const build = compile(admitted.application);
|
|
317
|
-
admitRuntime({ runtime: build.runtime }, resolved);
|
|
318
|
-
const adapter = admitted.adapter;
|
|
319
|
-
const parameters = adapter.parameters(this.#environment);
|
|
320
|
-
const source = await adapter.prepare(parameters, {
|
|
321
|
-
projectDir: this.#projectDir,
|
|
322
|
-
environment: this.#environment,
|
|
323
|
-
mode: 'development',
|
|
324
|
-
build,
|
|
325
|
-
runtime: resolved,
|
|
326
|
-
});
|
|
327
|
-
const artifact = verifyPreflight({ build, runtime: resolved, source });
|
|
328
|
-
const declared = this.#overrideSecrets === undefined
|
|
329
|
-
? secretsFor(adapter, parameters, this.#projectDir, resolved.runtime)
|
|
330
|
-
: { values: this.#overrideSecrets };
|
|
331
|
-
const sources = new Set();
|
|
332
|
-
for (const path of Object.keys(built.metafile?.inputs ?? {})) {
|
|
333
|
-
const absolute = isAbsolute(path) ? path : resolve(this.#projectDir, path);
|
|
334
|
-
if (!absolute.startsWith(`${resolve(this.#projectDir)}${sep}`))
|
|
335
|
-
continue;
|
|
336
|
-
if (absolute.includes(`${sep}.astrale${sep}`))
|
|
337
|
-
continue;
|
|
338
|
-
sources.add(absolute);
|
|
339
|
-
}
|
|
340
|
-
if (declared.path !== undefined)
|
|
341
|
-
sources.add(declared.path);
|
|
342
|
-
return Object.freeze({
|
|
343
|
-
adapter,
|
|
344
|
-
parameters,
|
|
345
|
-
artifact,
|
|
346
|
-
secrets: declared.values,
|
|
347
|
-
sources,
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
finally {
|
|
351
|
-
await rm(directory, { recursive: true, force: true });
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
async function discoverRuntimePath(configPath) {
|
|
356
|
-
const loaded = (await import(`${pathToFileURL(configPath).href}?discover=${Date.now()}`));
|
|
357
|
-
if (Object.keys(loaded).length !== 1 || !Object.hasOwn(loaded, 'default')) {
|
|
358
|
-
throw new TypeError('astrale.config.ts must export exactly one default Deployment.');
|
|
359
|
-
}
|
|
360
|
-
if (!isDeployment(loaded.default)) {
|
|
361
|
-
throw new TypeError('Default export must be created by deploy().');
|
|
362
|
-
}
|
|
363
|
-
return loaded.default.entrypoint.path;
|
|
364
|
-
}
|
|
365
|
-
function secretsFor(adapter, parameters, projectDir, runtime) {
|
|
366
|
-
const file = adapter.secretsFile?.(parameters);
|
|
367
|
-
if (file === undefined)
|
|
368
|
-
return { values: Object.freeze({}) };
|
|
369
|
-
const path = isAbsolute(file) ? file : join(projectDir, file);
|
|
370
|
-
// An Integration-free Runtime has no Providers and therefore no author-owned
|
|
371
|
-
// environment secrets. Adapter-owned secrets, such as the signing identity,
|
|
372
|
-
// are resolved separately by the adapter and must not make this file required.
|
|
373
|
-
if (Object.keys(runtime.integrations).length === 0 && !existsSync(path)) {
|
|
374
|
-
return { values: Object.freeze({}) };
|
|
375
|
-
}
|
|
376
|
-
return { values: Object.freeze(loadDeclaredSecrets(path, file)), path };
|
|
377
|
-
}
|
|
378
|
-
function bun() {
|
|
379
|
-
const value = Reflect.get(globalThis, 'Bun');
|
|
380
|
-
if (value === undefined || typeof value.build !== 'function') {
|
|
381
|
-
throw new TypeError('Domain development requires the Bun runtime.');
|
|
382
|
-
}
|
|
383
|
-
return value;
|
|
384
|
-
}
|
|
385
|
-
function moduleSpecifier(from, target) {
|
|
386
|
-
const path = relative(from, target).split(sep).join('/');
|
|
387
|
-
return path.startsWith('.') ? path : `./${path}`;
|
|
388
|
-
}
|
|
389
|
-
function stable(input) {
|
|
390
|
-
if (input === null || typeof input !== 'object')
|
|
391
|
-
return JSON.stringify(input);
|
|
392
|
-
if (Array.isArray(input))
|
|
393
|
-
return `[${input.map(stable).join(',')}]`;
|
|
394
|
-
const record = input;
|
|
395
|
-
return `{${Object.keys(record)
|
|
396
|
-
.sort()
|
|
397
|
-
.map((key) => `${JSON.stringify(key)}:${stable(record[key])}`)
|
|
398
|
-
.join(',')}}`;
|
|
399
|
-
}
|
|
400
|
-
function throwIfAborted(signal) {
|
|
401
|
-
if (signal.aborted) {
|
|
402
|
-
throw signal.reason instanceof Error ? signal.reason : new Error('Development interrupted.');
|
|
241
|
+
error(`View unavailable: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
403
242
|
}
|
|
404
243
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class DevelopmentLeaseError extends Error {
|
|
2
|
+
readonly code: 'DEVELOPMENT_LEASE_LOCKED' | 'DEVELOPMENT_LEASE_LOST';
|
|
3
|
+
readonly name = "DevelopmentLeaseError";
|
|
4
|
+
constructor(code: 'DEVELOPMENT_LEASE_LOCKED' | 'DEVELOPMENT_LEASE_LOST', message: string, options?: ErrorOptions);
|
|
5
|
+
}
|
|
6
|
+
export interface DevelopmentLease {
|
|
7
|
+
readonly path: string;
|
|
8
|
+
readonly recovered: boolean;
|
|
9
|
+
release(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
/** One fail-closed filesystem lease engine for every local development coordinate. */
|
|
12
|
+
export declare function acquireDevelopmentLease(input: {
|
|
13
|
+
readonly directory: string;
|
|
14
|
+
readonly coordinate: string;
|
|
15
|
+
readonly pid?: number;
|
|
16
|
+
readonly sessionId?: string;
|
|
17
|
+
readonly processAlive?: (pid: number) => boolean;
|
|
18
|
+
}): Promise<DevelopmentLease>;
|