@astrale-os/adapter-cloudflare 0.5.0-beta.36 → 0.5.0-beta.38
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.js +5 -1
- package/dist/build/artifact.js +1 -1
- package/dist/build/codegen/wrangler.d.ts +5 -2
- package/dist/build/codegen/wrangler.js +5 -7
- package/dist/build/direct.js +9 -15
- package/dist/build/gateway/prepare.js +2 -1
- package/dist/build/gateway/source.d.ts +1 -1
- package/dist/build/gateway/source.js +2 -2
- package/dist/build/worker/artifact.load.js +6 -0
- package/dist/build/worker/codegen/entry.d.ts +1 -1
- package/dist/build/worker/codegen/entry.js +2 -2
- package/dist/build/worker/codegen/service.d.ts +1 -0
- package/dist/build/worker/codegen/service.js +4 -3
- package/dist/build/worker/execution.prepare.js +5 -2
- package/dist/build/worker/modules.d.ts +11 -0
- package/dist/build/worker/modules.js +26 -0
- package/dist/build/worker/specifier.d.ts +1 -0
- package/dist/build/worker/specifier.js +5 -0
- package/package.json +2 -2
package/dist/adapter.js
CHANGED
|
@@ -7,6 +7,8 @@ import { artifact, materialize } from './build/artifact.js';
|
|
|
7
7
|
import { generateWranglerConfig } from './build/codegen/wrangler.js';
|
|
8
8
|
import { resolveRouter, workerName } from './build/configuration.js';
|
|
9
9
|
import { startFrontend } from './build/frontend-v1.js';
|
|
10
|
+
import { loadWorkerArtifact } from './build/worker/index.js';
|
|
11
|
+
import { workerModules } from './build/worker/modules.js';
|
|
10
12
|
import { ensureWranglerDispatchNamespace, runWranglerDeploymentStatus, runWranglerDeploy, runWranglerDev, runWranglerReleaseDeploy, } from './build/wrangler-cli.js';
|
|
11
13
|
import { deployCloudflare } from './deploy/index.js';
|
|
12
14
|
import { signingIdentitySecrets } from './identity/secret.js';
|
|
@@ -34,6 +36,7 @@ export function cloudflareWithDependencies(environments, dependencies) {
|
|
|
34
36
|
environments,
|
|
35
37
|
prepare: dependencies.artifact,
|
|
36
38
|
async watch(parameters, context) {
|
|
39
|
+
const workerArtifact = loadWorkerArtifact(context.artifact);
|
|
37
40
|
const identity = await dependencies.signingIdentity({
|
|
38
41
|
projectDir: context.projectDir,
|
|
39
42
|
source: parameters.signingIdentity,
|
|
@@ -57,7 +60,8 @@ export function cloudflareWithDependencies(environments, dependencies) {
|
|
|
57
60
|
const configPath = join(directory, 'wrangler.watch.jsonc');
|
|
58
61
|
await writeFile(configPath, generateWranglerConfig({
|
|
59
62
|
workerName: name,
|
|
60
|
-
main: `./${
|
|
63
|
+
main: `./${workerArtifact.release.entrypoint}`,
|
|
64
|
+
modules: workerModules(workerArtifact.release),
|
|
61
65
|
vars: {
|
|
62
66
|
...parameters.vars,
|
|
63
67
|
...(parameters.host === undefined ? {} : { WORKER_URL: parameters.host }),
|
package/dist/build/artifact.js
CHANGED
|
@@ -57,7 +57,7 @@ async function prepare(params, context, direct) {
|
|
|
57
57
|
main: `./${RELEASE_ENTRY}`,
|
|
58
58
|
vars: runtimeVars(params, configuredIssuer),
|
|
59
59
|
secretBindings: [SIGNING_IDENTITY_BINDING],
|
|
60
|
-
modules: { baseDir: './bundle', globs: ['service.mjs'] },
|
|
60
|
+
modules: { baseDir: './bundle', rules: [{ type: 'ESModule', globs: ['service.mjs'] }] },
|
|
61
61
|
...(context.build.frontend?.source.kind === 'vite'
|
|
62
62
|
? {
|
|
63
63
|
frontend: {
|
|
@@ -27,10 +27,13 @@ export interface WranglerCodegenOptions {
|
|
|
27
27
|
vars?: Record<string, string>;
|
|
28
28
|
/** Secret binding names required by generated Worker code. */
|
|
29
29
|
secretBindings?: readonly string[];
|
|
30
|
-
/**
|
|
30
|
+
/** Modules retained outside the startup entry and loaded on demand. */
|
|
31
31
|
modules?: {
|
|
32
32
|
readonly baseDir: string;
|
|
33
|
-
readonly
|
|
33
|
+
readonly rules: readonly {
|
|
34
|
+
readonly type: 'ESModule' | 'CompiledWasm' | 'Text' | 'Data';
|
|
35
|
+
readonly globs: readonly string[];
|
|
36
|
+
}[];
|
|
34
37
|
};
|
|
35
38
|
/** Add the SELF service binding (autobinding). */
|
|
36
39
|
selfBinding: boolean;
|
|
@@ -64,13 +64,11 @@ export function generateWranglerConfig(opts) {
|
|
|
64
64
|
if (opts.modules !== undefined) {
|
|
65
65
|
config.find_additional_modules = true;
|
|
66
66
|
config.base_dir = opts.modules.baseDir;
|
|
67
|
-
config.rules =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
},
|
|
73
|
-
];
|
|
67
|
+
config.rules = opts.modules.rules.map((rule) => ({
|
|
68
|
+
type: rule.type,
|
|
69
|
+
globs: [...rule.globs],
|
|
70
|
+
fallthrough: true,
|
|
71
|
+
}));
|
|
74
72
|
}
|
|
75
73
|
if (opts.releases !== undefined) {
|
|
76
74
|
config.dispatch_namespaces = [opts.releases];
|
package/dist/build/direct.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { posix } from 'node:path';
|
|
2
1
|
import { isDeepStrictEqual } from 'node:util';
|
|
3
2
|
import { releaseNamespace, releaseWorkerName } from '../release/index.js';
|
|
4
3
|
import { generateWranglerConfig } from './codegen/wrangler.js';
|
|
5
4
|
import { resolveRouter, workerName } from './configuration.js';
|
|
6
5
|
import { frontendRoutes } from './frontend/routes.js';
|
|
6
|
+
import { workerModules } from './worker/modules.js';
|
|
7
7
|
export function admitDirectPlacement(artifact, worker, parameters) {
|
|
8
8
|
const name = workerName(parameters, worker.origin);
|
|
9
9
|
const release = config(artifact, 'wrangler.release.jsonc');
|
|
10
10
|
const gateway = config(artifact, 'wrangler.gateway.jsonc');
|
|
11
|
-
const directory = posix.dirname(worker.release.entrypoint);
|
|
12
11
|
const router = resolveRouter(parameters.router);
|
|
13
12
|
const frontend = artifact.build.frontend;
|
|
14
13
|
const hasViteFrontend = frontend?.source.kind === 'vite';
|
|
@@ -22,10 +21,7 @@ export function admitDirectPlacement(artifact, worker, parameters) {
|
|
|
22
21
|
main: `./${worker.release.entrypoint}`,
|
|
23
22
|
vars: worker.bindings.vars,
|
|
24
23
|
secretBindings: worker.bindings.requiredSecrets,
|
|
25
|
-
modules:
|
|
26
|
-
baseDir: `./${directory}`,
|
|
27
|
-
globs: moduleGlobs(worker, directory),
|
|
28
|
-
},
|
|
24
|
+
modules: directModules(worker.release),
|
|
29
25
|
...(hasViteFrontend
|
|
30
26
|
? {
|
|
31
27
|
frontend: {
|
|
@@ -53,15 +49,13 @@ export function admitDirectPlacement(artifact, worker, parameters) {
|
|
|
53
49
|
selfBinding: false,
|
|
54
50
|
}));
|
|
55
51
|
}
|
|
56
|
-
function
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return relative;
|
|
64
|
-
});
|
|
52
|
+
function directModules(worker) {
|
|
53
|
+
try {
|
|
54
|
+
return workerModules(worker);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
mismatch();
|
|
58
|
+
}
|
|
65
59
|
}
|
|
66
60
|
function generated(input) {
|
|
67
61
|
return JSON.parse(generateWranglerConfig(input));
|
|
@@ -3,11 +3,12 @@ import { dirname, join } from 'node:path';
|
|
|
3
3
|
import { admitWorkerBundle } from '../bundle/admit.js';
|
|
4
4
|
import { generateWranglerConfig } from '../codegen/wrangler.js';
|
|
5
5
|
import { qualifyWorkerBundle } from '../qualification.js';
|
|
6
|
+
import { workerModuleSpecifier } from '../worker/specifier.js';
|
|
6
7
|
import { runWranglerBundle } from '../wrangler-cli.js';
|
|
7
8
|
import { generateGatewayEntry } from './source.js';
|
|
8
9
|
export async function prepareGateway(input) {
|
|
9
10
|
const gatewaySource = join(input.directory, 'gateway.gen.ts');
|
|
10
|
-
await writeFile(gatewaySource, generateGatewayEntry(input.revision));
|
|
11
|
+
await writeFile(gatewaySource, generateGatewayEntry(input.revision, workerModuleSpecifier()));
|
|
11
12
|
const configPath = join(input.directory, 'wrangler.gateway.prepare.jsonc');
|
|
12
13
|
await writeFile(configPath, generateWranglerConfig({
|
|
13
14
|
workerName: input.name,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function generateGatewayEntry(revision: string): string;
|
|
1
|
+
export declare function generateGatewayEntry(revision: string, workerSpecifier?: string): string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export function generateGatewayEntry(revision) {
|
|
1
|
+
export function generateGatewayEntry(revision, workerSpecifier = '@astrale-os/adapter-cloudflare/worker') {
|
|
2
2
|
return `// AUTO-GENERATED by @astrale-os/adapter-cloudflare — do not edit.
|
|
3
|
-
import { cloudflareGatewayEntry } from
|
|
3
|
+
import { cloudflareGatewayEntry } from ${JSON.stringify(workerSpecifier)}
|
|
4
4
|
|
|
5
5
|
export default cloudflareGatewayEntry({ current: ${JSON.stringify(revision)} })
|
|
6
6
|
`;
|
|
@@ -19,6 +19,9 @@ export function loadWorkerArtifact(artifact) {
|
|
|
19
19
|
throw new TypeError('Cloudflare Worker artifact manifest is invalid JSON.', { cause });
|
|
20
20
|
}
|
|
21
21
|
const manifest = admitManifest(decoded);
|
|
22
|
+
if (artifact.entrypoint !== manifest.release.entrypoint) {
|
|
23
|
+
throw new TypeError('Cloudflare Worker artifact entrypoint differs from its manifest.');
|
|
24
|
+
}
|
|
22
25
|
const origin = artifact.build.schema.compiled.root.origin;
|
|
23
26
|
const revision = artifact.build.schema.compiled.root.revision;
|
|
24
27
|
if (manifest.origin !== origin || manifest.revision !== revision) {
|
|
@@ -82,6 +85,9 @@ function executable(artifact, manifest, claimed, label) {
|
|
|
82
85
|
if (!manifest.modules.some((module) => module.path === manifest.entrypoint)) {
|
|
83
86
|
throw new TypeError(`Cloudflare Worker ${label} entrypoint is not a module.`);
|
|
84
87
|
}
|
|
88
|
+
if (manifest.modules.find((module) => module.path === manifest.entrypoint)?.kind !== 'esm') {
|
|
89
|
+
throw new TypeError(`Cloudflare Worker ${label} entrypoint is not an ES module.`);
|
|
90
|
+
}
|
|
85
91
|
return Object.freeze({ entrypoint: manifest.entrypoint, modules: Object.freeze(modules) });
|
|
86
92
|
}
|
|
87
93
|
function admitManifest(input) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Generate the isolate-startup entry that realizes the heavy Service on first request. */
|
|
2
|
-
export declare function generateExecutionEntry(serviceSpecifier: string): string;
|
|
2
|
+
export declare function generateExecutionEntry(serviceSpecifier: string, workerSpecifier?: string): string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Generate the isolate-startup entry that realizes the heavy Service on first request. */
|
|
2
|
-
export function generateExecutionEntry(serviceSpecifier) {
|
|
2
|
+
export function generateExecutionEntry(serviceSpecifier, workerSpecifier = '@astrale-os/adapter-cloudflare/worker') {
|
|
3
3
|
return `// AUTO-GENERATED by @astrale-os/adapter-cloudflare — do not edit.
|
|
4
|
-
import type { CloudflareWorker } from
|
|
4
|
+
import type { CloudflareWorker } from ${JSON.stringify(workerSpecifier)}
|
|
5
5
|
|
|
6
6
|
const SERVICE_SPECIFIER = ${JSON.stringify(serviceSpecifier)}
|
|
7
7
|
let servicePromise: Promise<CloudflareWorker<CloudflareEnv>> | undefined
|
|
@@ -2,6 +2,7 @@ import type { BuildMaterial } from '@astrale-os/sdk/deployment/build';
|
|
|
2
2
|
export interface ExecutionCodegenOptions {
|
|
3
3
|
readonly origin: string;
|
|
4
4
|
readonly runtimeSpecifier: string;
|
|
5
|
+
readonly workerSpecifier?: string;
|
|
5
6
|
readonly material: BuildMaterial;
|
|
6
7
|
readonly maximumRequestBytes?: number;
|
|
7
8
|
readonly providerAssignedWorker?: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export function generateExecutionService(options) {
|
|
2
|
+
const workerSpecifier = options.workerSpecifier ?? '@astrale-os/adapter-cloudflare/worker';
|
|
2
3
|
const router = options.router;
|
|
3
4
|
const routerPredicate = router === undefined
|
|
4
5
|
? ''
|
|
@@ -19,10 +20,10 @@ function isInstanceHost(host: string): boolean {
|
|
|
19
20
|
return `// AUTO-GENERATED by @astrale-os/adapter-cloudflare — do not edit.
|
|
20
21
|
// Domain origin: ${options.origin}
|
|
21
22
|
import type { BuildMaterial } from '@astrale-os/sdk/deployment/build'
|
|
22
|
-
import type { CloudflareAdapterBindings } from
|
|
23
|
+
import type { CloudflareAdapterBindings } from ${JSON.stringify(workerSpecifier)}
|
|
23
24
|
|
|
24
|
-
import { cloudflareWorkerEntry } from
|
|
25
|
-
import { decodeSigningIdentity, runtimeBindings } from
|
|
25
|
+
import { cloudflareWorkerEntry } from ${JSON.stringify(workerSpecifier)}
|
|
26
|
+
import { decodeSigningIdentity, runtimeBindings } from ${JSON.stringify(workerSpecifier)}
|
|
26
27
|
|
|
27
28
|
type WorkerEnv = CloudflareEnv & CloudflareAdapterBindings & {
|
|
28
29
|
readonly ASTRALE_SIGNING_IDENTITY: string
|
|
@@ -8,15 +8,18 @@ import { generateWranglerConfig } from '../codegen/wrangler.js';
|
|
|
8
8
|
import { workerRequestLimit } from '../configuration.js';
|
|
9
9
|
import { qualifyWorkerBundle } from '../qualification.js';
|
|
10
10
|
import { runWranglerBundle } from '../wrangler-cli.js';
|
|
11
|
+
import { workerModuleSpecifier } from './specifier.js';
|
|
11
12
|
export const RELEASE_ENTRY = 'bundle/index.mjs';
|
|
12
13
|
export const RELEASE_SERVICE = 'bundle/service.mjs';
|
|
13
14
|
export async function prepareExecution(input) {
|
|
14
15
|
const runtimePath = resolve(input.context.projectDir, input.context.runtime.reference.path);
|
|
15
16
|
const runtimeSpecifier = moduleSpecifier(relative(input.directory, runtimePath));
|
|
17
|
+
const workerSpecifier = workerModuleSpecifier();
|
|
16
18
|
const maximumRequestBytes = workerRequestLimit(input.params.maximumRequestBytes);
|
|
17
19
|
const serviceSource = generateExecutionService({
|
|
18
20
|
origin: input.context.build.schema.compiled.root.origin,
|
|
19
21
|
runtimeSpecifier,
|
|
22
|
+
workerSpecifier,
|
|
20
23
|
material: material(input.context.build),
|
|
21
24
|
...(maximumRequestBytes === undefined ? {} : { maximumRequestBytes }),
|
|
22
25
|
...(input.configuredIssuer === undefined && input.direct
|
|
@@ -62,14 +65,14 @@ export async function prepareExecution(input) {
|
|
|
62
65
|
await mkdir(dirname(join(input.directory, RELEASE_SERVICE)), { recursive: true });
|
|
63
66
|
await writeFile(join(input.directory, RELEASE_SERVICE), service);
|
|
64
67
|
const sourcePath = join(input.directory, 'worker.gen.ts');
|
|
65
|
-
await writeFile(sourcePath, generateExecutionEntry('./service.mjs'));
|
|
68
|
+
await writeFile(sourcePath, generateExecutionEntry('./service.mjs', workerSpecifier));
|
|
66
69
|
const configPath = join(input.directory, 'wrangler.prepare.jsonc');
|
|
67
70
|
await writeFile(configPath, generateWranglerConfig({
|
|
68
71
|
workerName: input.name,
|
|
69
72
|
...(input.params.route === undefined ? {} : { route: input.params.route }),
|
|
70
73
|
vars: runtimeVars(input.params, input.configuredIssuer),
|
|
71
74
|
secretBindings: [SIGNING_IDENTITY_BINDING],
|
|
72
|
-
modules: { baseDir: '.', globs: [RELEASE_SERVICE] },
|
|
75
|
+
modules: { baseDir: '.', rules: [{ type: 'ESModule', globs: [RELEASE_SERVICE] }] },
|
|
73
76
|
...(input.router === undefined
|
|
74
77
|
? {}
|
|
75
78
|
: { router: { binding: input.router.binding, service: input.router.service } }),
|
|
@@ -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 @@
|
|
|
1
|
+
export declare function workerModuleSpecifier(): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrale-os/adapter-cloudflare",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.38",
|
|
4
4
|
"description": "Deploy an Astrale application through Cloudflare Workers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adapter",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"hono": "^4.6.20",
|
|
46
46
|
"jose": "^6.1.3",
|
|
47
47
|
"wrangler": "4.123.0",
|
|
48
|
-
"@astrale-os/sdk": "^0.5.0-beta.
|
|
48
|
+
"@astrale-os/sdk": "^0.5.0-beta.35"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@astrale-os/ox": ">=0.1.0 <1.0.0",
|