@astrale-os/sdk 0.6.0-beta.13 → 0.6.0-beta.15
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 +4 -0
- package/dist/deployment/adapter/adapter.d.ts +9 -11
- package/dist/deployment/adapter/legacy/adapter.d.ts +0 -10
- package/dist/deployment/adapter/legacy/deploy/context.d.ts +0 -2
- package/dist/deployment/adapter/legacy/deploy/result.d.ts +2 -3
- package/dist/deployment/adapter/legacy/index.d.ts +12 -12
- package/dist/deployment/adapter/legacy/prepare/context.d.ts +0 -2
- package/dist/deployment/adapter/release/context.d.ts +23 -3
- package/dist/deployment/adapter/release/index.d.ts +1 -0
- package/dist/deployment/adapter/release/list.d.ts +41 -0
- package/dist/deployment/adapter/release/list.js +1 -0
- package/dist/deployment/address/index.d.ts +1 -1
- package/dist/deployment/address/index.js +1 -0
- package/dist/deployment/address/summary.d.ts +31 -1
- package/dist/deployment/address/summary.js +117 -1
- package/dist/deployment/build/index.d.ts +1 -1
- package/dist/deployment/build/index.js +1 -1
- package/dist/deployment/build/manifest.d.ts +5 -0
- package/dist/deployment/build/manifest.js +10 -0
- package/dist/deployment/index.d.ts +1 -1
- package/dist/deployment/release/legacy/index.d.ts +17 -12
- package/dist/deployment/release/legacy/index.js +17 -12
- package/dist/deployment/verify/readiness/deployment.js +3 -13
- package/dist/deployment/verify/readiness/fetch.d.ts +13 -0
- package/dist/deployment/verify/readiness/fetch.js +26 -0
- package/dist/deployment/verify/readiness/identity.d.ts +3 -6
- package/dist/deployment/verify/readiness/identity.js +3 -3
- package/dist/deployment/verify/readiness/index.d.ts +12 -8
- package/dist/deployment/verify/readiness/index.js +15 -4
- package/dist/deployment/verify/readiness/legacy/index.d.ts +2 -0
- package/dist/deployment/verify/readiness/legacy/index.js +2 -0
- package/dist/deployment/verify/readiness/legacy/publication.d.ts +12 -0
- package/dist/deployment/verify/readiness/legacy/publication.js +23 -0
- package/dist/deployment/verify/readiness/release.d.ts +8 -0
- package/dist/deployment/verify/readiness/release.js +22 -0
- package/dist/execution/identity/authentication.d.ts +14 -3
- package/dist/execution/identity/authentication.js +16 -7
- package/dist/execution/identity/callback.d.ts +5 -2
- package/dist/execution/identity/callback.js +11 -5
- package/dist/execution/identity/delivery.d.ts +11 -4
- package/dist/execution/identity/delivery.js +47 -20
- package/dist/execution/identity/identity.d.ts +12 -6
- package/dist/execution/identity/identity.js +3 -3
- package/dist/execution/invocation/admission/authentication.d.ts +1 -2
- package/dist/execution/invocation/admission/authentication.js +1 -2
- package/dist/execution/invocation/admission/authority.d.ts +10 -4
- package/dist/execution/invocation/admission/authority.js +5 -1
- package/dist/execution/invocation/invocation.js +51 -14
- package/dist/execution/runtime/index.d.ts +1 -0
- package/dist/execution/runtime/index.js +1 -0
- package/dist/execution/runtime/load.d.ts +3 -3
- package/dist/execution/runtime/load.js +3 -2
- package/dist/execution/runtime/release.d.ts +22 -0
- package/dist/execution/runtime/release.js +14 -0
- package/dist/execution/serve.d.ts +2 -2
- package/dist/execution/service/create.js +9 -7
- package/dist/execution/service/release.d.ts +2 -2
- package/dist/execution/service/release.js +3 -2
- package/dist/execution/service/service.d.ts +9 -5
- package/dist/execution/service/serving/delivery.d.ts +6 -0
- package/dist/execution/service/{publication → serving}/delivery.js +5 -1
- package/dist/execution/service/{publication → serving}/index.d.ts +1 -1
- package/dist/execution/service/serving/installation.d.ts +4 -0
- package/dist/execution/service/serving/installation.js +9 -0
- package/dist/execution/service/serving/legacy/index.d.ts +15 -0
- package/dist/execution/service/serving/legacy/index.js +19 -0
- package/dist/execution/service/serving/source.d.ts +18 -0
- package/dist/execution/service/serving/source.js +19 -0
- package/dist/execution/workflows/run.js +1 -1
- package/dist/platform/versioning/name.d.ts +4 -3
- package/dist/platform/versioning/name.js +4 -3
- package/dist/project/define.js +58 -28
- package/dist/project/install-command.d.ts +10 -0
- package/dist/project/install-command.js +13 -0
- package/dist/project/project.d.ts +4 -2
- package/dist/tooling/cli/arguments.d.ts +1 -3
- package/dist/tooling/cli/arguments.js +51 -22
- package/dist/tooling/cli/commit.d.ts +23 -0
- package/dist/tooling/cli/commit.js +216 -0
- package/dist/tooling/cli/deploy-mode.d.ts +16 -13
- package/dist/tooling/cli/deploy-mode.js +45 -36
- package/dist/tooling/cli/deploy-result.d.ts +10 -7
- package/dist/tooling/cli/deploy-result.js +4 -3
- package/dist/tooling/cli/dotenv.d.ts +2 -2
- package/dist/tooling/cli/dotenv.js +3 -33
- package/dist/tooling/cli/help.js +73 -29
- package/dist/tooling/cli/immutable-deployment.d.ts +27 -0
- package/dist/tooling/cli/immutable-deployment.js +95 -0
- package/dist/tooling/cli/index.d.ts +3 -4
- package/dist/tooling/cli/index.js +2 -3
- package/dist/tooling/cli/legacy/deploy-result.d.ts +5 -3
- package/dist/tooling/cli/legacy/deploy-result.js +5 -3
- package/dist/tooling/cli/{development → legacy/development}/candidate.d.ts +3 -4
- package/dist/tooling/cli/{development → legacy/development}/candidate.js +7 -14
- package/dist/tooling/cli/legacy/development/deployment.d.ts +10 -0
- package/dist/tooling/cli/legacy/development/deployment.js +20 -0
- package/dist/tooling/cli/legacy/development/deprecation.d.ts +11 -0
- package/dist/tooling/cli/legacy/development/deprecation.js +13 -0
- package/dist/tooling/cli/legacy/development/develop.d.ts +15 -0
- package/dist/tooling/cli/legacy/development/develop.js +142 -0
- package/dist/tooling/cli/legacy/development/index.d.ts +21 -0
- package/dist/tooling/cli/legacy/development/index.js +21 -0
- package/dist/tooling/cli/legacy/development/report.d.ts +7 -0
- package/dist/tooling/cli/{development → legacy/development}/report.js +2 -5
- package/dist/tooling/cli/legacy/development/secrets-file.d.ts +2 -0
- package/dist/tooling/cli/legacy/development/secrets-file.js +33 -0
- package/dist/tooling/cli/legacy/stable-target-adapter.d.ts +5 -3
- package/dist/tooling/cli/legacy/stable-target-deploy.d.ts +40 -0
- package/dist/tooling/cli/legacy/stable-target-deploy.js +102 -0
- package/dist/tooling/cli/list.d.ts +114 -0
- package/dist/tooling/cli/list.js +297 -0
- package/dist/tooling/cli/orchestrate.d.ts +1 -1
- package/dist/tooling/cli/orchestrate.js +91 -95
- package/dist/tooling/cli/secrets.d.ts +9 -0
- package/dist/tooling/cli/secrets.js +19 -0
- package/package.json +7 -7
- package/dist/deployment/verify/readiness/publication.d.ts +0 -11
- package/dist/deployment/verify/readiness/publication.js +0 -41
- package/dist/execution/service/publication/delivery.d.ts +0 -2
- package/dist/execution/service/publication/installation.d.ts +0 -3
- package/dist/execution/service/publication/installation.js +0 -8
- package/dist/execution/service/publication/source.d.ts +0 -3
- package/dist/execution/service/publication/source.js +0 -11
- package/dist/tooling/cli/astrale/authority.d.ts +0 -5
- package/dist/tooling/cli/astrale/authority.js +0 -11
- package/dist/tooling/cli/astrale/executable.d.ts +0 -2
- package/dist/tooling/cli/astrale/executable.js +0 -47
- package/dist/tooling/cli/astrale/failure.d.ts +0 -6
- package/dist/tooling/cli/astrale/failure.js +0 -48
- package/dist/tooling/cli/astrale/instance.d.ts +0 -11
- package/dist/tooling/cli/astrale/instance.js +0 -52
- package/dist/tooling/cli/astrale/process.d.ts +0 -13
- package/dist/tooling/cli/astrale/process.js +0 -94
- package/dist/tooling/cli/astrale/version.d.ts +0 -18
- package/dist/tooling/cli/astrale/version.js +0 -55
- package/dist/tooling/cli/development/deployment.d.ts +0 -16
- package/dist/tooling/cli/development/deployment.js +0 -39
- package/dist/tooling/cli/development/develop.d.ts +0 -11
- package/dist/tooling/cli/development/develop.js +0 -243
- package/dist/tooling/cli/development/release-evidence.d.ts +0 -4
- package/dist/tooling/cli/development/release-evidence.js +0 -10
- package/dist/tooling/cli/development/report.d.ts +0 -9
- package/dist/tooling/cli/development/session-file.d.ts +0 -53
- package/dist/tooling/cli/development/session-file.js +0 -337
- package/dist/tooling/cli/development/target-lock.d.ts +0 -16
- package/dist/tooling/cli/development/target-lock.js +0 -68
- package/dist/tooling/cli/development/view.d.ts +0 -28
- package/dist/tooling/cli/development/view.js +0 -151
- package/dist/tooling/cli/environment-release.d.ts +0 -24
- package/dist/tooling/cli/environment-release.js +0 -46
- package/dist/tooling/cli/evidence.d.ts +0 -14
- package/dist/tooling/cli/evidence.js +0 -53
- package/dist/tooling/cli/installation/index.d.ts +0 -2
- package/dist/tooling/cli/installation/index.js +0 -1
- package/dist/tooling/cli/installation/observation.d.ts +0 -10
- package/dist/tooling/cli/installation/observation.js +0 -44
- package/dist/tooling/cli/installation/reconcile.d.ts +0 -32
- package/dist/tooling/cli/installation/reconcile.js +0 -122
- /package/dist/execution/service/{publication → serving}/index.js +0 -0
- /package/dist/tooling/cli/{credential.d.ts → legacy/development/credential.d.ts} +0 -0
- /package/dist/tooling/cli/{credential.js → legacy/development/credential.js} +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/lease.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/lease.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/lifecycle.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/lifecycle.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/project-imports.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/project-imports.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/project-lock.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/project-lock.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/rebuild.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/rebuild.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/source-watch.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/source-watch.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/sources.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/sources.js +0 -0
|
@@ -1,243 +0,0 @@
|
|
|
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';
|
|
11
|
-
import { DevelopmentLifecycle } from './lifecycle.js';
|
|
12
|
-
import { acquireProjectLock } from './project-lock.js';
|
|
13
|
-
import { LatestRebuild } from './rebuild.js';
|
|
14
|
-
import { developmentReleaseEvidence } from './release-evidence.js';
|
|
15
|
-
import { reportDevelopmentDeployment } from './report.js';
|
|
16
|
-
import { DevelopmentSessionFileWriter } from './session-file.js';
|
|
17
|
-
import { watchSources } from './source-watch.js';
|
|
18
|
-
import { acquireDevelopmentTargetLock } from './target-lock.js';
|
|
19
|
-
import { DevelopmentView } from './view.js';
|
|
20
|
-
/** Watch one Project Environment and serialize complete remote deployment generations. */
|
|
21
|
-
export async function develop(input) {
|
|
22
|
-
const lifecycle = new DevelopmentLifecycle();
|
|
23
|
-
let sessionFile;
|
|
24
|
-
let lock;
|
|
25
|
-
let targetLock;
|
|
26
|
-
let view;
|
|
27
|
-
let installationExecutable;
|
|
28
|
-
let installationIssuer;
|
|
29
|
-
let sourceWatch;
|
|
30
|
-
let rebuild;
|
|
31
|
-
let current;
|
|
32
|
-
let lastEvidence;
|
|
33
|
-
let failure;
|
|
34
|
-
const cleanup = [];
|
|
35
|
-
try {
|
|
36
|
-
if (input.sessionFile !== undefined) {
|
|
37
|
-
sessionFile = await DevelopmentSessionFileWriter.create(input.sessionFile);
|
|
38
|
-
}
|
|
39
|
-
lock = await acquireProjectLock({
|
|
40
|
-
projectRoot: input.projectDir,
|
|
41
|
-
environment: input.environment,
|
|
42
|
-
});
|
|
43
|
-
const overrideSecrets = input.secretsFile === undefined
|
|
44
|
-
? undefined
|
|
45
|
-
: Object.freeze(loadPrivateSecretsFile(input.secretsFile));
|
|
46
|
-
const credential = input.credentialFile === undefined
|
|
47
|
-
? undefined
|
|
48
|
-
: loadPrivateCredentialFile(input.credentialFile);
|
|
49
|
-
const runtimePath = await discoverRuntimePath(input.configPath);
|
|
50
|
-
const builder = new DevelopmentCandidateBuilder({
|
|
51
|
-
...input,
|
|
52
|
-
runtimePath,
|
|
53
|
-
overrideSecrets,
|
|
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;
|
|
98
|
-
rebuild = new LatestRebuild({
|
|
99
|
-
async prepare(_ignored, signal) {
|
|
100
|
-
info(`Rebuilding: ${input.environment}`);
|
|
101
|
-
if (lastEvidence !== undefined)
|
|
102
|
-
await sessionFile?.transition('updating', lastEvidence);
|
|
103
|
-
return builder.prepare(signal);
|
|
104
|
-
},
|
|
105
|
-
async commit(candidate, signal) {
|
|
106
|
-
if (!sameEnvironment(current, candidate)) {
|
|
107
|
-
restartReported = true;
|
|
108
|
-
throw new Error('Project Environment configuration changed; restart pnpm dev to apply it.');
|
|
109
|
-
}
|
|
110
|
-
if (sameDeploymentCandidate(current, candidate)) {
|
|
111
|
-
current = candidate;
|
|
112
|
-
await sessionFile?.transition('ready', lastEvidence);
|
|
113
|
-
sourceWatch?.update(candidate.sources);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
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
|
-
});
|
|
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);
|
|
138
|
-
},
|
|
139
|
-
async failed(cause) {
|
|
140
|
-
error(cause instanceof Error ? cause.message : String(cause));
|
|
141
|
-
if (lastEvidence === undefined)
|
|
142
|
-
return;
|
|
143
|
-
try {
|
|
144
|
-
await sessionFile?.transition('recovering', lastEvidence);
|
|
145
|
-
}
|
|
146
|
-
catch (sessionCause) {
|
|
147
|
-
const terminal = new AggregateError([cause, sessionCause], 'Development rebuild failed and session evidence could not be recovered.');
|
|
148
|
-
failure ??= terminal;
|
|
149
|
-
lifecycle.stop(terminal);
|
|
150
|
-
}
|
|
151
|
-
},
|
|
152
|
-
});
|
|
153
|
-
sourceWatch = watchSources({
|
|
154
|
-
projectDir: input.projectDir,
|
|
155
|
-
configPath: input.configPath,
|
|
156
|
-
sources: current.sources,
|
|
157
|
-
onInvalidate: () => rebuild.invalidate(),
|
|
158
|
-
onRestartRequired: () => {
|
|
159
|
-
if (restartReported)
|
|
160
|
-
return;
|
|
161
|
-
restartReported = true;
|
|
162
|
-
error('Project Environment configuration changed; restart pnpm dev to apply it.');
|
|
163
|
-
},
|
|
164
|
-
onError: (cause) => {
|
|
165
|
-
failure = cause;
|
|
166
|
-
lifecycle.stop(cause);
|
|
167
|
-
},
|
|
168
|
-
});
|
|
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;
|
|
174
|
-
}
|
|
175
|
-
catch (cause) {
|
|
176
|
-
failure = cause;
|
|
177
|
-
}
|
|
178
|
-
lifecycle.stop(failure);
|
|
179
|
-
try {
|
|
180
|
-
await sessionFile?.transition('stopping', lastEvidence);
|
|
181
|
-
}
|
|
182
|
-
catch (cause) {
|
|
183
|
-
failure ??= cause;
|
|
184
|
-
}
|
|
185
|
-
for (const operation of [
|
|
186
|
-
() => sourceWatch?.stop(),
|
|
187
|
-
() => rebuild?.stop(failure),
|
|
188
|
-
() => view?.close(AbortSignal.timeout(30_000)),
|
|
189
|
-
() => rm(join(input.projectDir, '.astrale', 'development', input.environment, 'source'), {
|
|
190
|
-
recursive: true,
|
|
191
|
-
force: true,
|
|
192
|
-
}),
|
|
193
|
-
() => targetLock?.release(),
|
|
194
|
-
() => lock?.release(),
|
|
195
|
-
]) {
|
|
196
|
-
try {
|
|
197
|
-
await operation();
|
|
198
|
-
}
|
|
199
|
-
catch (cause) {
|
|
200
|
-
cleanup.push(cause);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
for (const directory of [
|
|
204
|
-
join(input.projectDir, '.astrale', 'development', input.environment),
|
|
205
|
-
join(input.projectDir, '.astrale', 'development'),
|
|
206
|
-
]) {
|
|
207
|
-
try {
|
|
208
|
-
await rmdir(directory);
|
|
209
|
-
}
|
|
210
|
-
catch (cause) {
|
|
211
|
-
const code = cause.code;
|
|
212
|
-
if (code !== 'ENOENT' && code !== 'ENOTEMPTY' && code !== 'EEXIST')
|
|
213
|
-
cleanup.push(cause);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
try {
|
|
217
|
-
await sessionFile?.transition(failure === undefined && cleanup.length === 0 ? 'stopped' : 'failed');
|
|
218
|
-
}
|
|
219
|
-
catch (cause) {
|
|
220
|
-
cleanup.push(cause);
|
|
221
|
-
}
|
|
222
|
-
lifecycle.dispose();
|
|
223
|
-
if (failure !== undefined) {
|
|
224
|
-
if (cleanup.length > 0)
|
|
225
|
-
error(new AggregateError(cleanup, 'Development cleanup failed.').message);
|
|
226
|
-
throw failure;
|
|
227
|
-
}
|
|
228
|
-
if (cleanup.length > 0)
|
|
229
|
-
throw new AggregateError(cleanup, 'Development cleanup failed.');
|
|
230
|
-
return 0;
|
|
231
|
-
}
|
|
232
|
-
async function refreshView(view, release, signal) {
|
|
233
|
-
if (view === undefined)
|
|
234
|
-
return;
|
|
235
|
-
try {
|
|
236
|
-
const pageUrl = await view.refresh(release, signal);
|
|
237
|
-
if (pageUrl !== undefined)
|
|
238
|
-
info(`View: ${pageUrl}`);
|
|
239
|
-
}
|
|
240
|
-
catch (cause) {
|
|
241
|
-
error(`View unavailable: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { InstallationEvidence } from '../installation/index.js';
|
|
2
|
-
import type { DevelopmentSessionReleaseEvidenceV1 } from './session-file.js';
|
|
3
|
-
/** Project installed evidence projected into the stable development-session representation. */
|
|
4
|
-
export declare function developmentReleaseEvidence(installation: InstallationEvidence): DevelopmentSessionReleaseEvidenceV1;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/** Project installed evidence projected into the stable development-session representation. */
|
|
2
|
-
export function developmentReleaseEvidence(installation) {
|
|
3
|
-
return Object.freeze({
|
|
4
|
-
origin: installation.origin,
|
|
5
|
-
revision: installation.revision,
|
|
6
|
-
issuer: installation.issuer,
|
|
7
|
-
etag: installation.etag,
|
|
8
|
-
generation: installation.generation,
|
|
9
|
-
});
|
|
10
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ReadyDeployResult } from '../../../deployment/adapter/index.js';
|
|
2
|
-
import type { InstallationEvidence } from '../installation/index.js';
|
|
3
|
-
export declare function reportDevelopmentDeployment(deployed: ReadyDeployResult, installation: InstallationEvidence | undefined, adapter: {
|
|
4
|
-
readonly name: string;
|
|
5
|
-
readonly version: string;
|
|
6
|
-
}, input: {
|
|
7
|
-
readonly environment: string;
|
|
8
|
-
readonly deployOnly: boolean;
|
|
9
|
-
}): void;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
export declare const DEVELOPMENT_SESSION_FILE_VERSION: 1;
|
|
2
|
-
export type DevelopmentSessionPhaseV1 = 'starting' | 'ready' | 'updating' | 'recovering' | 'stopping' | 'stopped' | 'failed';
|
|
3
|
-
export interface DevelopmentSessionProjectV1 {
|
|
4
|
-
readonly origin: string;
|
|
5
|
-
}
|
|
6
|
-
export interface DevelopmentSessionReleaseV1 {
|
|
7
|
-
readonly revision: string;
|
|
8
|
-
readonly issuer: string;
|
|
9
|
-
readonly etag: string;
|
|
10
|
-
readonly generation: string;
|
|
11
|
-
}
|
|
12
|
-
interface DevelopmentSessionFileBaseV1 {
|
|
13
|
-
readonly version: typeof DEVELOPMENT_SESSION_FILE_VERSION;
|
|
14
|
-
readonly sessionId: string;
|
|
15
|
-
readonly sequence: number;
|
|
16
|
-
readonly phase: DevelopmentSessionPhaseV1;
|
|
17
|
-
}
|
|
18
|
-
interface DevelopmentSessionStartingFileV1 extends DevelopmentSessionFileBaseV1 {
|
|
19
|
-
readonly phase: 'starting';
|
|
20
|
-
}
|
|
21
|
-
interface DevelopmentSessionActiveFileV1 extends DevelopmentSessionFileBaseV1 {
|
|
22
|
-
readonly phase: 'ready' | 'updating' | 'recovering';
|
|
23
|
-
readonly project: DevelopmentSessionProjectV1;
|
|
24
|
-
readonly release: DevelopmentSessionReleaseV1;
|
|
25
|
-
}
|
|
26
|
-
interface DevelopmentSessionTerminalFileBaseV1 extends DevelopmentSessionFileBaseV1 {
|
|
27
|
-
readonly phase: 'stopping' | 'stopped' | 'failed';
|
|
28
|
-
}
|
|
29
|
-
type DevelopmentSessionTerminalFileV1 = DevelopmentSessionTerminalFileBaseV1 & ({
|
|
30
|
-
readonly project: DevelopmentSessionProjectV1;
|
|
31
|
-
readonly release: DevelopmentSessionReleaseV1;
|
|
32
|
-
} | {
|
|
33
|
-
readonly project?: never;
|
|
34
|
-
readonly release?: never;
|
|
35
|
-
});
|
|
36
|
-
export type DevelopmentSessionFileV1 = DevelopmentSessionStartingFileV1 | DevelopmentSessionActiveFileV1 | DevelopmentSessionTerminalFileV1;
|
|
37
|
-
export interface DevelopmentSessionReleaseEvidenceV1 extends DevelopmentSessionProjectV1, DevelopmentSessionReleaseV1 {
|
|
38
|
-
}
|
|
39
|
-
export declare class DevelopmentSessionFileError extends Error {
|
|
40
|
-
readonly code: 'INVALID_SESSION_FILE_PATH' | 'SESSION_FILE_PATH_UNSAFE' | 'SESSION_FILE_EXISTS' | 'SESSION_FILE_TAMPERED' | 'SESSION_FILE_TRANSITION_INVALID' | 'SESSION_FILE_EVIDENCE_INCOHERENT';
|
|
41
|
-
readonly name = "DevelopmentSessionFileError";
|
|
42
|
-
constructor(code: 'INVALID_SESSION_FILE_PATH' | 'SESSION_FILE_PATH_UNSAFE' | 'SESSION_FILE_EXISTS' | 'SESSION_FILE_TAMPERED' | 'SESSION_FILE_TRANSITION_INVALID' | 'SESSION_FILE_EVIDENCE_INCOHERENT', message: string, options?: ErrorOptions);
|
|
43
|
-
}
|
|
44
|
-
export declare function acceptDevelopmentSessionFileV1(input: unknown): DevelopmentSessionFileV1;
|
|
45
|
-
/** SDK-private sole writer for one caller-selected machine-integration file. */
|
|
46
|
-
export declare class DevelopmentSessionFileWriter {
|
|
47
|
-
#private;
|
|
48
|
-
private constructor();
|
|
49
|
-
static create(path: string): Promise<DevelopmentSessionFileWriter>;
|
|
50
|
-
transition(phase: Exclude<DevelopmentSessionPhaseV1, 'starting'>, evidence?: DevelopmentSessionReleaseEvidenceV1): Promise<DevelopmentSessionFileV1>;
|
|
51
|
-
}
|
|
52
|
-
export declare function developmentSessionTransitionAllowed(previous: DevelopmentSessionPhaseV1, next: Exclude<DevelopmentSessionPhaseV1, 'starting'>): boolean;
|
|
53
|
-
export {};
|
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { link, lstat, open, readFile, realpath, rename, unlink } from 'node:fs/promises';
|
|
3
|
-
import { basename, dirname, isAbsolute, join, normalize, parse, sep } from 'node:path';
|
|
4
|
-
import { patterns } from '../../../platform/schema/index.js';
|
|
5
|
-
export const DEVELOPMENT_SESSION_FILE_VERSION = 1;
|
|
6
|
-
export class DevelopmentSessionFileError extends Error {
|
|
7
|
-
code;
|
|
8
|
-
name = 'DevelopmentSessionFileError';
|
|
9
|
-
constructor(code, message, options) {
|
|
10
|
-
super(message, options);
|
|
11
|
-
this.code = code;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
export function acceptDevelopmentSessionFileV1(input) {
|
|
15
|
-
const value = record(input, 'Development session file');
|
|
16
|
-
if (value.metadata !== undefined ||
|
|
17
|
-
value.extensions !== undefined ||
|
|
18
|
-
value.vendor !== undefined) {
|
|
19
|
-
invalid('Development session file cannot contain a metadata, extensions, or vendor bag.');
|
|
20
|
-
}
|
|
21
|
-
if (value.version !== DEVELOPMENT_SESSION_FILE_VERSION) {
|
|
22
|
-
invalid(`Unsupported development session file version: ${String(value.version)}.`);
|
|
23
|
-
}
|
|
24
|
-
const sessionId = text(value.sessionId, 'Development session id');
|
|
25
|
-
const sequence = integer(value.sequence, 'Development session sequence');
|
|
26
|
-
const phase = admitPhase(value.phase);
|
|
27
|
-
const base = Object.freeze({ version: 1, sessionId, sequence, phase });
|
|
28
|
-
const hasProject = value.project !== undefined;
|
|
29
|
-
const hasRelease = value.release !== undefined;
|
|
30
|
-
if (phase === 'starting') {
|
|
31
|
-
if (hasProject || hasRelease) {
|
|
32
|
-
invalid('Development session starting phase cannot contain Release evidence.');
|
|
33
|
-
}
|
|
34
|
-
return Object.freeze({ ...base, phase: 'starting' });
|
|
35
|
-
}
|
|
36
|
-
if (phase === 'ready' || phase === 'updating' || phase === 'recovering') {
|
|
37
|
-
if (!hasProject || !hasRelease)
|
|
38
|
-
invalid(`Development session phase ${phase} requires a Release.`);
|
|
39
|
-
return Object.freeze({
|
|
40
|
-
...base,
|
|
41
|
-
phase,
|
|
42
|
-
project: project(value.project),
|
|
43
|
-
release: release(value.release),
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
if (hasProject !== hasRelease) {
|
|
47
|
-
invalid('Development session terminal project and Release must be present together.');
|
|
48
|
-
}
|
|
49
|
-
if (!hasProject)
|
|
50
|
-
return Object.freeze({ ...base, phase });
|
|
51
|
-
return Object.freeze({
|
|
52
|
-
...base,
|
|
53
|
-
phase,
|
|
54
|
-
project: project(value.project),
|
|
55
|
-
release: release(value.release),
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
/** SDK-private sole writer for one caller-selected machine-integration file. */
|
|
59
|
-
export class DevelopmentSessionFileWriter {
|
|
60
|
-
#path;
|
|
61
|
-
#parent;
|
|
62
|
-
#sessionId;
|
|
63
|
-
#sequence = 0;
|
|
64
|
-
#phase = 'starting';
|
|
65
|
-
#last;
|
|
66
|
-
#tail = Promise.resolve();
|
|
67
|
-
constructor(path, parent, sessionId) {
|
|
68
|
-
this.#path = path;
|
|
69
|
-
this.#parent = parent;
|
|
70
|
-
this.#sessionId = sessionId;
|
|
71
|
-
}
|
|
72
|
-
static async create(path) {
|
|
73
|
-
const admitted = await admitSessionFilePath(path);
|
|
74
|
-
const writer = new DevelopmentSessionFileWriter(admitted.path, admitted.parent, randomUUID());
|
|
75
|
-
await writer.#create();
|
|
76
|
-
return writer;
|
|
77
|
-
}
|
|
78
|
-
transition(phase, evidence) {
|
|
79
|
-
const operation = this.#tail.then(async () => {
|
|
80
|
-
if (!developmentSessionTransitionAllowed(this.#phase, phase)) {
|
|
81
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_TRANSITION_INVALID', `Development session cannot transition from ${this.#phase} to ${phase}.`);
|
|
82
|
-
}
|
|
83
|
-
if (evidence !== undefined)
|
|
84
|
-
this.#last = admitEvidence(evidence);
|
|
85
|
-
if (['ready', 'updating', 'recovering'].includes(phase) && this.#last === undefined) {
|
|
86
|
-
throw new TypeError(`Development session phase ${phase} requires Release evidence.`);
|
|
87
|
-
}
|
|
88
|
-
const snapshot = this.#snapshot(phase, this.#sequence + 1);
|
|
89
|
-
await this.#replace(snapshot);
|
|
90
|
-
this.#sequence = snapshot.sequence;
|
|
91
|
-
this.#phase = snapshot.phase;
|
|
92
|
-
return snapshot;
|
|
93
|
-
});
|
|
94
|
-
this.#tail = operation.then(() => undefined, () => undefined);
|
|
95
|
-
return operation;
|
|
96
|
-
}
|
|
97
|
-
async #create() {
|
|
98
|
-
const snapshot = this.#snapshot('starting', 1);
|
|
99
|
-
const staging = await writeStaging(this.#parent, this.#path, this.#sessionId, snapshot);
|
|
100
|
-
try {
|
|
101
|
-
await link(staging, this.#path);
|
|
102
|
-
}
|
|
103
|
-
catch (cause) {
|
|
104
|
-
if (errorCode(cause) === 'EEXIST') {
|
|
105
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_EXISTS', `Development session file already exists: ${this.#path}`, { cause });
|
|
106
|
-
}
|
|
107
|
-
throw cause;
|
|
108
|
-
}
|
|
109
|
-
finally {
|
|
110
|
-
await unlink(staging).catch((cause) => {
|
|
111
|
-
if (errorCode(cause) !== 'ENOENT')
|
|
112
|
-
throw cause;
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
await syncDirectory(this.#parent);
|
|
116
|
-
this.#sequence = snapshot.sequence;
|
|
117
|
-
}
|
|
118
|
-
#snapshot(phase, sequence) {
|
|
119
|
-
const base = {
|
|
120
|
-
version: DEVELOPMENT_SESSION_FILE_VERSION,
|
|
121
|
-
sessionId: this.#sessionId,
|
|
122
|
-
sequence,
|
|
123
|
-
};
|
|
124
|
-
if (phase === 'starting')
|
|
125
|
-
return Object.freeze({ ...base, phase: 'starting' });
|
|
126
|
-
if (this.#last === undefined) {
|
|
127
|
-
if (phase === 'ready' || phase === 'updating' || phase === 'recovering') {
|
|
128
|
-
throw new TypeError(`Development session phase ${phase} requires Release evidence.`);
|
|
129
|
-
}
|
|
130
|
-
return Object.freeze({ ...base, phase });
|
|
131
|
-
}
|
|
132
|
-
return Object.freeze({
|
|
133
|
-
...base,
|
|
134
|
-
phase,
|
|
135
|
-
project: Object.freeze({ origin: this.#last.origin }),
|
|
136
|
-
release: Object.freeze({
|
|
137
|
-
revision: this.#last.revision,
|
|
138
|
-
issuer: this.#last.issuer,
|
|
139
|
-
etag: this.#last.etag,
|
|
140
|
-
generation: this.#last.generation,
|
|
141
|
-
}),
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
async #replace(snapshot) {
|
|
145
|
-
await assertParent(this.#parent);
|
|
146
|
-
const current = await readCurrent(this.#path);
|
|
147
|
-
if (current.sessionId !== this.#sessionId || current.sequence !== snapshot.sequence - 1) {
|
|
148
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_TAMPERED', `Development session file ownership changed: ${this.#path}`);
|
|
149
|
-
}
|
|
150
|
-
const staging = await writeStaging(this.#parent, this.#path, this.#sessionId, snapshot);
|
|
151
|
-
try {
|
|
152
|
-
await rename(staging, this.#path);
|
|
153
|
-
await syncDirectory(this.#parent);
|
|
154
|
-
}
|
|
155
|
-
finally {
|
|
156
|
-
await unlink(staging).catch((cause) => {
|
|
157
|
-
if (errorCode(cause) !== 'ENOENT')
|
|
158
|
-
throw cause;
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
function admitEvidence(input) {
|
|
164
|
-
const admittedProject = project({ origin: input.origin });
|
|
165
|
-
const admittedRelease = release(input);
|
|
166
|
-
return Object.freeze({ origin: admittedProject.origin, ...admittedRelease });
|
|
167
|
-
}
|
|
168
|
-
async function admitSessionFilePath(input) {
|
|
169
|
-
if (!isAbsolute(input) || normalize(input) !== input || basename(input).length === 0) {
|
|
170
|
-
throw new DevelopmentSessionFileError('INVALID_SESSION_FILE_PATH', '--session-file requires one normalized absolute file path.');
|
|
171
|
-
}
|
|
172
|
-
const parent = dirname(input);
|
|
173
|
-
await assertParent(parent);
|
|
174
|
-
try {
|
|
175
|
-
await lstat(input);
|
|
176
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_EXISTS', `Development session file path must not exist: ${input}`);
|
|
177
|
-
}
|
|
178
|
-
catch (cause) {
|
|
179
|
-
if (errorCode(cause) !== 'ENOENT')
|
|
180
|
-
throw cause;
|
|
181
|
-
}
|
|
182
|
-
return Object.freeze({ path: input, parent });
|
|
183
|
-
}
|
|
184
|
-
async function assertParent(parent) {
|
|
185
|
-
const root = parse(parent).root;
|
|
186
|
-
let cursor = root;
|
|
187
|
-
for (const segment of parent.slice(root.length).split(sep).filter(Boolean)) {
|
|
188
|
-
cursor = join(cursor, segment);
|
|
189
|
-
const entry = await lstat(cursor);
|
|
190
|
-
if (entry.isSymbolicLink())
|
|
191
|
-
unsafe(`Development session file path crosses a symlink: ${cursor}`);
|
|
192
|
-
}
|
|
193
|
-
const canonical = await realpath(parent);
|
|
194
|
-
if (canonical !== parent)
|
|
195
|
-
unsafe(`Development session file parent is not canonical: ${parent}`);
|
|
196
|
-
const entry = await lstat(parent);
|
|
197
|
-
if (!entry.isDirectory())
|
|
198
|
-
unsafe(`Development session file parent is not a directory: ${parent}`);
|
|
199
|
-
const uid = process.getuid?.();
|
|
200
|
-
if (uid !== undefined && entry.uid !== uid) {
|
|
201
|
-
unsafe(`Development session file parent is not owned by the current user: ${parent}`);
|
|
202
|
-
}
|
|
203
|
-
if ((entry.mode & 0o077) !== 0) {
|
|
204
|
-
unsafe(`Development session file parent must be owner-only: ${parent}`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
async function writeStaging(parent, target, sessionId, snapshot) {
|
|
208
|
-
const path = join(parent, `.${basename(target)}.${sessionId}.${randomUUID()}.next`);
|
|
209
|
-
const file = await open(path, 'wx', 0o600);
|
|
210
|
-
try {
|
|
211
|
-
await file.writeFile(`${JSON.stringify(snapshot, null, 2)}\n`, 'utf8');
|
|
212
|
-
await file.sync();
|
|
213
|
-
}
|
|
214
|
-
catch (cause) {
|
|
215
|
-
await file.close();
|
|
216
|
-
await unlink(path).catch(() => undefined);
|
|
217
|
-
throw cause;
|
|
218
|
-
}
|
|
219
|
-
await file.close();
|
|
220
|
-
return path;
|
|
221
|
-
}
|
|
222
|
-
async function syncDirectory(path) {
|
|
223
|
-
const directory = await open(path, 'r');
|
|
224
|
-
try {
|
|
225
|
-
await directory.sync();
|
|
226
|
-
}
|
|
227
|
-
finally {
|
|
228
|
-
await directory.close();
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
async function readCurrent(path) {
|
|
232
|
-
const entry = await lstat(path);
|
|
233
|
-
if (!entry.isFile() || entry.isSymbolicLink() || (entry.mode & 0o077) !== 0) {
|
|
234
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_TAMPERED', `Development session file is no longer one owner-only regular file: ${path}`);
|
|
235
|
-
}
|
|
236
|
-
try {
|
|
237
|
-
return acceptDevelopmentSessionFileV1(JSON.parse(await readFile(path, 'utf8')));
|
|
238
|
-
}
|
|
239
|
-
catch (cause) {
|
|
240
|
-
if (cause instanceof DevelopmentSessionFileError)
|
|
241
|
-
throw cause;
|
|
242
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_TAMPERED', `Development session file is unreadable or invalid: ${path}`, { cause });
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
function project(input) {
|
|
246
|
-
const value = record(input, 'Development session project');
|
|
247
|
-
rejectBags(value, 'Development session project');
|
|
248
|
-
const origin = text(value.origin, 'Development session project origin');
|
|
249
|
-
if (!patterns.origin.test(origin))
|
|
250
|
-
invalid('Development session project origin is invalid.');
|
|
251
|
-
return Object.freeze({ origin });
|
|
252
|
-
}
|
|
253
|
-
function release(input) {
|
|
254
|
-
const value = record(input, 'Development session Release');
|
|
255
|
-
rejectBags(value, 'Development session Release');
|
|
256
|
-
const revision = digest(value.revision, 'Development session Release revision');
|
|
257
|
-
const etag = digest(value.etag, 'Development session Release etag');
|
|
258
|
-
const generation = digest(value.generation, 'Development session Release generation');
|
|
259
|
-
const issuer = origin(value.issuer);
|
|
260
|
-
return Object.freeze({ revision, issuer, etag, generation });
|
|
261
|
-
}
|
|
262
|
-
function origin(input) {
|
|
263
|
-
const value = text(input, 'Development session Release issuer');
|
|
264
|
-
let url;
|
|
265
|
-
try {
|
|
266
|
-
url = new URL(value);
|
|
267
|
-
}
|
|
268
|
-
catch (cause) {
|
|
269
|
-
throw new TypeError('Development session Release issuer must be an HTTP(S) origin.', { cause });
|
|
270
|
-
}
|
|
271
|
-
if (!['http:', 'https:'].includes(url.protocol) || url.href !== `${url.origin}/`) {
|
|
272
|
-
invalid('Development session Release issuer must be an HTTP(S) origin.');
|
|
273
|
-
}
|
|
274
|
-
return url.origin;
|
|
275
|
-
}
|
|
276
|
-
function digest(input, label) {
|
|
277
|
-
const value = text(input, label);
|
|
278
|
-
if (!/^sha256:[0-9a-f]{64}$/u.test(value))
|
|
279
|
-
invalid(`${label} must be a sha256 digest.`);
|
|
280
|
-
return value;
|
|
281
|
-
}
|
|
282
|
-
function admitPhase(input) {
|
|
283
|
-
if (input !== 'starting' &&
|
|
284
|
-
input !== 'ready' &&
|
|
285
|
-
input !== 'updating' &&
|
|
286
|
-
input !== 'recovering' &&
|
|
287
|
-
input !== 'stopping' &&
|
|
288
|
-
input !== 'stopped' &&
|
|
289
|
-
input !== 'failed') {
|
|
290
|
-
invalid(`Unknown development session phase: ${String(input)}.`);
|
|
291
|
-
}
|
|
292
|
-
return input;
|
|
293
|
-
}
|
|
294
|
-
export function developmentSessionTransitionAllowed(previous, next) {
|
|
295
|
-
if (previous === 'stopped' || previous === 'failed')
|
|
296
|
-
return false;
|
|
297
|
-
if (previous === 'stopping')
|
|
298
|
-
return next === 'stopped' || next === 'failed';
|
|
299
|
-
if (next === 'stopping' || next === 'failed')
|
|
300
|
-
return true;
|
|
301
|
-
if (previous === 'starting')
|
|
302
|
-
return next === 'ready';
|
|
303
|
-
return next === 'ready' || next === 'updating' || next === 'recovering';
|
|
304
|
-
}
|
|
305
|
-
function rejectBags(value, label) {
|
|
306
|
-
if (value.metadata !== undefined ||
|
|
307
|
-
value.extensions !== undefined ||
|
|
308
|
-
value.vendor !== undefined) {
|
|
309
|
-
invalid(`${label} cannot contain a metadata, extensions, or vendor bag.`);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
function record(input, label) {
|
|
313
|
-
if (input === null || typeof input !== 'object' || Array.isArray(input))
|
|
314
|
-
invalid(`${label} must be an object.`);
|
|
315
|
-
return input;
|
|
316
|
-
}
|
|
317
|
-
function text(input, label) {
|
|
318
|
-
if (typeof input !== 'string' || input.length === 0)
|
|
319
|
-
invalid(`${label} must be text.`);
|
|
320
|
-
return input;
|
|
321
|
-
}
|
|
322
|
-
function integer(input, label) {
|
|
323
|
-
if (!Number.isSafeInteger(input) || Number(input) <= 0)
|
|
324
|
-
invalid(`${label} must be a positive integer.`);
|
|
325
|
-
return Number(input);
|
|
326
|
-
}
|
|
327
|
-
function invalid(message) {
|
|
328
|
-
throw new TypeError(message);
|
|
329
|
-
}
|
|
330
|
-
function unsafe(message) {
|
|
331
|
-
throw new DevelopmentSessionFileError('SESSION_FILE_PATH_UNSAFE', message);
|
|
332
|
-
}
|
|
333
|
-
function errorCode(input) {
|
|
334
|
-
return input !== null && typeof input === 'object' && 'code' in input
|
|
335
|
-
? String(Reflect.get(input, 'code'))
|
|
336
|
-
: undefined;
|
|
337
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { DevelopmentLease } from './lease.js';
|
|
2
|
-
export declare class DevelopmentTargetLockError extends Error {
|
|
3
|
-
readonly code: 'DEVELOPMENT_TARGET_LOCKED' | 'DEVELOPMENT_TARGET_LOCK_LOST';
|
|
4
|
-
readonly name = "DevelopmentTargetLockError";
|
|
5
|
-
constructor(code: 'DEVELOPMENT_TARGET_LOCKED' | 'DEVELOPMENT_TARGET_LOCK_LOST', message: string, options?: ErrorOptions);
|
|
6
|
-
}
|
|
7
|
-
/** Exclude local sessions targeting one installed Domain across separate checkouts. */
|
|
8
|
-
export declare function acquireDevelopmentTargetLock(input: {
|
|
9
|
-
readonly issuer: string;
|
|
10
|
-
readonly origin: string;
|
|
11
|
-
}, dependencies?: {
|
|
12
|
-
readonly root?: string;
|
|
13
|
-
readonly pid?: number;
|
|
14
|
-
readonly sessionId?: string;
|
|
15
|
-
readonly processAlive?: (pid: number) => boolean;
|
|
16
|
-
}): Promise<DevelopmentLease>;
|