@astrale-os/sdk 0.5.0-beta.99 → 0.6.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +4 -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/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 +125 -289
- 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 +84 -44
- 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,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { loadDeclaredSecrets, loadPrivateSecretsFile } from '../dotenv.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 { loadPrivateSecretsFile } from '../dotenv.js';
|
|
8
7
|
import { error, info } from '../log.js';
|
|
8
|
+
import { DevelopmentCandidateBuilder, discoverRuntimePath, sameDeploymentCandidate, sameEnvironment, } from './candidate.js';
|
|
9
|
+
import { deployDevelopmentCandidate } from './deployment.js';
|
|
9
10
|
import { DevelopmentLifecycle } from './lifecycle.js';
|
|
10
11
|
import { acquireProjectLock } from './project-lock.js';
|
|
11
12
|
import { LatestRebuild } from './rebuild.js';
|
|
12
|
-
import {
|
|
13
|
+
import { developmentReleaseEvidence } from './release-evidence.js';
|
|
14
|
+
import { reportDevelopmentDeployment } from './report.js';
|
|
15
|
+
import { DevelopmentSessionFileWriter } from './session-file.js';
|
|
13
16
|
import { watchSources } from './source-watch.js';
|
|
14
|
-
|
|
17
|
+
import { acquireDevelopmentTargetLock } from './target-lock.js';
|
|
18
|
+
import { DevelopmentView } from './view.js';
|
|
19
|
+
/** Watch one Project Environment and serialize complete remote deployment generations. */
|
|
15
20
|
export async function develop(input) {
|
|
16
21
|
const lifecycle = new DevelopmentLifecycle();
|
|
17
22
|
let sessionFile;
|
|
18
23
|
let lock;
|
|
19
|
-
let
|
|
24
|
+
let targetLock;
|
|
25
|
+
let view;
|
|
26
|
+
let installationExecutable;
|
|
27
|
+
let installationIssuer;
|
|
20
28
|
let sourceWatch;
|
|
21
29
|
let rebuild;
|
|
30
|
+
let current;
|
|
31
|
+
let lastEvidence;
|
|
22
32
|
let failure;
|
|
23
|
-
|
|
24
|
-
let watcherFailure;
|
|
33
|
+
const cleanup = [];
|
|
25
34
|
try {
|
|
26
35
|
if (input.sessionFile !== undefined) {
|
|
27
36
|
sessionFile = await DevelopmentSessionFileWriter.create(input.sessionFile);
|
|
@@ -33,103 +42,108 @@ export async function develop(input) {
|
|
|
33
42
|
const overrideSecrets = input.secretsFile === undefined
|
|
34
43
|
? undefined
|
|
35
44
|
: Object.freeze(loadPrivateSecretsFile(input.secretsFile));
|
|
45
|
+
const credential = input.credentialFile === undefined
|
|
46
|
+
? undefined
|
|
47
|
+
: loadPrivateCredentialFile(input.credentialFile);
|
|
36
48
|
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
|
-
},
|
|
49
|
+
const builder = new DevelopmentCandidateBuilder({
|
|
50
|
+
...input,
|
|
51
|
+
runtimePath,
|
|
52
|
+
overrideSecrets,
|
|
75
53
|
});
|
|
54
|
+
current = await builder.prepare(lifecycle.signal);
|
|
55
|
+
if (credential !== undefined && current.installation?.identity !== undefined) {
|
|
56
|
+
throw new TypeError('--credential-file cannot be combined with the Environment installation identity.');
|
|
57
|
+
}
|
|
58
|
+
if (sessionFile !== undefined && (current.installation === undefined || input.deployOnly)) {
|
|
59
|
+
throw new TypeError('--session-file requires an Environment installation that is active for this development session.');
|
|
60
|
+
}
|
|
61
|
+
info(`Domain: ${current.artifact.build.schema.compiled.root.origin}`);
|
|
62
|
+
if (current.installation !== undefined && !input.deployOnly) {
|
|
63
|
+
installationExecutable = await resolveCompatibleAstrale({
|
|
64
|
+
projectDir: input.projectDir,
|
|
65
|
+
signal: lifecycle.signal,
|
|
66
|
+
});
|
|
67
|
+
installationIssuer = await resolveAstraleInstanceIssuer({
|
|
68
|
+
executable: installationExecutable,
|
|
69
|
+
projectDir: input.projectDir,
|
|
70
|
+
instance: current.installation.instance,
|
|
71
|
+
signal: lifecycle.signal,
|
|
72
|
+
});
|
|
73
|
+
targetLock = await acquireDevelopmentTargetLock({
|
|
74
|
+
issuer: installationIssuer,
|
|
75
|
+
origin: current.artifact.build.schema.compiled.root.origin,
|
|
76
|
+
});
|
|
77
|
+
view = new DevelopmentView({
|
|
78
|
+
executable: installationExecutable,
|
|
79
|
+
projectDir: input.projectDir,
|
|
80
|
+
instance: current.installation.instance,
|
|
81
|
+
...(credential === undefined
|
|
82
|
+
? { identity: input.identity ?? current.installation.identity }
|
|
83
|
+
: { credential }),
|
|
84
|
+
});
|
|
85
|
+
if (current.artifact.build.frontend !== undefined)
|
|
86
|
+
await view.prepare(lifecycle.signal);
|
|
87
|
+
}
|
|
88
|
+
const first = await deployDevelopmentCandidate(current, { ...input, credential, installationExecutable }, lifecycle.signal);
|
|
89
|
+
lastEvidence =
|
|
90
|
+
first.installation === undefined ? undefined : developmentReleaseEvidence(first.installation);
|
|
91
|
+
await sessionFile?.transition('ready', lastEvidence);
|
|
92
|
+
reportDevelopmentDeployment(first.deployment, first.installation, current.adapter, input);
|
|
93
|
+
await refreshView(view, first.deployment.release, lifecycle.signal);
|
|
94
|
+
let restartReported = false;
|
|
76
95
|
rebuild = new LatestRebuild({
|
|
77
96
|
async prepare(_ignored, signal) {
|
|
78
|
-
|
|
79
|
-
|
|
97
|
+
info(`Rebuilding: ${input.environment}`);
|
|
98
|
+
if (lastEvidence !== undefined)
|
|
99
|
+
await sessionFile?.transition('updating', lastEvidence);
|
|
80
100
|
return builder.prepare(signal);
|
|
81
101
|
},
|
|
82
|
-
async commit(candidate) {
|
|
83
|
-
if (candidate
|
|
84
|
-
candidate.adapter.version !== adapter.version ||
|
|
85
|
-
stable(candidate.parameters) !== stable(parameters)) {
|
|
102
|
+
async commit(candidate, signal) {
|
|
103
|
+
if (!sameEnvironment(current, candidate)) {
|
|
86
104
|
restartReported = true;
|
|
87
|
-
throw new Error('
|
|
105
|
+
throw new Error('Project Environment configuration changed; restart pnpm dev to apply it.');
|
|
88
106
|
}
|
|
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();
|
|
107
|
+
if (sameDeploymentCandidate(current, candidate)) {
|
|
108
|
+
current = candidate;
|
|
109
|
+
await sessionFile?.transition('ready', lastEvidence);
|
|
103
110
|
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;
|
|
111
|
+
return;
|
|
114
112
|
}
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
if (installationIssuer !== undefined && candidate.installation !== undefined) {
|
|
114
|
+
await resolveAstraleInstanceIssuer({
|
|
115
|
+
executable: installationExecutable,
|
|
116
|
+
projectDir: input.projectDir,
|
|
117
|
+
instance: candidate.installation.instance,
|
|
118
|
+
expectedIssuer: installationIssuer,
|
|
119
|
+
signal,
|
|
120
|
+
});
|
|
117
121
|
}
|
|
122
|
+
if (candidate.artifact.build.frontend !== undefined)
|
|
123
|
+
await view?.prepare(signal);
|
|
124
|
+
const deployed = await deployDevelopmentCandidate(candidate, { ...input, credential, installationExecutable }, signal);
|
|
125
|
+
current = candidate;
|
|
126
|
+
lastEvidence =
|
|
127
|
+
deployed.installation === undefined
|
|
128
|
+
? undefined
|
|
129
|
+
: developmentReleaseEvidence(deployed.installation);
|
|
130
|
+
await sessionFile?.transition('ready', lastEvidence);
|
|
131
|
+
sourceWatch?.update(candidate.sources);
|
|
132
|
+
info(`Updated: ${candidate.artifact.build.schema.compiled.root.revision}`);
|
|
133
|
+
reportDevelopmentDeployment(deployed.deployment, deployed.installation, candidate.adapter, input);
|
|
134
|
+
await refreshView(view, deployed.deployment.release, signal);
|
|
118
135
|
},
|
|
119
136
|
async failed(cause) {
|
|
120
|
-
rebuildActive = false;
|
|
121
|
-
if (cause instanceof DevelopmentSessionFileError) {
|
|
122
|
-
watcherFailure = cause;
|
|
123
|
-
lifecycle.stop(cause);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
137
|
error(cause instanceof Error ? cause.message : String(cause));
|
|
138
|
+
if (lastEvidence === undefined)
|
|
139
|
+
return;
|
|
127
140
|
try {
|
|
128
|
-
await
|
|
141
|
+
await sessionFile?.transition('recovering', lastEvidence);
|
|
129
142
|
}
|
|
130
143
|
catch (sessionCause) {
|
|
131
|
-
|
|
132
|
-
|
|
144
|
+
const terminal = new AggregateError([cause, sessionCause], 'Development rebuild failed and session evidence could not be recovered.');
|
|
145
|
+
failure ??= terminal;
|
|
146
|
+
lifecycle.stop(terminal);
|
|
133
147
|
}
|
|
134
148
|
},
|
|
135
149
|
});
|
|
@@ -142,46 +156,38 @@ export async function develop(input) {
|
|
|
142
156
|
if (restartReported)
|
|
143
157
|
return;
|
|
144
158
|
restartReported = true;
|
|
145
|
-
error('
|
|
159
|
+
error('Project Environment configuration changed; restart pnpm dev to apply it.');
|
|
146
160
|
},
|
|
147
161
|
onError: (cause) => {
|
|
148
|
-
|
|
162
|
+
failure = cause;
|
|
149
163
|
lifecycle.stop(cause);
|
|
150
164
|
},
|
|
151
165
|
});
|
|
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;
|
|
166
|
+
info('Ready: watching for remote deployments');
|
|
167
|
+
// Edits made while the first build/deployment was in flight predate this watcher.
|
|
168
|
+
// Catch up once; artifact deduplication prevents an unchanged second deployment.
|
|
169
|
+
rebuild.invalidate();
|
|
170
|
+
await lifecycle.stopped;
|
|
163
171
|
}
|
|
164
172
|
catch (cause) {
|
|
165
|
-
failed = true;
|
|
166
173
|
failure = cause;
|
|
167
174
|
}
|
|
168
175
|
lifecycle.stop(failure);
|
|
169
|
-
const cleanup = [];
|
|
170
176
|
try {
|
|
171
|
-
await sessionFile?.transition('stopping');
|
|
177
|
+
await sessionFile?.transition('stopping', lastEvidence);
|
|
172
178
|
}
|
|
173
179
|
catch (cause) {
|
|
174
|
-
failed = true;
|
|
175
180
|
failure ??= cause;
|
|
176
181
|
}
|
|
177
182
|
for (const operation of [
|
|
178
183
|
() => sourceWatch?.stop(),
|
|
179
184
|
() => rebuild?.stop(failure),
|
|
180
|
-
() =>
|
|
185
|
+
() => view?.close(AbortSignal.timeout(30_000)),
|
|
181
186
|
() => rm(join(input.projectDir, '.astrale', 'development', input.environment, 'source'), {
|
|
182
187
|
recursive: true,
|
|
183
188
|
force: true,
|
|
184
189
|
}),
|
|
190
|
+
() => targetLock?.release(),
|
|
185
191
|
() => lock?.release(),
|
|
186
192
|
]) {
|
|
187
193
|
try {
|
|
@@ -205,13 +211,13 @@ export async function develop(input) {
|
|
|
205
211
|
}
|
|
206
212
|
}
|
|
207
213
|
try {
|
|
208
|
-
await sessionFile?.transition(
|
|
214
|
+
await sessionFile?.transition(failure === undefined && cleanup.length === 0 ? 'stopped' : 'failed');
|
|
209
215
|
}
|
|
210
216
|
catch (cause) {
|
|
211
217
|
cleanup.push(cause);
|
|
212
218
|
}
|
|
213
219
|
lifecycle.dispose();
|
|
214
|
-
if (
|
|
220
|
+
if (failure !== undefined) {
|
|
215
221
|
if (cleanup.length > 0)
|
|
216
222
|
error(new AggregateError(cleanup, 'Development cleanup failed.').message);
|
|
217
223
|
throw failure;
|
|
@@ -220,185 +226,15 @@ export async function develop(input) {
|
|
|
220
226
|
throw new AggregateError(cleanup, 'Development cleanup failed.');
|
|
221
227
|
return 0;
|
|
222
228
|
}
|
|
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;
|
|
229
|
+
async function refreshView(view, release, signal) {
|
|
230
|
+
if (view === undefined)
|
|
231
|
+
return;
|
|
239
232
|
try {
|
|
240
|
-
|
|
233
|
+
const pageUrl = await view.refresh(release, signal);
|
|
234
|
+
if (pageUrl !== undefined)
|
|
235
|
+
info(`View: ${pageUrl}`);
|
|
241
236
|
}
|
|
242
237
|
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.');
|
|
238
|
+
error(`View unavailable: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
403
239
|
}
|
|
404
240
|
}
|
|
@@ -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>;
|