@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.
Files changed (72) hide show
  1. package/dist/adapter.d.ts +1 -1
  2. package/dist/adapter.js +33 -4
  3. package/dist/build/artifact.d.ts +3 -4
  4. package/dist/build/artifact.js +84 -151
  5. package/dist/build/bundle/admit.d.ts +1 -0
  6. package/dist/build/bundle/admit.js +9 -0
  7. package/dist/build/codegen/execution.d.ts +3 -15
  8. package/dist/build/codegen/execution.js +2 -72
  9. package/dist/build/codegen/gateway.d.ts +1 -1
  10. package/dist/build/codegen/gateway.js +1 -7
  11. package/dist/build/configuration/addressing.d.ts +2 -0
  12. package/dist/build/configuration/addressing.js +11 -0
  13. package/dist/build/configuration/router.d.ts +7 -0
  14. package/dist/build/configuration/router.js +11 -0
  15. package/dist/build/configuration/worker-name.d.ts +2 -0
  16. package/dist/build/configuration/worker-name.js +18 -0
  17. package/dist/build/configuration.d.ts +3 -9
  18. package/dist/build/configuration.js +3 -40
  19. package/dist/build/direct.d.ts +4 -0
  20. package/dist/build/direct.js +52 -0
  21. package/dist/build/frontend/routes.d.ts +2 -0
  22. package/dist/build/frontend/routes.js +11 -0
  23. package/dist/build/gateway/prepare.d.ts +8 -0
  24. package/dist/build/gateway/prepare.js +32 -0
  25. package/dist/build/gateway/source.d.ts +1 -0
  26. package/dist/build/gateway/source.js +7 -0
  27. package/dist/build/index.d.ts +3 -1
  28. package/dist/build/index.js +2 -1
  29. package/dist/build/materialize.d.ts +4 -0
  30. package/dist/build/materialize.js +10 -0
  31. package/dist/build/worker/artifact.d.ts +38 -0
  32. package/dist/build/worker/artifact.js +1 -0
  33. package/dist/build/worker/artifact.load.d.ts +3 -0
  34. package/dist/build/worker/artifact.load.js +266 -0
  35. package/dist/build/worker/artifact.manifest.d.ts +46 -0
  36. package/dist/build/worker/artifact.manifest.js +84 -0
  37. package/dist/build/worker/artifact.paths.d.ts +4 -0
  38. package/dist/build/worker/artifact.paths.js +25 -0
  39. package/dist/build/worker/codegen/entry.d.ts +2 -0
  40. package/dist/build/worker/codegen/entry.js +28 -0
  41. package/dist/build/worker/codegen/service.d.ts +13 -0
  42. package/dist/build/worker/codegen/service.js +44 -0
  43. package/dist/build/worker/execution.prepare.d.ts +18 -0
  44. package/dist/build/worker/execution.prepare.js +102 -0
  45. package/dist/build/worker/index.d.ts +2 -0
  46. package/dist/build/worker/index.js +1 -0
  47. package/dist/build/worker/runtime.d.ts +10 -0
  48. package/dist/build/worker/runtime.js +35 -0
  49. package/dist/build/wrangler/bundle.d.ts +10 -0
  50. package/dist/build/wrangler/bundle.js +29 -0
  51. package/dist/build/wrangler/deploy.d.ts +23 -0
  52. package/dist/build/wrangler/deploy.js +35 -0
  53. package/dist/build/wrangler/development.d.ts +15 -0
  54. package/dist/build/wrangler/development.js +135 -0
  55. package/dist/build/wrangler/namespace.d.ts +10 -0
  56. package/dist/build/wrangler/namespace.js +26 -0
  57. package/dist/build/wrangler/process.d.ts +15 -0
  58. package/dist/build/wrangler/process.js +103 -0
  59. package/dist/build/wrangler/release.d.ts +11 -0
  60. package/dist/build/wrangler/release.js +27 -0
  61. package/dist/build/wrangler/secrets.d.ts +6 -0
  62. package/dist/build/wrangler/secrets.js +58 -0
  63. package/dist/build/wrangler/status.d.ts +14 -0
  64. package/dist/build/wrangler/status.js +56 -0
  65. package/dist/build/wrangler/type-generation.d.ts +6 -0
  66. package/dist/build/wrangler/type-generation.js +19 -0
  67. package/dist/build/wrangler-cli.d.ts +8 -105
  68. package/dist/build/wrangler-cli.js +8 -448
  69. package/dist/deploy/deploy.d.ts +1 -1
  70. package/dist/deploy/deploy.js +125 -98
  71. package/dist/worker/gateway.js +2 -2
  72. 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, { signal: AbortSignal.timeout(5_000) });
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 new Promise((resolve) => setTimeout(resolve, 1_000));
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
+ }
@@ -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
- export declare function materialize(root: string, files: readonly {
6
- readonly path: string;
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>;
@@ -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 { readFile, writeFile, mkdir, rm } from 'node:fs/promises';
4
- import { dirname, join, relative, resolve } from 'node:path';
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 { qualifyWorkerBundle } from './qualification.js';
14
- import { runWranglerBundle } from './wrangler-cli.js';
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 serviceSource = generateExecutionService({
33
- origin: context.build.schema.compiled.root.origin,
34
- runtimeSpecifier,
35
- material: material(context.build),
36
- ...(configuredIssuer === undefined ? { providerAssignedWorker: name } : {}),
37
- ...(router === undefined
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 qualifyWorkerBundle({
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
- configPath: gatewayPrepareConfig,
129
- outDir: gatewayOutput,
130
- });
131
- await qualifyWorkerBundle({
132
- metafilePath: gateway.metafilePath,
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: 'wrangler.release.jsonc', content: encoder.encode(releaseConfig) },
170
- { path: 'wrangler.gateway.jsonc', content: encoder.encode(gatewayConfig) },
171
- { path: RELEASE_ENTRY, content: new Uint8Array(bundle) },
172
- { path: RELEASE_SERVICE, content: new Uint8Array(serviceBundle) },
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
- import type { BuildMaterial } from '@astrale-os/sdk/deployment/build';
2
- export interface ExecutionCodegenOptions {
3
- readonly origin: string;
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 function generateExecutionService(options) {
2
- const router = options.router;
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 declare function generateGatewayEntry(revision: string): string;
1
+ export { generateGatewayEntry } from '../gateway/source.js';
@@ -1,7 +1 @@
1
- export function generateGatewayEntry(revision) {
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,2 @@
1
+ import type { CloudflareParams } from '../../params.js';
2
+ export declare function deploymentAddressing(parameters: CloudflareParams): string | undefined;
@@ -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,2 @@
1
+ import type { CloudflareParams } from '../../params.js';
2
+ export declare function workerName(parameters: CloudflareParams, origin: string): string;
@@ -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
- import type { CloudflareParams } from '../params.js';
2
- export declare function deploymentAddressing(parameters: CloudflareParams): string | undefined;
3
- export declare function workerName(parameters: CloudflareParams, origin: string): string;
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
- import { addressing } from '@astrale-os/sdk/deployment/release';
2
- import { createHash } from 'node:crypto';
3
- const WORKER_NAME = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u;
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;