@astrale-os/adapter-cloudflare 0.5.0-beta.3 → 0.5.0-beta.30
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 +11 -0
- package/dist/adapter.d.ts +17 -0
- package/dist/adapter.js +174 -0
- package/dist/build/artifact.d.ts +7 -0
- package/dist/build/artifact.js +150 -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/gateway.d.ts +1 -0
- package/dist/build/codegen/gateway.js +1 -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 +15 -1
- package/dist/build/codegen/wrangler.js +35 -16
- package/dist/build/configuration/addressing.d.ts +2 -0
- package/dist/build/configuration/addressing.js +11 -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 +3 -0
- package/dist/build/configuration.js +3 -0
- package/dist/build/direct.d.ts +4 -0
- package/dist/build/direct.js +52 -0
- package/dist/build/frontend/routes.d.ts +2 -0
- package/dist/build/frontend/routes.js +11 -0
- package/dist/build/frontend-v1.d.ts +16 -0
- package/dist/build/frontend-v1.js +133 -0
- package/dist/build/gateway/prepare.d.ts +8 -0
- package/dist/build/gateway/prepare.js +32 -0
- package/dist/build/gateway/source.d.ts +1 -0
- package/dist/build/gateway/source.js +7 -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/parse-output.d.ts +0 -1
- package/dist/build/parse-output.js +0 -1
- 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 +38 -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 +266 -0
- package/dist/build/worker/artifact.manifest.d.ts +46 -0
- package/dist/build/worker/artifact.manifest.js +84 -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 +13 -0
- package/dist/build/worker/codegen/service.js +44 -0
- package/dist/build/worker/execution.prepare.d.ts +18 -0
- package/dist/build/worker/execution.prepare.js +102 -0
- package/dist/build/worker/index.d.ts +2 -0
- package/dist/build/worker/index.js +1 -0
- package/dist/build/worker/runtime.d.ts +10 -0
- package/dist/build/worker/runtime.js +35 -0
- package/dist/build/wrangler/bundle.d.ts +10 -0
- package/dist/build/wrangler/bundle.js +29 -0
- package/dist/build/wrangler/deploy.d.ts +23 -0
- package/dist/build/wrangler/deploy.js +35 -0
- package/dist/build/wrangler/development.d.ts +15 -0
- package/dist/build/wrangler/development.js +135 -0
- package/dist/build/wrangler/namespace.d.ts +10 -0
- package/dist/build/wrangler/namespace.js +26 -0
- package/dist/build/wrangler/process.d.ts +15 -0
- package/dist/build/wrangler/process.js +103 -0
- package/dist/build/wrangler/release.d.ts +11 -0
- package/dist/build/wrangler/release.js +27 -0
- package/dist/build/wrangler/secrets.d.ts +6 -0
- package/dist/build/wrangler/secrets.js +58 -0
- package/dist/build/wrangler/status.d.ts +14 -0
- package/dist/build/wrangler/status.js +56 -0
- package/dist/build/wrangler/type-generation.d.ts +6 -0
- package/dist/build/wrangler/type-generation.js +19 -0
- package/dist/build/wrangler-cli.d.ts +8 -86
- package/dist/build/wrangler-cli.js +8 -275
- package/dist/cloudflare.d.ts +1 -34
- package/dist/cloudflare.js +1 -205
- package/dist/deploy/deploy.d.ts +17 -0
- package/dist/deploy/deploy.js +234 -0
- package/dist/deploy/index.d.ts +1 -0
- package/dist/deploy/index.js +1 -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 +98 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.js +3 -4
- package/dist/params.d.ts +18 -5
- package/dist/params.js +0 -1
- package/dist/release/index.d.ts +2 -0
- package/dist/release/index.js +2 -0
- package/dist/release/namespace.d.ts +2 -0
- package/dist/release/namespace.js +6 -0
- package/dist/release/target.d.ts +2 -0
- package/dist/release/target.js +9 -0
- package/dist/worker/entry.d.ts +38 -0
- package/dist/worker/entry.js +161 -0
- package/dist/worker/fetch.d.ts +11 -0
- package/dist/worker/fetch.js +31 -0
- package/dist/worker/gateway.d.ts +15 -0
- package/dist/worker/gateway.js +26 -0
- package/dist/worker/identity.d.ts +7 -0
- package/dist/worker/identity.js +23 -0
- package/dist/worker/index.d.ts +3 -59
- package/dist/worker/index.js +3 -209
- package/package.json +21 -18
- package/template/astrale.config.ts +19 -11
- 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.map +0 -1
- 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.map +0 -1
- 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/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 -362
- package/src/cloudflare.ts +0 -251
- package/src/index.ts +0 -21
- package/src/params.ts +0 -92
- package/src/worker/index.ts +0 -312
- package/src/worker/tsconfig.json +0 -10
|
@@ -1,86 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export interface DevHandle {
|
|
10
|
-
url: string;
|
|
11
|
-
stop(): Promise<void>;
|
|
12
|
-
}
|
|
13
|
-
export declare function runWranglerDev(args: {
|
|
14
|
-
projectDir: string;
|
|
15
|
-
configPath: string;
|
|
16
|
-
port: number;
|
|
17
|
-
remote: boolean;
|
|
18
|
-
/** Bind address — '0.0.0.0' for tunneled/proxied dev (`--host`). Default loopback. */
|
|
19
|
-
ip?: string;
|
|
20
|
-
/** When the port was NOT explicitly chosen, dodge a taken one automatically. */
|
|
21
|
-
autoPickPort?: boolean;
|
|
22
|
-
onReload: () => void;
|
|
23
|
-
onLog?: (line: string) => void;
|
|
24
|
-
}): Promise<DevHandle>;
|
|
25
|
-
export interface DeployArgs {
|
|
26
|
-
configPath: string;
|
|
27
|
-
/** SELF-less config for the first-deploy two-pass (see `deployWithSelfFallback`). */
|
|
28
|
-
fallbackConfigPath?: string;
|
|
29
|
-
/** The worker's own name, to scope the self-binding-missing detection. */
|
|
30
|
-
workerName?: string;
|
|
31
|
-
route?: string;
|
|
32
|
-
onLog?: (line: string) => void;
|
|
33
|
-
}
|
|
34
|
-
export declare function runWranglerDeploy(args: DeployArgs & {
|
|
35
|
-
projectDir: string;
|
|
36
|
-
}): Promise<{
|
|
37
|
-
url: string;
|
|
38
|
-
raw: string;
|
|
39
|
-
deploymentVersion?: string;
|
|
40
|
-
}>;
|
|
41
|
-
/**
|
|
42
|
-
* Deploy with a one-time SELF-binding first-deploy recovery. A fresh worker that
|
|
43
|
-
* declares a `services: SELF` binding can't deploy (its own script doesn't exist
|
|
44
|
-
* yet); on THAT specific failure we deploy the SELF-less fallback to create the
|
|
45
|
-
* script, then redeploy WITH SELF so autobinding works. Steady state (every
|
|
46
|
-
* deploy after the first) is a single pass. The `deploy` runner is injected so
|
|
47
|
-
* the orchestration is unit-testable without shelling out.
|
|
48
|
-
*/
|
|
49
|
-
export declare function deployWithSelfFallback(deploy: (configPath: string) => Promise<{
|
|
50
|
-
code: number;
|
|
51
|
-
out: string;
|
|
52
|
-
}>, args: DeployArgs): Promise<{
|
|
53
|
-
url: string;
|
|
54
|
-
raw: string;
|
|
55
|
-
deploymentVersion?: string;
|
|
56
|
-
}>;
|
|
57
|
-
/**
|
|
58
|
-
* True when wrangler failed specifically because the worker's OWN `SELF` service
|
|
59
|
-
* binding can't resolve yet (first deploy of a fresh script). Requires the
|
|
60
|
-
* worker name so an unrelated missing-service error doesn't trigger the two-pass.
|
|
61
|
-
*/
|
|
62
|
-
export declare function isSelfBindingMissing(out: string, workerName?: string): boolean;
|
|
63
|
-
export declare function bulkPutSecrets(args: {
|
|
64
|
-
projectDir: string;
|
|
65
|
-
configPath: string;
|
|
66
|
-
secrets: Record<string, string>;
|
|
67
|
-
onLog?: (line: string) => void;
|
|
68
|
-
}): Promise<void>;
|
|
69
|
-
/**
|
|
70
|
-
* Build the single-module worker bundle WITHOUT deploying — `wrangler deploy
|
|
71
|
-
* --dry-run --outdir` (no Cloudflare auth required). Returns the path of the
|
|
72
|
-
* bundled .js module (the managed adapter publishes its bytes).
|
|
73
|
-
*/
|
|
74
|
-
export declare function runWranglerBundle(args: {
|
|
75
|
-
projectDir: string;
|
|
76
|
-
configPath: string;
|
|
77
|
-
outDir: string;
|
|
78
|
-
onLog?: (line: string) => void;
|
|
79
|
-
}): Promise<string>;
|
|
80
|
-
/** Generate the exact binding and runtime types selected by the generated config. */
|
|
81
|
-
export declare function runWranglerTypes(args: {
|
|
82
|
-
readonly projectDir: string;
|
|
83
|
-
readonly configPath: string;
|
|
84
|
-
readonly onLog?: (line: string) => void;
|
|
85
|
-
}): Promise<string>;
|
|
86
|
-
//# sourceMappingURL=wrangler-cli.d.ts.map
|
|
1
|
+
export { runWranglerBundle } from './wrangler/bundle.js';
|
|
2
|
+
export { runWranglerDeploy, WranglerDeployError, type DeployArgs } from './wrangler/deploy.js';
|
|
3
|
+
export { runWranglerDev, type DevHandle } from './wrangler/development.js';
|
|
4
|
+
export { ensureWranglerDispatchNamespace, WranglerDispatchNamespaceError, } from './wrangler/namespace.js';
|
|
5
|
+
export { wranglerProcessEnv } from './wrangler/process.js';
|
|
6
|
+
export { runWranglerReleaseDeploy } from './wrangler/release.js';
|
|
7
|
+
export { admitWranglerDeploymentStatus, runWranglerDeploymentStatus, type WranglerDeploymentStatus, } from './wrangler/status.js';
|
|
8
|
+
export { runWranglerTypes } from './wrangler/type-generation.js';
|
|
@@ -1,275 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import { spawn } from 'node:child_process';
|
|
10
|
-
import { existsSync, readdirSync } from 'node:fs';
|
|
11
|
-
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
12
|
-
import { createServer } from 'node:net';
|
|
13
|
-
import { tmpdir } from 'node:os';
|
|
14
|
-
import { dirname, join } from 'node:path';
|
|
15
|
-
import { parseDeployUrl, parseDeployVersionId, parseDevReadyUrl } from './parse-output.js';
|
|
16
|
-
function wranglerCommand(projectDir) {
|
|
17
|
-
const local = join(projectDir, 'node_modules', '.bin', 'wrangler');
|
|
18
|
-
if (existsSync(local))
|
|
19
|
-
return { cmd: local, prefix: [] };
|
|
20
|
-
return { cmd: 'npx', prefix: ['--yes', 'wrangler'] };
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* True when `port` is free on `host`. A taken port previously made `wrangler
|
|
24
|
-
* dev` either die ("Address already in use") or — worse — a FIRST probe hit a
|
|
25
|
-
* DIFFERENT project's dev server on the same port (observed in agent runs:
|
|
26
|
-
* every reader of the docs converges on 8787/8899).
|
|
27
|
-
*/
|
|
28
|
-
function portFree(port, host) {
|
|
29
|
-
return new Promise((resolve) => {
|
|
30
|
-
const srv = createServer();
|
|
31
|
-
srv.once('error', () => resolve(false));
|
|
32
|
-
srv.once('listening', () => srv.close(() => resolve(true)));
|
|
33
|
-
srv.listen(port, host);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
/** An OS-assigned free port. */
|
|
37
|
-
function ephemeralPort(host) {
|
|
38
|
-
return new Promise((resolve, reject) => {
|
|
39
|
-
const srv = createServer();
|
|
40
|
-
srv.once('error', reject);
|
|
41
|
-
srv.listen(0, host, () => {
|
|
42
|
-
const addr = srv.address();
|
|
43
|
-
const port = typeof addr === 'object' && addr ? addr.port : 0;
|
|
44
|
-
srv.close(() => resolve(port));
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
export async function runWranglerDev(args) {
|
|
49
|
-
await runWranglerTypes(args);
|
|
50
|
-
const { cmd, prefix } = wranglerCommand(args.projectDir);
|
|
51
|
-
const bindHost = args.ip ?? '127.0.0.1';
|
|
52
|
-
if (args.autoPickPort && !(await portFree(args.port, bindHost))) {
|
|
53
|
-
const picked = await ephemeralPort(bindHost);
|
|
54
|
-
args.onLog?.(`port ${args.port} is taken — using ${picked} instead (pass --port to pin one)`);
|
|
55
|
-
args = { ...args, port: picked };
|
|
56
|
-
}
|
|
57
|
-
const wranglerArgs = [
|
|
58
|
-
...prefix,
|
|
59
|
-
'dev',
|
|
60
|
-
'--config',
|
|
61
|
-
args.configPath,
|
|
62
|
-
'--port',
|
|
63
|
-
String(args.port),
|
|
64
|
-
'--local-protocol',
|
|
65
|
-
'http',
|
|
66
|
-
'--ip',
|
|
67
|
-
args.ip ?? '127.0.0.1',
|
|
68
|
-
...(args.remote ? ['--remote'] : []),
|
|
69
|
-
];
|
|
70
|
-
const child = spawn(cmd, wranglerArgs, {
|
|
71
|
-
cwd: args.projectDir,
|
|
72
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
73
|
-
env: { ...process.env, WRANGLER_SEND_METRICS: 'false' },
|
|
74
|
-
});
|
|
75
|
-
const fallbackUrl = `http://localhost:${args.port}`;
|
|
76
|
-
// (args.port may have been re-picked above — everything below reads args.port)
|
|
77
|
-
let resolved = false;
|
|
78
|
-
// Wrangler's watch mode STAYS ALIVE on a build failure (listener up, worker
|
|
79
|
-
// never answers) — the classic silent hang. Track build errors so the
|
|
80
|
-
// safety net can fail LOUD instead of resolving a dead URL.
|
|
81
|
-
let buildErrorTail = '';
|
|
82
|
-
let outputTail = '';
|
|
83
|
-
const url = await new Promise((resolve, reject) => {
|
|
84
|
-
const onData = (buf) => {
|
|
85
|
-
const text = buf.toString();
|
|
86
|
-
outputTail = (outputTail + text).slice(-3000);
|
|
87
|
-
for (const line of text.split('\n')) {
|
|
88
|
-
if (line.trim())
|
|
89
|
-
args.onLog?.(line);
|
|
90
|
-
}
|
|
91
|
-
if (/✘ \[ERROR\]|Build failed|Could not resolve "/.test(text)) {
|
|
92
|
-
buildErrorTail = (buildErrorTail + text).slice(-2000);
|
|
93
|
-
}
|
|
94
|
-
if (!resolved) {
|
|
95
|
-
const ready = parseDevReadyUrl(text, args.port);
|
|
96
|
-
if (ready) {
|
|
97
|
-
resolved = true;
|
|
98
|
-
resolve(ready);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
else if (/Reloading|Detected changes|Updated/i.test(text)) {
|
|
102
|
-
args.onReload();
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
child.stdout?.on('data', onData);
|
|
106
|
-
child.stderr?.on('data', onData);
|
|
107
|
-
child.on('exit', (code) => {
|
|
108
|
-
if (!resolved) {
|
|
109
|
-
resolved = true;
|
|
110
|
-
reject(new Error(`wrangler dev exited before becoming ready (code ${code ?? 'null'}).\n${outputTail}`));
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
child.on('error', (err) => {
|
|
114
|
-
if (!resolved) {
|
|
115
|
-
resolved = true;
|
|
116
|
-
reject(err);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
// Safety net: if we never matched a URL but the process is alive, assume the
|
|
120
|
-
// conventional localhost URL after a grace period — UNLESS the build
|
|
121
|
-
// failed, in which case a listener may be up but the worker will never
|
|
122
|
-
// answer: fail loud with the build output instead of handing back a dead
|
|
123
|
-
// URL.
|
|
124
|
-
setTimeout(() => {
|
|
125
|
-
if (!resolved && child.exitCode === null) {
|
|
126
|
-
resolved = true;
|
|
127
|
-
if (buildErrorTail) {
|
|
128
|
-
void stopChild(child);
|
|
129
|
-
reject(new Error(`worker build failed — the dev server would hang silently.\n${buildErrorTail}`));
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
resolve(fallbackUrl);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}, 15_000).unref?.();
|
|
136
|
-
});
|
|
137
|
-
return { url, stop: () => stopChild(child) };
|
|
138
|
-
}
|
|
139
|
-
export async function runWranglerDeploy(args) {
|
|
140
|
-
await runWranglerTypes(args);
|
|
141
|
-
const { cmd, prefix } = wranglerCommand(args.projectDir);
|
|
142
|
-
const deploy = (configPath) => runCapture(cmd, [...prefix, 'deploy', '--config', configPath], args.projectDir, args.onLog);
|
|
143
|
-
return deployWithSelfFallback(deploy, args);
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Deploy with a one-time SELF-binding first-deploy recovery. A fresh worker that
|
|
147
|
-
* declares a `services: SELF` binding can't deploy (its own script doesn't exist
|
|
148
|
-
* yet); on THAT specific failure we deploy the SELF-less fallback to create the
|
|
149
|
-
* script, then redeploy WITH SELF so autobinding works. Steady state (every
|
|
150
|
-
* deploy after the first) is a single pass. The `deploy` runner is injected so
|
|
151
|
-
* the orchestration is unit-testable without shelling out.
|
|
152
|
-
*/
|
|
153
|
-
export async function deployWithSelfFallback(deploy, args) {
|
|
154
|
-
let { code, out } = await deploy(args.configPath);
|
|
155
|
-
if (code !== 0 && args.fallbackConfigPath && isSelfBindingMissing(out, args.workerName)) {
|
|
156
|
-
args.onLog?.('SELF service binding not resolvable yet (first deploy) — creating the worker, then re-binding SELF');
|
|
157
|
-
const first = await deploy(args.fallbackConfigPath);
|
|
158
|
-
if (first.code !== 0) {
|
|
159
|
-
throw new Error(`wrangler deploy (no-self pass) failed (code ${first.code}):\n${first.out.slice(-2000)}`);
|
|
160
|
-
}
|
|
161
|
-
;
|
|
162
|
-
({ code, out } = await deploy(args.configPath));
|
|
163
|
-
}
|
|
164
|
-
if (code !== 0) {
|
|
165
|
-
throw new Error(`wrangler deploy failed (code ${code}):\n${out.slice(-2000)}`);
|
|
166
|
-
}
|
|
167
|
-
const url = parseDeployUrl(out, args.route);
|
|
168
|
-
if (!url) {
|
|
169
|
-
throw new Error(`could not determine deployed URL from wrangler output:\n${out.slice(-2000)}`);
|
|
170
|
-
}
|
|
171
|
-
const deploymentVersion = parseDeployVersionId(out);
|
|
172
|
-
return { url, raw: out, ...(deploymentVersion === undefined ? {} : { deploymentVersion }) };
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* True when wrangler failed specifically because the worker's OWN `SELF` service
|
|
176
|
-
* binding can't resolve yet (first deploy of a fresh script). Requires the
|
|
177
|
-
* worker name so an unrelated missing-service error doesn't trigger the two-pass.
|
|
178
|
-
*/
|
|
179
|
-
export function isSelfBindingMissing(out, workerName) {
|
|
180
|
-
const bindingError = /could not resolve binding/i.test(out) ||
|
|
181
|
-
/service\b[^\n]*\bnot found/i.test(out) ||
|
|
182
|
-
/script\b[^\n]*\bnot found/i.test(out);
|
|
183
|
-
if (!bindingError || !/\bSELF\b/.test(out))
|
|
184
|
-
return false;
|
|
185
|
-
return workerName ? out.includes(workerName) : true;
|
|
186
|
-
}
|
|
187
|
-
export async function bulkPutSecrets(args) {
|
|
188
|
-
const names = Object.keys(args.secrets);
|
|
189
|
-
if (names.length === 0)
|
|
190
|
-
return;
|
|
191
|
-
const { cmd, prefix } = wranglerCommand(args.projectDir);
|
|
192
|
-
const dir = await mkdtemp(join(tmpdir(), 'astrale-secrets-'));
|
|
193
|
-
const file = join(dir, 'secrets.json');
|
|
194
|
-
try {
|
|
195
|
-
await writeFile(file, JSON.stringify(args.secrets));
|
|
196
|
-
const { code, out } = await runCapture(cmd, [...prefix, 'secret', 'bulk', file, '--config', args.configPath], args.projectDir, args.onLog);
|
|
197
|
-
if (code !== 0) {
|
|
198
|
-
throw new Error(`wrangler secret bulk failed (code ${code}):\n${out.slice(-1500)}`);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
finally {
|
|
202
|
-
await rm(dir, { recursive: true, force: true });
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
// ── internals ──────────────────────────────────────────────────────────────
|
|
206
|
-
function runCapture(cmd, args, cwd, onLog) {
|
|
207
|
-
return new Promise((resolve, reject) => {
|
|
208
|
-
const child = spawn(cmd, args, {
|
|
209
|
-
cwd,
|
|
210
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
211
|
-
env: { ...process.env, WRANGLER_SEND_METRICS: 'false' },
|
|
212
|
-
});
|
|
213
|
-
let out = '';
|
|
214
|
-
const onData = (buf) => {
|
|
215
|
-
const text = buf.toString();
|
|
216
|
-
out += text;
|
|
217
|
-
for (const line of text.split('\n'))
|
|
218
|
-
if (line.trim())
|
|
219
|
-
onLog?.(line);
|
|
220
|
-
};
|
|
221
|
-
child.stdout?.on('data', onData);
|
|
222
|
-
child.stderr?.on('data', onData);
|
|
223
|
-
child.on('exit', (code) => resolve({ code: code ?? 1, out }));
|
|
224
|
-
child.on('error', reject);
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
async function stopChild(child) {
|
|
228
|
-
if (child.exitCode !== null)
|
|
229
|
-
return;
|
|
230
|
-
await new Promise((resolve) => {
|
|
231
|
-
child.on('exit', () => resolve());
|
|
232
|
-
child.kill('SIGTERM');
|
|
233
|
-
setTimeout(() => {
|
|
234
|
-
if (child.exitCode === null)
|
|
235
|
-
child.kill('SIGKILL');
|
|
236
|
-
resolve();
|
|
237
|
-
}, 4000).unref?.();
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Build the single-module worker bundle WITHOUT deploying — `wrangler deploy
|
|
242
|
-
* --dry-run --outdir` (no Cloudflare auth required). Returns the path of the
|
|
243
|
-
* bundled .js module (the managed adapter publishes its bytes).
|
|
244
|
-
*/
|
|
245
|
-
export async function runWranglerBundle(args) {
|
|
246
|
-
await runWranglerTypes(args);
|
|
247
|
-
const { cmd, prefix } = wranglerCommand(args.projectDir);
|
|
248
|
-
const { code, out } = await runCapture(cmd, [...prefix, 'deploy', '--dry-run', '--outdir', args.outDir, '--config', args.configPath], args.projectDir, args.onLog);
|
|
249
|
-
if (code !== 0)
|
|
250
|
-
throw new Error(`wrangler bundle failed (exit ${code}): ${out.slice(-400)}`);
|
|
251
|
-
const js = readdirSync(args.outDir).filter((f) => f.endsWith('.js'));
|
|
252
|
-
if (js.length === 0)
|
|
253
|
-
throw new Error(`wrangler bundle produced no .js in ${args.outDir}`);
|
|
254
|
-
const preferred = js.find((f) => f.startsWith('worker')) ?? js[0];
|
|
255
|
-
return join(args.outDir, preferred);
|
|
256
|
-
}
|
|
257
|
-
/** Generate the exact binding and runtime types selected by the generated config. */
|
|
258
|
-
export async function runWranglerTypes(args) {
|
|
259
|
-
const { cmd, prefix } = wranglerCommand(args.projectDir);
|
|
260
|
-
const outputPath = join(dirname(args.configPath), 'worker-configuration.d.ts');
|
|
261
|
-
const { code, out } = await runCapture(cmd, [
|
|
262
|
-
...prefix,
|
|
263
|
-
'types',
|
|
264
|
-
outputPath,
|
|
265
|
-
'--env-interface',
|
|
266
|
-
'CloudflareEnv',
|
|
267
|
-
'--config',
|
|
268
|
-
args.configPath,
|
|
269
|
-
], args.projectDir, args.onLog);
|
|
270
|
-
if (code !== 0) {
|
|
271
|
-
throw new Error(`wrangler types failed (code ${code}):\n${out.slice(-2000)}`);
|
|
272
|
-
}
|
|
273
|
-
return outputPath;
|
|
274
|
-
}
|
|
275
|
-
//# sourceMappingURL=wrangler-cli.js.map
|
|
1
|
+
export { runWranglerBundle } from './wrangler/bundle.js';
|
|
2
|
+
export { runWranglerDeploy, WranglerDeployError } from './wrangler/deploy.js';
|
|
3
|
+
export { runWranglerDev } from './wrangler/development.js';
|
|
4
|
+
export { ensureWranglerDispatchNamespace, WranglerDispatchNamespaceError, } from './wrangler/namespace.js';
|
|
5
|
+
export { wranglerProcessEnv } from './wrangler/process.js';
|
|
6
|
+
export { runWranglerReleaseDeploy } from './wrangler/release.js';
|
|
7
|
+
export { admitWranglerDeploymentStatus, runWranglerDeploymentStatus, } from './wrangler/status.js';
|
|
8
|
+
export { runWranglerTypes } from './wrangler/type-generation.js';
|
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,17 @@
|
|
|
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 { ensureWranglerDispatchNamespace, runWranglerDeploy, runWranglerDeploymentStatus, runWranglerReleaseDeploy } from '../build/wrangler-cli.js';
|
|
5
|
+
import type { signingIdentity } from '../identity/source.js';
|
|
6
|
+
import type { CloudflareParams } from '../params.js';
|
|
7
|
+
export interface CloudflareDeployDependencies {
|
|
8
|
+
readonly materialize: typeof materialize;
|
|
9
|
+
readonly ensureWranglerDispatchNamespace: typeof ensureWranglerDispatchNamespace;
|
|
10
|
+
readonly runWranglerDeploy: typeof runWranglerDeploy;
|
|
11
|
+
readonly runWranglerReleaseDeploy: typeof runWranglerReleaseDeploy;
|
|
12
|
+
readonly runWranglerDeploymentStatus: typeof runWranglerDeploymentStatus;
|
|
13
|
+
readonly waitForReadiness: (release: Release, signal: AbortSignal) => Promise<void>;
|
|
14
|
+
readonly signingIdentity: typeof signingIdentity;
|
|
15
|
+
}
|
|
16
|
+
/** Establish private placement and place one revision before advancing the public gateway. */
|
|
17
|
+
export declare function deployCloudflare(parameters: CloudflareParams, context: DeployContext, dependencies: CloudflareDeployDependencies): Promise<DeployResult>;
|