@astrale-os/adapter-cloudflare 0.5.0-beta.8 → 0.5.0-beta.80
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/CHANGELOG.md +983 -0
- package/README.md +20 -2
- package/dist/adapter.d.ts +15 -0
- package/dist/adapter.js +76 -0
- package/dist/build/artifact.d.ts +7 -0
- package/dist/build/artifact.js +165 -0
- package/dist/build/bundle/admit.d.ts +1 -0
- package/dist/build/bundle/admit.js +9 -0
- package/dist/build/closure.d.ts +2 -0
- package/dist/build/closure.js +22 -0
- package/dist/build/codegen/execution.d.ts +3 -0
- package/dist/build/codegen/execution.js +2 -0
- package/dist/build/codegen/merge.d.ts +0 -1
- package/dist/build/codegen/merge.js +0 -1
- package/dist/build/codegen/wrangler.d.ts +13 -1
- package/dist/build/codegen/wrangler.js +35 -18
- package/dist/build/configuration/addressing.d.ts +2 -0
- package/dist/build/configuration/addressing.js +11 -0
- package/dist/build/configuration/invocation-timeout.d.ts +2 -0
- package/dist/build/configuration/invocation-timeout.js +9 -0
- package/dist/build/configuration/request-limit.d.ts +2 -0
- package/dist/build/configuration/request-limit.js +9 -0
- package/dist/build/configuration/router.d.ts +7 -0
- package/dist/build/configuration/router.js +11 -0
- package/dist/build/configuration/worker-name.d.ts +2 -0
- package/dist/build/configuration/worker-name.js +18 -0
- package/dist/build/configuration.d.ts +5 -0
- package/dist/build/configuration.js +5 -0
- package/dist/build/direct.d.ts +4 -0
- package/dist/build/direct.js +93 -0
- package/dist/build/frontend/files.d.ts +7 -0
- package/dist/build/frontend/files.js +60 -0
- package/dist/build/frontend/routes.d.ts +2 -0
- package/dist/build/frontend/routes.js +11 -0
- package/dist/build/index.d.ts +10 -16
- package/dist/build/index.js +9 -16
- package/dist/build/materialize.d.ts +4 -0
- package/dist/build/materialize.js +10 -0
- package/dist/build/metafile.d.ts +5 -0
- package/dist/build/metafile.js +14 -0
- package/dist/build/qualification.d.ts +5 -0
- package/dist/build/qualification.js +7 -0
- package/dist/build/roots.d.ts +2 -0
- package/dist/build/roots.js +34 -0
- package/dist/build/worker/artifact.d.ts +40 -0
- package/dist/build/worker/artifact.js +1 -0
- package/dist/build/worker/artifact.load.d.ts +3 -0
- package/dist/build/worker/artifact.load.js +308 -0
- package/dist/build/worker/artifact.manifest.d.ts +48 -0
- package/dist/build/worker/artifact.manifest.js +87 -0
- package/dist/build/worker/artifact.paths.d.ts +4 -0
- package/dist/build/worker/artifact.paths.js +25 -0
- package/dist/build/worker/codegen/entry.d.ts +2 -0
- package/dist/build/worker/codegen/entry.js +28 -0
- package/dist/build/worker/codegen/service.d.ts +16 -0
- package/dist/build/worker/codegen/service.js +52 -0
- package/dist/build/worker/execution.prepare.d.ts +18 -0
- package/dist/build/worker/execution.prepare.js +109 -0
- package/dist/build/worker/index.d.ts +2 -0
- package/dist/build/worker/index.js +1 -0
- package/dist/build/worker/modules.d.ts +11 -0
- package/dist/build/worker/modules.js +26 -0
- package/dist/build/worker/runtime.d.ts +10 -0
- package/dist/build/worker/runtime.js +35 -0
- package/dist/build/worker/specifier.d.ts +1 -0
- package/dist/build/worker/specifier.js +5 -0
- package/dist/cloudflare.d.ts +1 -34
- package/dist/cloudflare.js +1 -205
- package/dist/deploy/deploy.d.ts +16 -0
- package/dist/deploy/deploy.js +204 -0
- package/dist/deploy/index.d.ts +1 -0
- package/dist/deploy/index.js +1 -0
- package/dist/deploy/output.d.ts +2 -0
- package/dist/deploy/output.js +10 -0
- package/dist/development/develop.d.ts +15 -0
- package/dist/development/develop.js +267 -0
- package/dist/development/frontend.d.ts +11 -0
- package/dist/development/frontend.js +109 -0
- package/dist/development/host.d.ts +2 -0
- package/dist/development/host.js +46 -0
- package/dist/development/port.d.ts +1 -0
- package/dist/development/port.js +12 -0
- package/dist/development/readiness.d.ts +14 -0
- package/dist/development/readiness.js +71 -0
- package/dist/development/resolved-fetch.d.ts +17 -0
- package/dist/development/resolved-fetch.js +80 -0
- package/dist/development/worker-output.d.ts +2 -0
- package/dist/development/worker-output.js +25 -0
- package/dist/development/worker.d.ts +17 -0
- package/dist/development/worker.js +147 -0
- package/dist/identity/binding.d.ts +2 -0
- package/dist/identity/binding.js +2 -0
- package/dist/identity/material.d.ts +7 -0
- package/dist/identity/material.js +42 -0
- package/dist/identity/secret.d.ts +3 -0
- package/dist/identity/secret.js +7 -0
- package/dist/identity/source.d.ts +26 -0
- package/dist/identity/source.js +127 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/params.d.ts +32 -7
- package/dist/params.js +0 -1
- package/dist/release/deployment.d.ts +44 -0
- package/dist/release/deployment.js +141 -0
- package/dist/release/index.d.ts +2 -0
- package/dist/release/index.js +2 -0
- package/dist/release/staged-worker-name.d.ts +3 -0
- package/dist/release/staged-worker-name.js +10 -0
- package/dist/worker/entry.d.ts +43 -0
- package/dist/worker/entry.js +181 -0
- package/dist/worker/fetch.d.ts +0 -1
- package/dist/worker/fetch.js +0 -1
- package/dist/worker/identity.d.ts +7 -0
- package/dist/worker/identity.js +23 -0
- package/dist/worker/index.d.ts +2 -61
- package/dist/worker/index.js +2 -212
- package/dist/wrangler/bundle.d.ts +10 -0
- package/dist/wrangler/bundle.js +27 -0
- package/dist/wrangler/deploy.d.ts +24 -0
- package/dist/wrangler/deploy.js +44 -0
- package/dist/wrangler/index.d.ts +5 -0
- package/dist/wrangler/index.js +5 -0
- package/dist/wrangler/process.d.ts +17 -0
- package/dist/wrangler/process.js +115 -0
- package/dist/wrangler/secrets.d.ts +6 -0
- package/dist/wrangler/secrets.js +58 -0
- package/dist/wrangler/status.d.ts +14 -0
- package/dist/wrangler/status.js +56 -0
- package/dist/wrangler/type-generation.d.ts +6 -0
- package/dist/wrangler/type-generation.js +19 -0
- package/package.json +30 -19
- package/template/astrale.config.ts +25 -17
- package/dist/build/codegen/identity.d.ts +0 -10
- package/dist/build/codegen/identity.d.ts.map +0 -1
- package/dist/build/codegen/identity.js +0 -32
- package/dist/build/codegen/identity.js.map +0 -1
- package/dist/build/codegen/merge.d.ts.map +0 -1
- package/dist/build/codegen/merge.js.map +0 -1
- package/dist/build/codegen/worker.d.ts +0 -12
- package/dist/build/codegen/worker.d.ts.map +0 -1
- package/dist/build/codegen/worker.js +0 -40
- package/dist/build/codegen/worker.js.map +0 -1
- package/dist/build/codegen/wrangler.d.ts.map +0 -1
- package/dist/build/codegen/wrangler.js.map +0 -1
- package/dist/build/frontend.d.ts +0 -26
- package/dist/build/frontend.d.ts.map +0 -1
- package/dist/build/frontend.js +0 -263
- package/dist/build/frontend.js.map +0 -1
- package/dist/build/index.d.ts.map +0 -1
- package/dist/build/index.js.map +0 -1
- package/dist/build/parse-output.d.ts +0 -27
- package/dist/build/parse-output.d.ts.map +0 -1
- package/dist/build/parse-output.js +0 -58
- package/dist/build/parse-output.js.map +0 -1
- package/dist/build/prepare.d.ts +0 -18
- package/dist/build/prepare.d.ts.map +0 -1
- package/dist/build/prepare.js +0 -117
- package/dist/build/prepare.js.map +0 -1
- package/dist/build/worker.d.ts +0 -15
- package/dist/build/worker.d.ts.map +0 -1
- package/dist/build/worker.js +0 -21
- package/dist/build/worker.js.map +0 -1
- package/dist/build/wrangler-cli.d.ts +0 -88
- package/dist/build/wrangler-cli.d.ts.map +0 -1
- package/dist/build/wrangler-cli.js +0 -283
- package/dist/build/wrangler-cli.js.map +0 -1
- package/dist/cloudflare.d.ts.map +0 -1
- package/dist/cloudflare.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/params.d.ts.map +0 -1
- package/dist/params.js.map +0 -1
- package/dist/worker/fetch.d.ts.map +0 -1
- package/dist/worker/fetch.js.map +0 -1
- package/dist/worker/index.d.ts.map +0 -1
- package/dist/worker/index.js.map +0 -1
- package/src/build/codegen/identity.ts +0 -40
- package/src/build/codegen/merge.ts +0 -92
- package/src/build/codegen/worker.ts +0 -53
- package/src/build/codegen/wrangler.ts +0 -127
- package/src/build/frontend.ts +0 -324
- package/src/build/index.ts +0 -29
- package/src/build/parse-output.ts +0 -60
- package/src/build/prepare.ts +0 -161
- package/src/build/worker.ts +0 -37
- package/src/build/wrangler-cli.ts +0 -372
- package/src/cloudflare.ts +0 -251
- package/src/index.ts +0 -21
- package/src/params.ts +0 -92
- package/src/worker/fetch.ts +0 -46
- package/src/worker/index.ts +0 -325
- package/src/worker/tsconfig.json +0 -10
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
3
|
+
import { SIGNING_IDENTITY_BINDING } from '../../identity/binding.js';
|
|
4
|
+
import { runWranglerBundle } from '../../wrangler/bundle.js';
|
|
5
|
+
import { admitWorkerBundle } from '../bundle/admit.js';
|
|
6
|
+
import { generateExecutionEntry, generateExecutionService } from '../codegen/execution.js';
|
|
7
|
+
import { generateWranglerConfig } from '../codegen/wrangler.js';
|
|
8
|
+
import { workerInvocationTimeout, workerRequestLimit } from '../configuration.js';
|
|
9
|
+
import { qualifyWorkerBundle } from '../qualification.js';
|
|
10
|
+
import { workerModuleSpecifier } from './specifier.js';
|
|
11
|
+
export const RELEASE_ENTRY = 'bundle/index.mjs';
|
|
12
|
+
export const RELEASE_SERVICE = 'bundle/service.mjs';
|
|
13
|
+
export async function prepareExecution(input) {
|
|
14
|
+
const runtimePath = resolve(input.context.projectDir, input.context.runtime.reference.path);
|
|
15
|
+
const runtimeSpecifier = moduleSpecifier(relative(input.directory, runtimePath));
|
|
16
|
+
const workerSpecifier = workerModuleSpecifier();
|
|
17
|
+
const maximumRequestBytes = workerRequestLimit(input.params.maximumRequestBytes);
|
|
18
|
+
const invocationTimeoutMs = workerInvocationTimeout(input.params.invocationTimeoutMs);
|
|
19
|
+
const serviceSource = generateExecutionService({
|
|
20
|
+
origin: input.context.build.schema.compiled.root.origin,
|
|
21
|
+
runtimeSpecifier,
|
|
22
|
+
workerSpecifier,
|
|
23
|
+
build: input.context.build,
|
|
24
|
+
...(maximumRequestBytes === undefined ? {} : { maximumRequestBytes }),
|
|
25
|
+
...(invocationTimeoutMs === undefined ? {} : { invocationTimeoutMs }),
|
|
26
|
+
...(input.configuredIssuer === undefined && input.direct
|
|
27
|
+
? { providerAssignedWorker: input.name }
|
|
28
|
+
: {}),
|
|
29
|
+
...(input.router === undefined
|
|
30
|
+
? {}
|
|
31
|
+
: {
|
|
32
|
+
router: {
|
|
33
|
+
binding: input.router.binding,
|
|
34
|
+
hostSuffix: input.router.hostSuffix,
|
|
35
|
+
minLabels: input.router.minLabels,
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
39
|
+
const serviceSourcePath = join(input.directory, 'service.gen.ts');
|
|
40
|
+
await writeFile(serviceSourcePath, serviceSource);
|
|
41
|
+
const serviceConfigPath = join(input.directory, 'wrangler.service.prepare.jsonc');
|
|
42
|
+
await writeFile(serviceConfigPath, generateWranglerConfig({
|
|
43
|
+
workerName: input.name,
|
|
44
|
+
main: './service.gen.ts',
|
|
45
|
+
vars: runtimeVars(input.params, input.configuredIssuer),
|
|
46
|
+
secretBindings: [SIGNING_IDENTITY_BINDING],
|
|
47
|
+
...(input.router === undefined
|
|
48
|
+
? {}
|
|
49
|
+
: { router: { binding: input.router.binding, service: input.router.service } }),
|
|
50
|
+
...(input.params.wrangler === undefined ? {} : { wrangler: input.params.wrangler }),
|
|
51
|
+
selfBinding: false,
|
|
52
|
+
}));
|
|
53
|
+
const serviceOutput = join(input.directory, 'dist-service');
|
|
54
|
+
await rm(serviceOutput, { recursive: true, force: true });
|
|
55
|
+
const emittedService = await runWranglerBundle({
|
|
56
|
+
projectDir: input.context.projectDir,
|
|
57
|
+
configPath: serviceConfigPath,
|
|
58
|
+
outDir: serviceOutput,
|
|
59
|
+
});
|
|
60
|
+
await qualifyWorkerBundle({
|
|
61
|
+
metafilePath: emittedService.metafilePath,
|
|
62
|
+
inputRoot: dirname(serviceConfigPath),
|
|
63
|
+
});
|
|
64
|
+
await admitWorkerBundle(emittedService.bundlePath);
|
|
65
|
+
const service = new Uint8Array(await readFile(emittedService.bundlePath));
|
|
66
|
+
await mkdir(dirname(join(input.directory, RELEASE_SERVICE)), { recursive: true });
|
|
67
|
+
await writeFile(join(input.directory, RELEASE_SERVICE), service);
|
|
68
|
+
const sourcePath = join(input.directory, 'worker.gen.ts');
|
|
69
|
+
await writeFile(sourcePath, generateExecutionEntry('./service.mjs', workerSpecifier));
|
|
70
|
+
const configPath = join(input.directory, 'wrangler.prepare.jsonc');
|
|
71
|
+
await writeFile(configPath, generateWranglerConfig({
|
|
72
|
+
workerName: input.name,
|
|
73
|
+
...(input.params.route === undefined ? {} : { route: input.params.route }),
|
|
74
|
+
vars: runtimeVars(input.params, input.configuredIssuer),
|
|
75
|
+
secretBindings: [SIGNING_IDENTITY_BINDING],
|
|
76
|
+
modules: { baseDir: '.', rules: [{ type: 'ESModule', globs: [RELEASE_SERVICE] }] },
|
|
77
|
+
...(input.router === undefined
|
|
78
|
+
? {}
|
|
79
|
+
: { router: { binding: input.router.binding, service: input.router.service } }),
|
|
80
|
+
...(input.params.wrangler === undefined ? {} : { wrangler: input.params.wrangler }),
|
|
81
|
+
selfBinding: false,
|
|
82
|
+
}));
|
|
83
|
+
const output = join(input.directory, 'dist-prepare');
|
|
84
|
+
await rm(output, { recursive: true, force: true });
|
|
85
|
+
const emitted = await runWranglerBundle({
|
|
86
|
+
projectDir: input.context.projectDir,
|
|
87
|
+
configPath,
|
|
88
|
+
outDir: output,
|
|
89
|
+
});
|
|
90
|
+
await qualifyWorkerBundle({
|
|
91
|
+
metafilePath: emitted.metafilePath,
|
|
92
|
+
inputRoot: dirname(configPath),
|
|
93
|
+
});
|
|
94
|
+
await admitWorkerBundle(emitted.bundlePath);
|
|
95
|
+
return Object.freeze({
|
|
96
|
+
entry: new Uint8Array(await readFile(emitted.bundlePath)),
|
|
97
|
+
service,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
export function runtimeVars(params, configuredIssuer) {
|
|
101
|
+
return {
|
|
102
|
+
...params.vars,
|
|
103
|
+
...(configuredIssuer === undefined ? {} : { WORKER_URL: configuredIssuer }),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function moduleSpecifier(input) {
|
|
107
|
+
const normalized = input.split('\\').join('/');
|
|
108
|
+
return normalized.startsWith('.') ? normalized : `./${normalized}`;
|
|
109
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { loadWorkerArtifact } from './artifact.load.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { WorkerArtifact } from './artifact.js';
|
|
2
|
+
type WranglerModuleType = 'ESModule' | 'CompiledWasm' | 'Text' | 'Data';
|
|
3
|
+
/** Project one admitted Worker module inventory into Wrangler's relative module discovery. */
|
|
4
|
+
export declare function workerModules(worker: WorkerArtifact['release']): {
|
|
5
|
+
readonly baseDir: string;
|
|
6
|
+
readonly rules: readonly {
|
|
7
|
+
readonly type: WranglerModuleType;
|
|
8
|
+
readonly globs: readonly string[];
|
|
9
|
+
}[];
|
|
10
|
+
};
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { posix } from 'node:path';
|
|
2
|
+
const TYPES = Object.freeze({
|
|
3
|
+
esm: 'ESModule',
|
|
4
|
+
wasm: 'CompiledWasm',
|
|
5
|
+
text: 'Text',
|
|
6
|
+
data: 'Data',
|
|
7
|
+
});
|
|
8
|
+
/** Project one admitted Worker module inventory into Wrangler's relative module discovery. */
|
|
9
|
+
export function workerModules(worker) {
|
|
10
|
+
const directory = posix.dirname(worker.entrypoint);
|
|
11
|
+
const groups = new Map();
|
|
12
|
+
for (const module of worker.modules) {
|
|
13
|
+
if (module.path === worker.entrypoint)
|
|
14
|
+
continue;
|
|
15
|
+
const relative = posix.relative(directory, module.path);
|
|
16
|
+
if (relative === '' || relative === '..' || relative.startsWith('../')) {
|
|
17
|
+
throw new TypeError('Cloudflare Worker module escapes its entrypoint directory.');
|
|
18
|
+
}
|
|
19
|
+
const type = TYPES[module.kind];
|
|
20
|
+
const globs = groups.get(type) ?? [];
|
|
21
|
+
globs.push(relative);
|
|
22
|
+
groups.set(type, globs);
|
|
23
|
+
}
|
|
24
|
+
const rules = [...groups].map(([type, globs]) => Object.freeze({ type, globs: Object.freeze(globs) }));
|
|
25
|
+
return Object.freeze({ baseDir: `./${directory}`, rules: Object.freeze(rules) });
|
|
26
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface WorkerRuntimeConfiguration {
|
|
2
|
+
readonly compatibilityDate: string;
|
|
3
|
+
readonly compatibilityFlags: readonly string[];
|
|
4
|
+
readonly vars: Readonly<Record<string, string>>;
|
|
5
|
+
readonly services: readonly {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly service: string;
|
|
8
|
+
}[];
|
|
9
|
+
}
|
|
10
|
+
export declare function admitWorkerRuntimeConfiguration(input: string): WorkerRuntimeConfiguration;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function admitWorkerRuntimeConfiguration(input) {
|
|
2
|
+
const value = JSON.parse(input);
|
|
3
|
+
const compatibilityDate = value.compatibility_date;
|
|
4
|
+
const compatibilityFlags = value.compatibility_flags;
|
|
5
|
+
const vars = value.vars ?? {};
|
|
6
|
+
const services = value.services ?? [];
|
|
7
|
+
if (typeof compatibilityDate !== 'string' ||
|
|
8
|
+
!Array.isArray(compatibilityFlags) ||
|
|
9
|
+
compatibilityFlags.some((flag) => typeof flag !== 'string') ||
|
|
10
|
+
vars === null ||
|
|
11
|
+
typeof vars !== 'object' ||
|
|
12
|
+
Array.isArray(vars) ||
|
|
13
|
+
Object.values(vars).some((item) => typeof item !== 'string') ||
|
|
14
|
+
!Array.isArray(services)) {
|
|
15
|
+
invalidRuntime();
|
|
16
|
+
}
|
|
17
|
+
const admittedServices = services.map((input) => {
|
|
18
|
+
if (input === null || typeof input !== 'object' || Array.isArray(input))
|
|
19
|
+
invalidRuntime();
|
|
20
|
+
const binding = Reflect.get(input, 'binding');
|
|
21
|
+
const service = Reflect.get(input, 'service');
|
|
22
|
+
if (typeof binding !== 'string' || typeof service !== 'string')
|
|
23
|
+
invalidRuntime();
|
|
24
|
+
return Object.freeze({ name: binding, service });
|
|
25
|
+
});
|
|
26
|
+
return Object.freeze({
|
|
27
|
+
compatibilityDate,
|
|
28
|
+
compatibilityFlags: Object.freeze([...compatibilityFlags]),
|
|
29
|
+
vars: Object.freeze({ ...vars }),
|
|
30
|
+
services: Object.freeze(admittedServices),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function invalidRuntime() {
|
|
34
|
+
throw new TypeError('Generated Cloudflare runtime configuration is invalid.');
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function workerModuleSpecifier(): string;
|
package/dist/cloudflare.d.ts
CHANGED
|
@@ -1,34 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* `cloudflare(envs)` — the Cloudflare deployment adapter.
|
|
3
|
-
*
|
|
4
|
-
* Owns everything target-specific: it codegens the Worker entry + wrangler
|
|
5
|
-
* config (the dev never sees a `wrangler.jsonc`), materializes the optional frontend
|
|
6
|
-
* SPA, and shells out to `wrangler`. `watch` → `wrangler dev` (local URL);
|
|
7
|
-
* `deploy` → `wrangler deploy` (workers.dev or a custom-domain URL); secrets →
|
|
8
|
-
* `wrangler secret bulk`. Both `watch` and `deploy` return the URL the CLI
|
|
9
|
-
* prints and `astrale domain install <url>` consumes.
|
|
10
|
-
*/
|
|
11
|
-
import type { DomainAdapter } from '@astrale-os/sdk';
|
|
12
|
-
import type { CloudflareParams } from './params.js';
|
|
13
|
-
import { bulkPutSecrets, buildCloudflareWorker, buildFrontend, logTo, prepare, runWranglerDeploy, runWranglerDev, runWranglerTypes, watchFrontend } from './build/index.js';
|
|
14
|
-
export declare function cloudflare(envs: Record<string, CloudflareParams>): DomainAdapter<CloudflareParams>;
|
|
15
|
-
interface CloudflareAdapterDependencies {
|
|
16
|
-
readonly bulkPutSecrets: typeof bulkPutSecrets;
|
|
17
|
-
readonly buildCloudflareWorker: typeof buildCloudflareWorker;
|
|
18
|
-
readonly buildFrontend: typeof buildFrontend;
|
|
19
|
-
readonly logTo: typeof logTo;
|
|
20
|
-
readonly prepare: typeof prepare;
|
|
21
|
-
readonly runWranglerDeploy: typeof runWranglerDeploy;
|
|
22
|
-
readonly runWranglerDev: typeof runWranglerDev;
|
|
23
|
-
readonly runWranglerTypes: typeof runWranglerTypes;
|
|
24
|
-
readonly watchFrontend: typeof watchFrontend;
|
|
25
|
-
readonly waitUntilLive: typeof waitUntilLive;
|
|
26
|
-
}
|
|
27
|
-
/** Exact orchestration seam used by adapter-level deployment qualification. */
|
|
28
|
-
export declare function cloudflareWithDependencies(envs: Record<string, CloudflareParams>, dependencies: CloudflareAdapterDependencies): DomainAdapter<CloudflareParams>;
|
|
29
|
-
/**
|
|
30
|
-
* Poll until the deployed Worker health endpoint returns exactly 200.
|
|
31
|
-
*/
|
|
32
|
-
declare function waitUntilLive(url: string, onLog: (line: string) => void, expectedDeploymentVersion?: string, timeoutMs?: number): Promise<void>;
|
|
33
|
-
export {};
|
|
34
|
-
//# sourceMappingURL=cloudflare.d.ts.map
|
|
1
|
+
export { cloudflare } from './adapter.js';
|
package/dist/cloudflare.js
CHANGED
|
@@ -1,205 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* `cloudflare(envs)` — the Cloudflare deployment adapter.
|
|
3
|
-
*
|
|
4
|
-
* Owns everything target-specific: it codegens the Worker entry + wrangler
|
|
5
|
-
* config (the dev never sees a `wrangler.jsonc`), materializes the optional frontend
|
|
6
|
-
* SPA, and shells out to `wrangler`. `watch` → `wrangler dev` (local URL);
|
|
7
|
-
* `deploy` → `wrangler deploy` (workers.dev or a custom-domain URL); secrets →
|
|
8
|
-
* `wrangler secret bulk`. Both `watch` and `deploy` return the URL the CLI
|
|
9
|
-
* prints and `astrale domain install <url>` consumes.
|
|
10
|
-
*/
|
|
11
|
-
import { defineAdapter } from '@astrale-os/sdk';
|
|
12
|
-
import { bulkPutSecrets, buildCloudflareWorker, buildFrontend, logTo, prepare, runWranglerDeploy, runWranglerDev, runWranglerTypes, watchFrontend, } from './build/index.js';
|
|
13
|
-
export function cloudflare(envs) {
|
|
14
|
-
return cloudflareWithDependencies(envs, {
|
|
15
|
-
bulkPutSecrets,
|
|
16
|
-
buildCloudflareWorker,
|
|
17
|
-
buildFrontend,
|
|
18
|
-
logTo,
|
|
19
|
-
prepare,
|
|
20
|
-
runWranglerDeploy,
|
|
21
|
-
runWranglerDev,
|
|
22
|
-
runWranglerTypes,
|
|
23
|
-
watchFrontend,
|
|
24
|
-
waitUntilLive,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
/** Exact orchestration seam used by adapter-level deployment qualification. */
|
|
28
|
-
export function cloudflareWithDependencies(envs, dependencies) {
|
|
29
|
-
return defineAdapter({
|
|
30
|
-
name: 'cloudflare',
|
|
31
|
-
envs,
|
|
32
|
-
async build(params, ctx) {
|
|
33
|
-
await dependencies.buildCloudflareWorker({
|
|
34
|
-
params,
|
|
35
|
-
context: ctx,
|
|
36
|
-
onLog: dependencies.logTo(),
|
|
37
|
-
});
|
|
38
|
-
},
|
|
39
|
-
async watch(params, ctx) {
|
|
40
|
-
const onLog = dependencies.logTo();
|
|
41
|
-
const frontend = await dependencies.buildFrontend({
|
|
42
|
-
definition: ctx.definition,
|
|
43
|
-
projectDir: ctx.projectDir,
|
|
44
|
-
onLog,
|
|
45
|
-
});
|
|
46
|
-
const { configPath, port } = await dependencies.prepare(params, ctx, 'dev', frontend);
|
|
47
|
-
const handle = await dependencies.runWranglerDev({
|
|
48
|
-
projectDir: ctx.projectDir,
|
|
49
|
-
configPath,
|
|
50
|
-
port,
|
|
51
|
-
remote: Boolean(params.remote),
|
|
52
|
-
autoPickPort: params.port === undefined,
|
|
53
|
-
...(params.host ? { ip: '0.0.0.0' } : {}),
|
|
54
|
-
onReload: ctx.onReload,
|
|
55
|
-
onLog,
|
|
56
|
-
});
|
|
57
|
-
let frontendWatch;
|
|
58
|
-
try {
|
|
59
|
-
frontendWatch = dependencies.watchFrontend({
|
|
60
|
-
definition: ctx.definition,
|
|
61
|
-
projectDir: ctx.projectDir,
|
|
62
|
-
onLog,
|
|
63
|
-
// Routes and source recipes are immutable for this watch generation.
|
|
64
|
-
// Wrangler already observes the atomically swapped asset stage, so a
|
|
65
|
-
// source rebuild needs no config regeneration.
|
|
66
|
-
onRebuild: ctx.onReload,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
try {
|
|
71
|
-
await handle.stop();
|
|
72
|
-
}
|
|
73
|
-
catch (cleanupError) {
|
|
74
|
-
throw new AggregateError([error, cleanupError], 'cloudflare frontend watcher startup failed and Wrangler cleanup also failed');
|
|
75
|
-
}
|
|
76
|
-
throw error;
|
|
77
|
-
}
|
|
78
|
-
// With --host the actionable URL is the PUBLIC one (the tunnel/proxy
|
|
79
|
-
// front), not the local bind — print and spec-stamp that.
|
|
80
|
-
return {
|
|
81
|
-
url: params.host ?? handle.url,
|
|
82
|
-
async stop() {
|
|
83
|
-
const errors = [];
|
|
84
|
-
try {
|
|
85
|
-
await frontendWatch?.stop();
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
errors.push(error);
|
|
89
|
-
}
|
|
90
|
-
try {
|
|
91
|
-
await handle.stop();
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
errors.push(error);
|
|
95
|
-
}
|
|
96
|
-
if (errors.length === 1)
|
|
97
|
-
throw errors[0];
|
|
98
|
-
if (errors.length > 1) {
|
|
99
|
-
throw new AggregateError(errors, 'cloudflare development cleanup failed');
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
},
|
|
104
|
-
// Config hot-regen: rewrite the generated files only — the running
|
|
105
|
-
// `wrangler dev` watches its `--config` (and the worker entry) and reloads
|
|
106
|
-
// them itself, so a `astrale.config.ts` edit lands without a restart.
|
|
107
|
-
// Mirrors `watch`'s prep exactly (codegen + frontend build), minus the spawn.
|
|
108
|
-
async regenerate(params, ctx) {
|
|
109
|
-
const frontend = await dependencies.buildFrontend({
|
|
110
|
-
definition: ctx.definition,
|
|
111
|
-
projectDir: ctx.projectDir,
|
|
112
|
-
onLog: dependencies.logTo(),
|
|
113
|
-
});
|
|
114
|
-
const { configPath } = await dependencies.prepare(params, ctx, 'dev', frontend);
|
|
115
|
-
await dependencies.runWranglerTypes({
|
|
116
|
-
projectDir: ctx.projectDir,
|
|
117
|
-
configPath,
|
|
118
|
-
onLog: dependencies.logTo(),
|
|
119
|
-
});
|
|
120
|
-
},
|
|
121
|
-
async deploy(params, ctx) {
|
|
122
|
-
const frontend = await dependencies.buildFrontend({
|
|
123
|
-
definition: ctx.definition,
|
|
124
|
-
projectDir: ctx.projectDir,
|
|
125
|
-
onLog: dependencies.logTo(),
|
|
126
|
-
});
|
|
127
|
-
const { configPath, fallbackConfigPath, workerName: name, } = await dependencies.prepare(params, ctx, 'deploy', frontend);
|
|
128
|
-
const { url, deploymentVersion } = await dependencies.runWranglerDeploy({
|
|
129
|
-
projectDir: ctx.projectDir,
|
|
130
|
-
configPath,
|
|
131
|
-
workerName: name,
|
|
132
|
-
...(fallbackConfigPath ? { fallbackConfigPath } : {}),
|
|
133
|
-
...(params.route ? { route: params.route } : {}),
|
|
134
|
-
onLog: dependencies.logTo(),
|
|
135
|
-
});
|
|
136
|
-
if (Object.keys(ctx.secrets).length > 0) {
|
|
137
|
-
await dependencies.bulkPutSecrets({
|
|
138
|
-
projectDir: ctx.projectDir,
|
|
139
|
-
configPath,
|
|
140
|
-
secrets: ctx.secrets,
|
|
141
|
-
onLog: dependencies.logTo(),
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
// A first deploy on a fresh `*.workers.dev` host can take ~30-60s to
|
|
145
|
-
// propagate; an `astrale domain install <url>` issued right away would
|
|
146
|
-
// 404 (Cloudflare 1042). Block until the URL actually serves so the
|
|
147
|
-
// install line we print is immediately actionable.
|
|
148
|
-
await dependencies.waitUntilLive(url, dependencies.logTo(), deploymentVersion);
|
|
149
|
-
return { url };
|
|
150
|
-
},
|
|
151
|
-
secretsFile(params) {
|
|
152
|
-
return params.secrets;
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Poll until the deployed Worker health endpoint returns exactly 200.
|
|
158
|
-
*/
|
|
159
|
-
async function waitUntilLive(url, onLog, expectedDeploymentVersion, timeoutMs = 90_000) {
|
|
160
|
-
const probe = new URL('/health', url);
|
|
161
|
-
const metadata = new URL('/meta', url);
|
|
162
|
-
const deadline = Date.now() + timeoutMs;
|
|
163
|
-
let waited = false;
|
|
164
|
-
let lastStatus;
|
|
165
|
-
let lastDeploymentVersion;
|
|
166
|
-
for (;;) {
|
|
167
|
-
try {
|
|
168
|
-
const res = await fetch(probe, { redirect: 'manual' });
|
|
169
|
-
lastStatus = res.status;
|
|
170
|
-
await res.body?.cancel();
|
|
171
|
-
if (res.status === 200) {
|
|
172
|
-
if (expectedDeploymentVersion === undefined)
|
|
173
|
-
return;
|
|
174
|
-
const meta = await fetch(metadata, { redirect: 'manual' });
|
|
175
|
-
if (meta.status === 200) {
|
|
176
|
-
const body = (await meta.json());
|
|
177
|
-
lastDeploymentVersion =
|
|
178
|
-
typeof body.deploymentVersion === 'string' ? body.deploymentVersion : undefined;
|
|
179
|
-
if (lastDeploymentVersion === expectedDeploymentVersion)
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
await meta.body?.cancel();
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
catch {
|
|
188
|
-
// Network hiccup — treat like "not live yet" and keep polling.
|
|
189
|
-
}
|
|
190
|
-
if (Date.now() >= deadline) {
|
|
191
|
-
throw new Error(`deployed Worker health did not reach HTTP 200 within ${Math.round(timeoutMs / 1000)}s` +
|
|
192
|
-
(lastStatus === undefined ? '' : ` (last status ${lastStatus})`) +
|
|
193
|
-
(expectedDeploymentVersion === undefined
|
|
194
|
-
? ''
|
|
195
|
-
: `; deployment version ${JSON.stringify(lastDeploymentVersion)} ` +
|
|
196
|
-
`did not reach ${JSON.stringify(expectedDeploymentVersion)}`));
|
|
197
|
-
}
|
|
198
|
-
if (!waited) {
|
|
199
|
-
waited = true;
|
|
200
|
-
onLog('waiting for the URL to go live (first deploys can take ~30-60s)…');
|
|
201
|
-
}
|
|
202
|
-
await new Promise((r) => setTimeout(r, 3000));
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
//# sourceMappingURL=cloudflare.js.map
|
|
1
|
+
export { cloudflare } from './adapter.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DeployContext, DeployResult } from '@astrale-os/sdk/deployment/adapter';
|
|
2
|
+
import type { Release } from '@astrale-os/sdk/deployment/release';
|
|
3
|
+
import type { materialize } from '../build/artifact.js';
|
|
4
|
+
import type { signingIdentity } from '../identity/source.js';
|
|
5
|
+
import type { CloudflareParams } from '../params.js';
|
|
6
|
+
import type { runWranglerDeploy } from '../wrangler/deploy.js';
|
|
7
|
+
import type { runWranglerDeploymentStatus } from '../wrangler/status.js';
|
|
8
|
+
export interface CloudflareDeployDependencies {
|
|
9
|
+
readonly materialize: typeof materialize;
|
|
10
|
+
readonly runWranglerDeploy: typeof runWranglerDeploy;
|
|
11
|
+
readonly runWranglerDeploymentStatus: typeof runWranglerDeploymentStatus;
|
|
12
|
+
readonly waitForReadiness: (release: Release, signal: AbortSignal) => Promise<void>;
|
|
13
|
+
readonly signingIdentity: typeof signingIdentity;
|
|
14
|
+
}
|
|
15
|
+
/** Atomically advance one stable Worker address to the prepared implementation. */
|
|
16
|
+
export declare function deployCloudflare(parameters: CloudflareParams, context: DeployContext, dependencies: CloudflareDeployDependencies): Promise<DeployResult>;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { addressing, assemble } from '@astrale-os/sdk/deployment/release';
|
|
2
|
+
import { mkdir, mkdtemp, rm } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { workerName } from '../build/configuration.js';
|
|
5
|
+
import { admitDirectPlacement } from '../build/direct.js';
|
|
6
|
+
import { loadWorkerArtifact } from '../build/worker/index.js';
|
|
7
|
+
import { signingIdentitySecrets } from '../identity/secret.js';
|
|
8
|
+
import { WranglerDeployError } from '../wrangler/deploy.js';
|
|
9
|
+
const NONE = Object.freeze({ kind: 'none' });
|
|
10
|
+
/** Atomically advance one stable Worker address to the prepared implementation. */
|
|
11
|
+
export async function deployCloudflare(parameters, context, dependencies) {
|
|
12
|
+
let secrets;
|
|
13
|
+
try {
|
|
14
|
+
const identity = await dependencies.signingIdentity({
|
|
15
|
+
projectDir: context.projectDir,
|
|
16
|
+
source: parameters.signingIdentity,
|
|
17
|
+
origin: context.artifact.build.schema.compiled.root.origin,
|
|
18
|
+
mode: 'deploy',
|
|
19
|
+
});
|
|
20
|
+
secrets = signingIdentitySecrets(context.secrets, identity);
|
|
21
|
+
}
|
|
22
|
+
catch (cause) {
|
|
23
|
+
return failed('prerequisite', progress({}), cause);
|
|
24
|
+
}
|
|
25
|
+
let worker;
|
|
26
|
+
try {
|
|
27
|
+
worker = loadWorkerArtifact(context.artifact);
|
|
28
|
+
for (const name of worker.bindings.requiredSecrets) {
|
|
29
|
+
if (!Object.hasOwn(secrets, name)) {
|
|
30
|
+
throw new TypeError(`Cloudflare Worker requires secret ${name}.`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
admitDirectPlacement(context.artifact, worker, parameters);
|
|
34
|
+
}
|
|
35
|
+
catch (cause) {
|
|
36
|
+
return failed('prerequisite', progress({}), cause);
|
|
37
|
+
}
|
|
38
|
+
const stateDirectory = join(context.projectDir, '.astrale');
|
|
39
|
+
await mkdir(stateDirectory, { recursive: true });
|
|
40
|
+
const directory = await mkdtemp(join(stateDirectory, 'deploy-'));
|
|
41
|
+
try {
|
|
42
|
+
await dependencies.materialize(directory, context.artifact.files);
|
|
43
|
+
const name = workerName(parameters, context.artifact.build.schema.compiled.root.origin);
|
|
44
|
+
const configPath = join(directory, 'wrangler.jsonc');
|
|
45
|
+
let deployed;
|
|
46
|
+
try {
|
|
47
|
+
deployed = await dependencies.runWranglerDeploy({
|
|
48
|
+
projectDir: context.projectDir,
|
|
49
|
+
configPath,
|
|
50
|
+
secrets,
|
|
51
|
+
...(parameters.route === undefined ? {} : { route: parameters.route }),
|
|
52
|
+
signal: context.signal,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
catch (cause) {
|
|
56
|
+
return failed('provider', progress({ provider: partialProvider(cause, context.artifact) }), cause);
|
|
57
|
+
}
|
|
58
|
+
const configuration = Object.freeze({
|
|
59
|
+
kind: 'applied',
|
|
60
|
+
evidence: Object.freeze({ names: Object.keys(secrets).sort() }),
|
|
61
|
+
});
|
|
62
|
+
const retained = Object.freeze({
|
|
63
|
+
kind: 'partial',
|
|
64
|
+
evidence: Object.freeze({
|
|
65
|
+
provider: 'cloudflare',
|
|
66
|
+
deployment: deployed.deploymentVersion,
|
|
67
|
+
artifact: context.artifact.digest,
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
let selected;
|
|
71
|
+
try {
|
|
72
|
+
selected = observeAddressing(context.artifact, deployed.url, name);
|
|
73
|
+
}
|
|
74
|
+
catch (cause) {
|
|
75
|
+
return failed('addressing', progress({
|
|
76
|
+
provider: retained,
|
|
77
|
+
configuration,
|
|
78
|
+
}), cause);
|
|
79
|
+
}
|
|
80
|
+
let observed;
|
|
81
|
+
try {
|
|
82
|
+
observed = await dependencies.runWranglerDeploymentStatus({
|
|
83
|
+
projectDir: context.projectDir,
|
|
84
|
+
configPath,
|
|
85
|
+
workerName: name,
|
|
86
|
+
signal: context.signal,
|
|
87
|
+
});
|
|
88
|
+
requireCurrentDeployment(observed, deployed.deploymentVersion);
|
|
89
|
+
}
|
|
90
|
+
catch (cause) {
|
|
91
|
+
return failed('readiness', progress({
|
|
92
|
+
provider: retained,
|
|
93
|
+
configuration,
|
|
94
|
+
}), cause);
|
|
95
|
+
}
|
|
96
|
+
let release;
|
|
97
|
+
try {
|
|
98
|
+
release = assemble(context.artifact.build, selected);
|
|
99
|
+
}
|
|
100
|
+
catch (cause) {
|
|
101
|
+
return failed('release', progress({ provider: retained, configuration }), cause);
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
await dependencies.waitForReadiness(release, context.signal);
|
|
105
|
+
}
|
|
106
|
+
catch (cause) {
|
|
107
|
+
return failed('readiness', progress({ provider: retained, configuration }), cause, release);
|
|
108
|
+
}
|
|
109
|
+
const provider = Object.freeze({
|
|
110
|
+
kind: 'applied',
|
|
111
|
+
evidence: Object.freeze({
|
|
112
|
+
provider: 'cloudflare',
|
|
113
|
+
deployment: deployed.deploymentVersion,
|
|
114
|
+
artifact: context.artifact.digest,
|
|
115
|
+
issuer: selected.issuer,
|
|
116
|
+
}),
|
|
117
|
+
});
|
|
118
|
+
return Object.freeze({
|
|
119
|
+
status: 'ready',
|
|
120
|
+
phase: 'complete',
|
|
121
|
+
progress: Object.freeze({ ...progress({ configuration }), provider }),
|
|
122
|
+
release,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
await rm(directory, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function partialProvider(cause, artifact) {
|
|
130
|
+
if (!(cause instanceof WranglerDeployError) || cause.applied?.deploymentVersion === undefined) {
|
|
131
|
+
return Object.freeze({ kind: 'unknown' });
|
|
132
|
+
}
|
|
133
|
+
let issuer;
|
|
134
|
+
if (cause.applied.url !== undefined) {
|
|
135
|
+
try {
|
|
136
|
+
issuer = addressing(cause.applied.url).issuer;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// The provider effect remains known when its printed URL is not Addressing.
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return Object.freeze({
|
|
143
|
+
kind: 'partial',
|
|
144
|
+
evidence: Object.freeze({
|
|
145
|
+
provider: 'cloudflare',
|
|
146
|
+
deployment: cause.applied.deploymentVersion,
|
|
147
|
+
artifact: artifact.digest,
|
|
148
|
+
...(issuer === undefined ? {} : { issuer }),
|
|
149
|
+
}),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function requireCurrentDeployment(observed, expectedVersion) {
|
|
153
|
+
if (observed.versions.length !== 1 ||
|
|
154
|
+
observed.versions[0].percentage !== 100 ||
|
|
155
|
+
observed.versions[0].version !== expectedVersion) {
|
|
156
|
+
throw new TypeError('Cloudflare Worker is not one exact version at 100%.');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function observeAddressing(artifact, deployedUrl, expectedWorker) {
|
|
160
|
+
if (artifact.addressing.kind === 'configured') {
|
|
161
|
+
if (deployedUrl === undefined)
|
|
162
|
+
return artifact.addressing.addressing;
|
|
163
|
+
const observed = addressing(deployedUrl);
|
|
164
|
+
if (observed.issuer !== artifact.addressing.addressing.issuer) {
|
|
165
|
+
throw new TypeError('Cloudflare deployed URL differs from configured Addressing.');
|
|
166
|
+
}
|
|
167
|
+
return observed;
|
|
168
|
+
}
|
|
169
|
+
if (deployedUrl === undefined) {
|
|
170
|
+
throw new TypeError('Cloudflare did not report provider-assigned Addressing.');
|
|
171
|
+
}
|
|
172
|
+
const observed = addressing(deployedUrl);
|
|
173
|
+
if (artifact.addressing.claim !== expectedWorker) {
|
|
174
|
+
throw new TypeError('PreparedArtifact worker claim differs from the deployment target.');
|
|
175
|
+
}
|
|
176
|
+
const url = new URL(observed.issuer);
|
|
177
|
+
const labels = url.hostname.split('.');
|
|
178
|
+
if (url.protocol !== 'https:' ||
|
|
179
|
+
labels.length < 4 ||
|
|
180
|
+
labels[0] !== artifact.addressing.claim ||
|
|
181
|
+
labels.at(-2) !== 'workers' ||
|
|
182
|
+
labels.at(-1) !== 'dev') {
|
|
183
|
+
throw new TypeError('Cloudflare workers.dev URL does not satisfy its prepared worker claim.');
|
|
184
|
+
}
|
|
185
|
+
return observed;
|
|
186
|
+
}
|
|
187
|
+
function progress(input) {
|
|
188
|
+
return Object.freeze({
|
|
189
|
+
prerequisite: input.prerequisite ?? NONE,
|
|
190
|
+
provider: input.provider ?? NONE,
|
|
191
|
+
configuration: input.configuration ?? NONE,
|
|
192
|
+
installation: input.installation ?? NONE,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function failed(phase, progressValue, cause, release) {
|
|
196
|
+
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
197
|
+
return Object.freeze({
|
|
198
|
+
status: 'failed',
|
|
199
|
+
phase,
|
|
200
|
+
progress: progressValue,
|
|
201
|
+
error,
|
|
202
|
+
...(release === undefined ? {} : { release }),
|
|
203
|
+
});
|
|
204
|
+
}
|