@astrale-os/adapter-cloudflare 0.5.0-beta.37 → 0.5.0-beta.39

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 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: `./${context.artifact.entrypoint}`,
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 }),
@@ -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
- /** JavaScript modules retained outside the startup entry and loaded on demand. */
30
+ /** Modules retained outside the startup entry and loaded on demand. */
31
31
  modules?: {
32
32
  readonly baseDir: string;
33
- readonly globs: readonly string[];
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
- type: 'ESModule',
70
- globs: [...opts.modules.globs],
71
- fallthrough: true,
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];
@@ -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 moduleGlobs(worker, directory) {
57
- return worker.release.modules
58
- .filter((module) => module.path !== worker.release.entrypoint)
59
- .map((module) => {
60
- const relative = posix.relative(directory, module.path);
61
- if (relative === '' || relative === '..' || relative.startsWith('../'))
62
- mismatch();
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));
@@ -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) {
@@ -72,7 +72,7 @@ export async function prepareExecution(input) {
72
72
  ...(input.params.route === undefined ? {} : { route: input.params.route }),
73
73
  vars: runtimeVars(input.params, input.configuredIssuer),
74
74
  secretBindings: [SIGNING_IDENTITY_BINDING],
75
- modules: { baseDir: '.', globs: [RELEASE_SERVICE] },
75
+ modules: { baseDir: '.', rules: [{ type: 'ESModule', globs: [RELEASE_SERVICE] }] },
76
76
  ...(input.router === undefined
77
77
  ? {}
78
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/adapter-cloudflare",
3
- "version": "0.5.0-beta.37",
3
+ "version": "0.5.0-beta.39",
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.34"
48
+ "@astrale-os/sdk": "^0.5.0-beta.36"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@astrale-os/ox": ">=0.1.0 <1.0.0",