@astrale-os/adapter-cloudflare 0.5.0-beta.29 → 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/dist/adapter.d.ts +1 -1
- package/dist/adapter.js +33 -4
- package/dist/build/artifact.d.ts +3 -4
- package/dist/build/artifact.js +84 -151
- package/dist/build/bundle/admit.d.ts +1 -0
- package/dist/build/bundle/admit.js +9 -0
- package/dist/build/codegen/execution.d.ts +3 -15
- package/dist/build/codegen/execution.js +2 -72
- package/dist/build/codegen/gateway.d.ts +1 -1
- package/dist/build/codegen/gateway.js +1 -7
- 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 -9
- package/dist/build/configuration.js +3 -40
- 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/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 +3 -1
- package/dist/build/index.js +2 -1
- package/dist/build/materialize.d.ts +4 -0
- package/dist/build/materialize.js +10 -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 -105
- package/dist/build/wrangler-cli.js +8 -448
- package/dist/deploy/deploy.d.ts +1 -1
- package/dist/deploy/deploy.js +125 -98
- package/dist/worker/gateway.js +2 -2
- package/package.json +2 -2
package/dist/adapter.d.ts
CHANGED
|
@@ -14,4 +14,4 @@ export interface CloudflareDependencies extends CloudflareDeployDependencies {
|
|
|
14
14
|
}
|
|
15
15
|
export declare function cloudflare(environments: Readonly<Record<string, CloudflareParams>>): import("@astrale-os/sdk/deployment/adapter").Adapter<CloudflareParams>;
|
|
16
16
|
export declare function cloudflareWithDependencies(environments: Readonly<Record<string, CloudflareParams>>, dependencies: CloudflareDependencies): import("@astrale-os/sdk/deployment/adapter").Adapter<CloudflareParams>;
|
|
17
|
-
export declare function waitForReadiness(verify: typeof verifyReadiness, release: Release): Promise<void>;
|
|
17
|
+
export declare function waitForReadiness(verify: typeof verifyReadiness, release: Release, signal?: AbortSignal): Promise<void>;
|
package/dist/adapter.js
CHANGED
|
@@ -24,7 +24,7 @@ export function cloudflare(environments) {
|
|
|
24
24
|
runWranglerDev,
|
|
25
25
|
startFrontend,
|
|
26
26
|
signingIdentity,
|
|
27
|
-
waitForReadiness: (release) => waitForReadiness(verifyReadiness, release),
|
|
27
|
+
waitForReadiness: (release, signal) => waitForReadiness(verifyReadiness, release, signal),
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
export function cloudflareWithDependencies(environments, dependencies) {
|
|
@@ -57,6 +57,7 @@ export function cloudflareWithDependencies(environments, dependencies) {
|
|
|
57
57
|
const configPath = join(directory, 'wrangler.watch.jsonc');
|
|
58
58
|
await writeFile(configPath, generateWranglerConfig({
|
|
59
59
|
workerName: name,
|
|
60
|
+
main: `./${context.artifact.entrypoint}`,
|
|
60
61
|
vars: {
|
|
61
62
|
...parameters.vars,
|
|
62
63
|
...(parameters.host === undefined ? {} : { WORKER_URL: parameters.host }),
|
|
@@ -128,18 +129,46 @@ function frontendRoutes(artifact) {
|
|
|
128
129
|
: [route.path])
|
|
129
130
|
.sort());
|
|
130
131
|
}
|
|
131
|
-
export async function waitForReadiness(verify, release) {
|
|
132
|
+
export async function waitForReadiness(verify, release, signal) {
|
|
132
133
|
const deadline = Date.now() + 90_000;
|
|
133
134
|
let last;
|
|
134
135
|
while (Date.now() < deadline) {
|
|
136
|
+
throwIfAborted(signal);
|
|
135
137
|
try {
|
|
136
|
-
await verify(release, {
|
|
138
|
+
await verify(release, {
|
|
139
|
+
signal: signal === undefined
|
|
140
|
+
? AbortSignal.timeout(5_000)
|
|
141
|
+
: AbortSignal.any([signal, AbortSignal.timeout(5_000)]),
|
|
142
|
+
});
|
|
137
143
|
return;
|
|
138
144
|
}
|
|
139
145
|
catch (cause) {
|
|
146
|
+
throwIfAborted(signal);
|
|
140
147
|
last = cause;
|
|
141
|
-
await
|
|
148
|
+
await pause(signal);
|
|
142
149
|
}
|
|
143
150
|
}
|
|
144
151
|
throw last instanceof Error ? last : new Error('Cloudflare Release did not become ready.');
|
|
145
152
|
}
|
|
153
|
+
function pause(signal) {
|
|
154
|
+
return new Promise((resolve, reject) => {
|
|
155
|
+
const timer = setTimeout(done, 1_000);
|
|
156
|
+
const abort = () => done(abortError(signal));
|
|
157
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
158
|
+
function done(cause) {
|
|
159
|
+
clearTimeout(timer);
|
|
160
|
+
signal?.removeEventListener('abort', abort);
|
|
161
|
+
if (cause === undefined)
|
|
162
|
+
resolve();
|
|
163
|
+
else
|
|
164
|
+
reject(cause);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function throwIfAborted(signal) {
|
|
169
|
+
if (signal?.aborted)
|
|
170
|
+
throw abortError(signal);
|
|
171
|
+
}
|
|
172
|
+
function abortError(signal) {
|
|
173
|
+
return signal?.reason instanceof Error ? signal.reason : new Error('Deployment interrupted.');
|
|
174
|
+
}
|
package/dist/build/artifact.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { ArtifactSource, PrepareContext } from '@astrale-os/sdk/deployment/adapter';
|
|
2
2
|
import type { CloudflareParams } from '../params.js';
|
|
3
|
+
export { materialize } from './materialize.js';
|
|
3
4
|
/** Prepare one revision Service and its stateless gateway without provider mutation. */
|
|
4
5
|
export declare function artifact(params: CloudflareParams, context: PrepareContext): Promise<ArtifactSource>;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
bytes(): Uint8Array;
|
|
8
|
-
}[]): Promise<void>;
|
|
6
|
+
/** Prepare the complete portable Cloudflare Worker without direct Wrangler placement files. */
|
|
7
|
+
export declare function prepareWorkerArtifact(params: CloudflareParams, context: PrepareContext): Promise<ArtifactSource>;
|
package/dist/build/artifact.js
CHANGED
|
@@ -1,146 +1,61 @@
|
|
|
1
|
-
import { material } from '@astrale-os/sdk/deployment/build';
|
|
2
1
|
import { addressing } from '@astrale-os/sdk/deployment/release';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { pathToFileURL } from 'node:url';
|
|
2
|
+
import { mkdir } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
6
4
|
import { SIGNING_IDENTITY_BINDING } from '../identity/binding.js';
|
|
7
5
|
import { releaseNamespace, releaseWorkerName } from '../release/index.js';
|
|
8
|
-
import { generateExecutionEntry, generateExecutionService } from './codegen/execution.js';
|
|
9
|
-
import { generateGatewayEntry } from './codegen/gateway.js';
|
|
10
6
|
import { generateWranglerConfig } from './codegen/wrangler.js';
|
|
11
7
|
import { deploymentAddressing, resolveRouter, workerName } from './configuration.js';
|
|
12
8
|
import { frontendFiles } from './frontend-v1.js';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
9
|
+
import { frontendRoutes } from './frontend/routes.js';
|
|
10
|
+
import { prepareGateway } from './gateway/prepare.js';
|
|
11
|
+
import { encodeWorkerArtifactManifest, inferMediaType, workerContentDigest, WORKER_MANIFEST_PATH, } from './worker/artifact.manifest.js';
|
|
12
|
+
import { prepareExecution, RELEASE_ENTRY, RELEASE_SERVICE, runtimeVars, } from './worker/execution.prepare.js';
|
|
13
|
+
import { admitWorkerRuntimeConfiguration } from './worker/runtime.js';
|
|
14
|
+
export { materialize } from './materialize.js';
|
|
15
15
|
const encoder = new TextEncoder();
|
|
16
|
-
const SERVICE_MODULE = 'service.mjs';
|
|
17
|
-
const RELEASE_ENTRY = 'bundle/index.mjs';
|
|
18
|
-
const RELEASE_SERVICE = `bundle/${SERVICE_MODULE}`;
|
|
19
16
|
/** Prepare one revision Service and its stateless gateway without provider mutation. */
|
|
20
17
|
export async function artifact(params, context) {
|
|
18
|
+
return prepare(params, context, true);
|
|
19
|
+
}
|
|
20
|
+
/** Prepare the complete portable Cloudflare Worker without direct Wrangler placement files. */
|
|
21
|
+
export async function prepareWorkerArtifact(params, context) {
|
|
22
|
+
return prepare(params, context, false);
|
|
23
|
+
}
|
|
24
|
+
async function prepare(params, context, direct) {
|
|
21
25
|
const stateDirectory = join(context.projectDir, '.astrale');
|
|
22
26
|
const directory = join(stateDirectory, 'runtime');
|
|
23
27
|
await mkdir(directory, { recursive: true });
|
|
24
|
-
const runtimePath = resolve(context.projectDir, context.runtime.reference.path);
|
|
25
|
-
const runtimeSpecifier = moduleSpecifier(relative(directory, runtimePath));
|
|
26
28
|
const router = resolveRouter(params.router);
|
|
27
29
|
const name = workerName(params, context.build.schema.compiled.root.origin);
|
|
28
30
|
const revision = context.build.schema.compiled.root.revision;
|
|
29
31
|
const namespace = releaseNamespace(name);
|
|
30
32
|
const target = releaseWorkerName(revision);
|
|
31
33
|
const configuredIssuer = deploymentAddressing(params);
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
router: {
|
|
41
|
-
binding: router.binding,
|
|
42
|
-
hostSuffix: router.hostSuffix,
|
|
43
|
-
minLabels: router.minLabels,
|
|
44
|
-
},
|
|
45
|
-
}),
|
|
46
|
-
});
|
|
47
|
-
const serviceSourcePath = join(directory, 'service.gen.ts');
|
|
48
|
-
await writeFile(serviceSourcePath, serviceSource);
|
|
49
|
-
const serviceConfigPath = join(directory, 'wrangler.service.prepare.jsonc');
|
|
50
|
-
await writeFile(serviceConfigPath, generateWranglerConfig({
|
|
51
|
-
workerName: name,
|
|
52
|
-
main: './service.gen.ts',
|
|
53
|
-
vars: {
|
|
54
|
-
...params.vars,
|
|
55
|
-
...(configuredIssuer === undefined ? {} : { WORKER_URL: configuredIssuer }),
|
|
56
|
-
},
|
|
57
|
-
secretBindings: [SIGNING_IDENTITY_BINDING],
|
|
58
|
-
...(router === undefined
|
|
59
|
-
? {}
|
|
60
|
-
: { router: { binding: router.binding, service: router.service } }),
|
|
61
|
-
...(params.wrangler === undefined ? {} : { wrangler: params.wrangler }),
|
|
62
|
-
selfBinding: false,
|
|
63
|
-
}));
|
|
64
|
-
const serviceOutput = join(directory, 'dist-service');
|
|
65
|
-
await rm(serviceOutput, { recursive: true, force: true });
|
|
66
|
-
const emittedService = await runWranglerBundle({
|
|
67
|
-
projectDir: context.projectDir,
|
|
68
|
-
configPath: serviceConfigPath,
|
|
69
|
-
outDir: serviceOutput,
|
|
70
|
-
});
|
|
71
|
-
await qualifyWorkerBundle({
|
|
72
|
-
metafilePath: emittedService.metafilePath,
|
|
73
|
-
inputRoot: dirname(serviceConfigPath),
|
|
74
|
-
});
|
|
75
|
-
await admitBundle(emittedService.bundlePath);
|
|
76
|
-
const serviceBundle = await readFile(emittedService.bundlePath);
|
|
77
|
-
await mkdir(dirname(join(directory, RELEASE_SERVICE)), { recursive: true });
|
|
78
|
-
await writeFile(join(directory, RELEASE_SERVICE), serviceBundle);
|
|
79
|
-
const sourcePath = join(directory, 'worker.gen.ts');
|
|
80
|
-
await writeFile(sourcePath, generateExecutionEntry(`./${RELEASE_SERVICE}`));
|
|
81
|
-
const configPath = join(directory, 'wrangler.prepare.jsonc');
|
|
82
|
-
await writeFile(configPath, generateWranglerConfig({
|
|
83
|
-
workerName: name,
|
|
84
|
-
...(params.route === undefined ? {} : { route: params.route }),
|
|
85
|
-
vars: {
|
|
86
|
-
...params.vars,
|
|
87
|
-
...(configuredIssuer === undefined ? {} : { WORKER_URL: configuredIssuer }),
|
|
88
|
-
},
|
|
89
|
-
secretBindings: [SIGNING_IDENTITY_BINDING],
|
|
90
|
-
modules: { baseDir: '.', globs: [RELEASE_SERVICE] },
|
|
91
|
-
...(router === undefined
|
|
92
|
-
? {}
|
|
93
|
-
: { router: { binding: router.binding, service: router.service } }),
|
|
94
|
-
...(params.wrangler === undefined ? {} : { wrangler: params.wrangler }),
|
|
95
|
-
selfBinding: false,
|
|
96
|
-
}));
|
|
97
|
-
const output = join(directory, 'dist-prepare');
|
|
98
|
-
await rm(output, { recursive: true, force: true });
|
|
99
|
-
const emitted = await runWranglerBundle({
|
|
100
|
-
projectDir: context.projectDir,
|
|
101
|
-
configPath,
|
|
102
|
-
outDir: output,
|
|
34
|
+
const execution = await prepareExecution({
|
|
35
|
+
params,
|
|
36
|
+
context,
|
|
37
|
+
directory,
|
|
38
|
+
name,
|
|
39
|
+
direct,
|
|
40
|
+
configuredIssuer,
|
|
41
|
+
router,
|
|
103
42
|
});
|
|
104
43
|
const frontend = await frontendFiles({
|
|
105
44
|
frontend: context.build.frontend,
|
|
106
45
|
projectDir: context.projectDir,
|
|
107
46
|
});
|
|
108
|
-
await
|
|
109
|
-
metafilePath: emitted.metafilePath,
|
|
110
|
-
inputRoot: dirname(configPath),
|
|
111
|
-
});
|
|
112
|
-
await admitBundle(emitted.bundlePath);
|
|
113
|
-
const bundle = await readFile(emitted.bundlePath);
|
|
114
|
-
const gatewaySource = join(directory, 'gateway.gen.ts');
|
|
115
|
-
await writeFile(gatewaySource, generateGatewayEntry(revision));
|
|
116
|
-
const gatewayPrepareConfig = join(directory, 'wrangler.gateway.prepare.jsonc');
|
|
117
|
-
await writeFile(gatewayPrepareConfig, generateWranglerConfig({
|
|
118
|
-
workerName: name,
|
|
119
|
-
main: './gateway.gen.ts',
|
|
120
|
-
...(params.route === undefined ? {} : { route: params.route }),
|
|
121
|
-
releases: { binding: 'RELEASES', namespace },
|
|
122
|
-
selfBinding: false,
|
|
123
|
-
}));
|
|
124
|
-
const gatewayOutput = join(directory, 'dist-gateway');
|
|
125
|
-
await rm(gatewayOutput, { recursive: true, force: true });
|
|
126
|
-
const gateway = await runWranglerBundle({
|
|
47
|
+
const gatewayBundle = await prepareGateway({
|
|
127
48
|
projectDir: context.projectDir,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
inputRoot: dirname(gatewayPrepareConfig),
|
|
49
|
+
directory,
|
|
50
|
+
name,
|
|
51
|
+
...(params.route === undefined ? {} : { route: params.route }),
|
|
52
|
+
namespace,
|
|
53
|
+
revision,
|
|
134
54
|
});
|
|
135
|
-
await admitBundle(gateway.bundlePath);
|
|
136
|
-
const gatewayBundle = await readFile(gateway.bundlePath);
|
|
137
55
|
const releaseConfig = generateWranglerConfig({
|
|
138
56
|
workerName: target,
|
|
139
57
|
main: `./${RELEASE_ENTRY}`,
|
|
140
|
-
vars:
|
|
141
|
-
...params.vars,
|
|
142
|
-
...(configuredIssuer === undefined ? {} : { WORKER_URL: configuredIssuer }),
|
|
143
|
-
},
|
|
58
|
+
vars: runtimeVars(params, configuredIssuer),
|
|
144
59
|
secretBindings: [SIGNING_IDENTITY_BINDING],
|
|
145
60
|
modules: { baseDir: '.', globs: [RELEASE_SERVICE] },
|
|
146
61
|
...(context.build.frontend?.source.kind === 'vite'
|
|
@@ -165,16 +80,65 @@ export async function artifact(params, context) {
|
|
|
165
80
|
releases: { binding: 'RELEASES', namespace },
|
|
166
81
|
selfBinding: false,
|
|
167
82
|
});
|
|
83
|
+
const runtime = admitWorkerRuntimeConfiguration(releaseConfig);
|
|
84
|
+
const manifest = encodeWorkerArtifactManifest({
|
|
85
|
+
origin: context.build.schema.compiled.root.origin,
|
|
86
|
+
revision,
|
|
87
|
+
release: {
|
|
88
|
+
entrypoint: RELEASE_ENTRY,
|
|
89
|
+
modules: [
|
|
90
|
+
{ path: RELEASE_ENTRY, kind: 'esm', digest: workerContentDigest(execution.entry) },
|
|
91
|
+
{ path: RELEASE_SERVICE, kind: 'esm', digest: workerContentDigest(execution.service) },
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
gateway: {
|
|
95
|
+
entrypoint: 'gateway/index.mjs',
|
|
96
|
+
modules: [
|
|
97
|
+
{ path: 'gateway/index.mjs', kind: 'esm', digest: workerContentDigest(gatewayBundle) },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
runtime: {
|
|
101
|
+
compatibilityDate: runtime.compatibilityDate,
|
|
102
|
+
compatibilityFlags: runtime.compatibilityFlags,
|
|
103
|
+
},
|
|
104
|
+
bindings: {
|
|
105
|
+
vars: runtime.vars,
|
|
106
|
+
services: runtime.services,
|
|
107
|
+
requiredSecrets: [SIGNING_IDENTITY_BINDING],
|
|
108
|
+
},
|
|
109
|
+
...(frontend.length === 0
|
|
110
|
+
? {}
|
|
111
|
+
: {
|
|
112
|
+
assets: {
|
|
113
|
+
files: frontend.map((file) => {
|
|
114
|
+
const contentType = file.mediaType ?? inferMediaType(file.path);
|
|
115
|
+
return {
|
|
116
|
+
path: `/${file.path}`,
|
|
117
|
+
artifactPath: `frontend/${file.path}`,
|
|
118
|
+
digest: workerContentDigest(file.bytes()),
|
|
119
|
+
...(contentType === undefined ? {} : { contentType }),
|
|
120
|
+
};
|
|
121
|
+
}),
|
|
122
|
+
notFound: 'none',
|
|
123
|
+
runWorkerFirst: true,
|
|
124
|
+
},
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
168
127
|
const files = [
|
|
169
|
-
{ path:
|
|
170
|
-
{ path:
|
|
171
|
-
{ path:
|
|
172
|
-
{ path:
|
|
173
|
-
{ path: 'gateway/index.mjs', content: new Uint8Array(gatewayBundle) },
|
|
128
|
+
{ path: RELEASE_ENTRY, content: execution.entry },
|
|
129
|
+
{ path: RELEASE_SERVICE, content: execution.service },
|
|
130
|
+
{ path: 'gateway/index.mjs', content: gatewayBundle },
|
|
131
|
+
{ path: WORKER_MANIFEST_PATH, content: manifest },
|
|
174
132
|
...frontend.map((file) => ({
|
|
175
133
|
path: `frontend/${file.path}`,
|
|
176
134
|
content: file.bytes(),
|
|
177
135
|
})),
|
|
136
|
+
...(direct
|
|
137
|
+
? [
|
|
138
|
+
{ path: 'wrangler.release.jsonc', content: encoder.encode(releaseConfig) },
|
|
139
|
+
{ path: 'wrangler.gateway.jsonc', content: encoder.encode(gatewayConfig) },
|
|
140
|
+
]
|
|
141
|
+
: []),
|
|
178
142
|
];
|
|
179
143
|
return Object.freeze({
|
|
180
144
|
entrypoint: RELEASE_ENTRY,
|
|
@@ -184,34 +148,3 @@ export async function artifact(params, context) {
|
|
|
184
148
|
: Object.freeze({ kind: 'configured', addressing: addressing(configuredIssuer) }),
|
|
185
149
|
});
|
|
186
150
|
}
|
|
187
|
-
async function admitBundle(path) {
|
|
188
|
-
const loaded = (await import(`${pathToFileURL(path).href}?admit=${Date.now()}`));
|
|
189
|
-
if (loaded.default === null ||
|
|
190
|
-
typeof loaded.default !== 'object' ||
|
|
191
|
-
typeof Reflect.get(loaded.default, 'fetch') !== 'function') {
|
|
192
|
-
throw new TypeError('Generated Worker bundle does not export a Fetch handler.');
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
function frontendRoutes(frontend) {
|
|
196
|
-
if (frontend.source.kind !== 'vite')
|
|
197
|
-
return [];
|
|
198
|
-
return Object.freeze(frontend.routes
|
|
199
|
-
.flatMap((route) => frontend.source.kind === 'vite' && frontend.source.spa && route.path !== '/'
|
|
200
|
-
? [route.path, `${route.path}/*`]
|
|
201
|
-
: route.path === '/'
|
|
202
|
-
? ['/*']
|
|
203
|
-
: [route.path])
|
|
204
|
-
.sort());
|
|
205
|
-
}
|
|
206
|
-
export async function materialize(root, files) {
|
|
207
|
-
await rm(root, { recursive: true, force: true });
|
|
208
|
-
for (const file of files) {
|
|
209
|
-
const path = join(root, file.path);
|
|
210
|
-
await mkdir(dirname(path), { recursive: true });
|
|
211
|
-
await writeFile(path, file.bytes());
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
function moduleSpecifier(input) {
|
|
215
|
-
const normalized = input.split('\\').join('/');
|
|
216
|
-
return normalized.startsWith('.') ? normalized : `./${normalized}`;
|
|
217
|
-
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function admitWorkerBundle(path: string): Promise<void>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
2
|
+
export async function admitWorkerBundle(path) {
|
|
3
|
+
const loaded = (await import(`${pathToFileURL(path).href}?admit=${Date.now()}`));
|
|
4
|
+
if (loaded.default === null ||
|
|
5
|
+
typeof loaded.default !== 'object' ||
|
|
6
|
+
typeof Reflect.get(loaded.default, 'fetch') !== 'function') {
|
|
7
|
+
throw new TypeError('Generated Worker bundle does not export a Fetch handler.');
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
readonly runtimeSpecifier: string;
|
|
5
|
-
readonly material: BuildMaterial;
|
|
6
|
-
readonly providerAssignedWorker?: string;
|
|
7
|
-
readonly router?: {
|
|
8
|
-
readonly binding: string;
|
|
9
|
-
readonly hostSuffix: string;
|
|
10
|
-
readonly minLabels: number;
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
export declare function generateExecutionService(options: ExecutionCodegenOptions): string;
|
|
14
|
-
/** Generate the isolate-startup entry that realizes the heavy Service on first request. */
|
|
15
|
-
export declare function generateExecutionEntry(serviceSpecifier: string): string;
|
|
1
|
+
export { generateExecutionEntry } from '../worker/codegen/entry.js';
|
|
2
|
+
export { generateExecutionService } from '../worker/codegen/service.js';
|
|
3
|
+
export type { ExecutionCodegenOptions } from '../worker/codegen/service.js';
|
|
@@ -1,72 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
const routerPredicate = router === undefined
|
|
4
|
-
? ''
|
|
5
|
-
: `
|
|
6
|
-
function isInstanceHost(host: string): boolean {
|
|
7
|
-
return host.endsWith(${JSON.stringify(router.hostSuffix)}) && host.split('.').length >= ${router.minLabels}
|
|
8
|
-
}
|
|
9
|
-
`;
|
|
10
|
-
const routeSubrequest = router === undefined
|
|
11
|
-
? ''
|
|
12
|
-
: `
|
|
13
|
-
routeSubrequest: (url, env) => {
|
|
14
|
-
const labels = url.hostname.split('.')
|
|
15
|
-
if (env.DISPATCHER && labels[1] === 'svc') return env.DISPATCHER.get(labels[0]!)
|
|
16
|
-
if (env.${router.binding} && isInstanceHost(url.hostname)) return env.${router.binding}
|
|
17
|
-
return null
|
|
18
|
-
},`;
|
|
19
|
-
return `// AUTO-GENERATED by @astrale-os/adapter-cloudflare — do not edit.
|
|
20
|
-
// Domain origin: ${options.origin}
|
|
21
|
-
import type { BuildMaterial } from '@astrale-os/sdk/deployment/build'
|
|
22
|
-
import type { CloudflareAdapterBindings } from '@astrale-os/adapter-cloudflare/worker'
|
|
23
|
-
|
|
24
|
-
import { cloudflareWorkerEntry } from '@astrale-os/adapter-cloudflare/worker'
|
|
25
|
-
import { decodeSigningIdentity, runtimeBindings } from '@astrale-os/adapter-cloudflare/worker'
|
|
26
|
-
|
|
27
|
-
type WorkerEnv = CloudflareEnv & CloudflareAdapterBindings & {
|
|
28
|
-
readonly ASTRALE_SIGNING_IDENTITY: string
|
|
29
|
-
}
|
|
30
|
-
type RuntimeEnv = Omit<WorkerEnv, 'ASTRALE_SIGNING_IDENTITY'>
|
|
31
|
-
${routerPredicate}
|
|
32
|
-
export default cloudflareWorkerEntry<WorkerEnv, RuntimeEnv>()({
|
|
33
|
-
load: async () => ({
|
|
34
|
-
runtime: (await import(${JSON.stringify(options.runtimeSpecifier)})).default,
|
|
35
|
-
material: ${JSON.stringify(options.material)} as const satisfies BuildMaterial,
|
|
36
|
-
}),
|
|
37
|
-
privateKey: (env) => decodeSigningIdentity(env.ASTRALE_SIGNING_IDENTITY),
|
|
38
|
-
resolveEnvironment: runtimeBindings,
|
|
39
|
-
resolveUrl: (env, requestOrigin) => env.WORKER_URL ?? env.IDENTITY_ISS ?? requestOrigin,
|
|
40
|
-
${options.providerAssignedWorker === undefined ? '' : `providerAssignedWorker: ${JSON.stringify(options.providerAssignedWorker)},`}
|
|
41
|
-
selfBinding: (env) => env.SELF,${routeSubrequest}
|
|
42
|
-
})
|
|
43
|
-
`;
|
|
44
|
-
}
|
|
45
|
-
/** Generate the isolate-startup entry that realizes the heavy Service on first request. */
|
|
46
|
-
export function generateExecutionEntry(serviceSpecifier) {
|
|
47
|
-
return `// AUTO-GENERATED by @astrale-os/adapter-cloudflare — do not edit.
|
|
48
|
-
import type { CloudflareWorker } from '@astrale-os/adapter-cloudflare/worker'
|
|
49
|
-
|
|
50
|
-
const SERVICE_SPECIFIER = ${JSON.stringify(serviceSpecifier)}
|
|
51
|
-
let servicePromise: Promise<CloudflareWorker<CloudflareEnv>> | undefined
|
|
52
|
-
|
|
53
|
-
export default {
|
|
54
|
-
async fetch(request: Request, environment: CloudflareEnv, context: ExecutionContext) {
|
|
55
|
-
return (await service()).fetch(request, environment, context)
|
|
56
|
-
},
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function service(): Promise<CloudflareWorker<CloudflareEnv>> {
|
|
60
|
-
return (servicePromise ??= import(SERVICE_SPECIFIER).then((loaded: unknown) => {
|
|
61
|
-
if (loaded === null || typeof loaded !== 'object') invalid()
|
|
62
|
-
const worker = Reflect.get(loaded, 'default') as unknown
|
|
63
|
-
if (worker === null || typeof worker !== 'object' || typeof Reflect.get(worker, 'fetch') !== 'function') invalid()
|
|
64
|
-
return worker as CloudflareWorker<CloudflareEnv>
|
|
65
|
-
}))
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function invalid(): never {
|
|
69
|
-
throw new TypeError('Cloudflare execution Service module is invalid.')
|
|
70
|
-
}
|
|
71
|
-
`;
|
|
72
|
-
}
|
|
1
|
+
export { generateExecutionEntry } from '../worker/codegen/entry.js';
|
|
2
|
+
export { generateExecutionService } from '../worker/codegen/service.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { generateGatewayEntry } from '../gateway/source.js';
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
return `// AUTO-GENERATED by @astrale-os/adapter-cloudflare — do not edit.
|
|
3
|
-
import { cloudflareGatewayEntry } from '@astrale-os/adapter-cloudflare/worker'
|
|
4
|
-
|
|
5
|
-
export default cloudflareGatewayEntry({ current: ${JSON.stringify(revision)} })
|
|
6
|
-
`;
|
|
7
|
-
}
|
|
1
|
+
export { generateGatewayEntry } from '../gateway/source.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { addressing } from '@astrale-os/sdk/deployment/release';
|
|
2
|
+
export function deploymentAddressing(parameters) {
|
|
3
|
+
const routed = parameters.route === undefined ? undefined : addressing(`https://${parameters.route}`).issuer;
|
|
4
|
+
if (parameters.addressing === undefined)
|
|
5
|
+
return routed;
|
|
6
|
+
const configured = addressing(parameters.addressing).issuer;
|
|
7
|
+
if (routed !== undefined && configured !== routed) {
|
|
8
|
+
throw new TypeError('Cloudflare route and addressing identify different origins.');
|
|
9
|
+
}
|
|
10
|
+
return configured;
|
|
11
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CloudflareParams } from '../../params.js';
|
|
2
|
+
export declare function resolveRouter(input: CloudflareParams['router']): {
|
|
3
|
+
readonly binding: string;
|
|
4
|
+
readonly service: string;
|
|
5
|
+
readonly hostSuffix: string;
|
|
6
|
+
readonly minLabels: number;
|
|
7
|
+
} | undefined;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function resolveRouter(input) {
|
|
2
|
+
if (input === false)
|
|
3
|
+
return undefined;
|
|
4
|
+
const value = input ?? {};
|
|
5
|
+
return Object.freeze({
|
|
6
|
+
binding: value.binding ?? 'ROUTER',
|
|
7
|
+
service: value.service ?? 'admin-router',
|
|
8
|
+
hostSuffix: value.hostSuffix ?? '.astrale.ai',
|
|
9
|
+
minLabels: value.minLabels ?? 4,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
const WORKER_NAME = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u;
|
|
3
|
+
export function workerName(parameters, origin) {
|
|
4
|
+
if (parameters.workerName !== undefined) {
|
|
5
|
+
if (!WORKER_NAME.test(parameters.workerName) || parameters.workerName.length > 63) {
|
|
6
|
+
throw new TypeError('Cloudflare workerName is invalid.');
|
|
7
|
+
}
|
|
8
|
+
return parameters.workerName;
|
|
9
|
+
}
|
|
10
|
+
const readable = origin
|
|
11
|
+
.toLowerCase()
|
|
12
|
+
.replace(/[^a-z0-9]+/gu, '-')
|
|
13
|
+
.slice(0, 12)
|
|
14
|
+
.replace(/^-+|-+$/gu, '') || 'domain';
|
|
15
|
+
const hexadecimal = createHash('sha256').update(origin).digest('hex');
|
|
16
|
+
const identity = BigInt(`0x${hexadecimal}`).toString(36).padStart(50, '0');
|
|
17
|
+
return `${readable}-${identity}`;
|
|
18
|
+
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export declare function resolveRouter(input: CloudflareParams['router']): {
|
|
5
|
-
readonly binding: string;
|
|
6
|
-
readonly service: string;
|
|
7
|
-
readonly hostSuffix: string;
|
|
8
|
-
readonly minLabels: number;
|
|
9
|
-
} | undefined;
|
|
1
|
+
export { deploymentAddressing } from './configuration/addressing.js';
|
|
2
|
+
export { resolveRouter } from './configuration/router.js';
|
|
3
|
+
export { workerName } from './configuration/worker-name.js';
|
|
@@ -1,40 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export function deploymentAddressing(parameters) {
|
|
5
|
-
const routed = parameters.route === undefined ? undefined : addressing(`https://${parameters.route}`).issuer;
|
|
6
|
-
if (parameters.addressing === undefined)
|
|
7
|
-
return routed;
|
|
8
|
-
const configured = addressing(parameters.addressing).issuer;
|
|
9
|
-
if (routed !== undefined && configured !== routed) {
|
|
10
|
-
throw new TypeError('Cloudflare route and addressing identify different origins.');
|
|
11
|
-
}
|
|
12
|
-
return configured;
|
|
13
|
-
}
|
|
14
|
-
export function workerName(parameters, origin) {
|
|
15
|
-
if (parameters.workerName !== undefined) {
|
|
16
|
-
if (!WORKER_NAME.test(parameters.workerName) || parameters.workerName.length > 63) {
|
|
17
|
-
throw new TypeError('Cloudflare workerName is invalid.');
|
|
18
|
-
}
|
|
19
|
-
return parameters.workerName;
|
|
20
|
-
}
|
|
21
|
-
const readable = origin
|
|
22
|
-
.toLowerCase()
|
|
23
|
-
.replace(/[^a-z0-9]+/gu, '-')
|
|
24
|
-
.slice(0, 12)
|
|
25
|
-
.replace(/^-+|-+$/gu, '') || 'domain';
|
|
26
|
-
const hexadecimal = createHash('sha256').update(origin).digest('hex');
|
|
27
|
-
const identity = BigInt(`0x${hexadecimal}`).toString(36).padStart(50, '0');
|
|
28
|
-
return `${readable}-${identity}`;
|
|
29
|
-
}
|
|
30
|
-
export function resolveRouter(input) {
|
|
31
|
-
if (input === false)
|
|
32
|
-
return undefined;
|
|
33
|
-
const value = input ?? {};
|
|
34
|
-
return Object.freeze({
|
|
35
|
-
binding: value.binding ?? 'ROUTER',
|
|
36
|
-
service: value.service ?? 'admin-router',
|
|
37
|
-
hostSuffix: value.hostSuffix ?? '.astrale.ai',
|
|
38
|
-
minLabels: value.minLabels ?? 4,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
1
|
+
export { deploymentAddressing } from './configuration/addressing.js';
|
|
2
|
+
export { resolveRouter } from './configuration/router.js';
|
|
3
|
+
export { workerName } from './configuration/worker-name.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PreparedArtifact } from '@astrale-os/sdk/deployment/adapter';
|
|
2
|
+
import type { CloudflareParams } from '../params.js';
|
|
3
|
+
import type { WorkerArtifact } from './worker/index.js';
|
|
4
|
+
export declare function admitDirectPlacement(artifact: PreparedArtifact, worker: WorkerArtifact, parameters: CloudflareParams): void;
|