@astrale-os/adapter-cloudflare 0.5.0-beta.60 → 0.5.0-beta.62

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 (48) hide show
  1. package/README.md +14 -0
  2. package/dist/adapter.js +1 -3
  3. package/dist/build/artifact.d.ts +1 -1
  4. package/dist/build/artifact.js +140 -128
  5. package/dist/build/codegen/wrangler.d.ts +0 -5
  6. package/dist/build/codegen/wrangler.js +1 -5
  7. package/dist/build/direct.js +8 -13
  8. package/dist/build/worker/artifact.d.ts +2 -1
  9. package/dist/build/worker/artifact.load.js +37 -6
  10. package/dist/build/worker/artifact.manifest.d.ts +5 -4
  11. package/dist/build/worker/artifact.manifest.js +2 -2
  12. package/dist/build/wrangler/deploy.d.ts +1 -0
  13. package/dist/build/wrangler/deploy.js +10 -1
  14. package/dist/build/wrangler-cli.d.ts +0 -2
  15. package/dist/build/wrangler-cli.js +0 -2
  16. package/dist/deploy/deploy.d.ts +2 -4
  17. package/dist/deploy/deploy.js +15 -45
  18. package/dist/identity/binding.d.ts +1 -1
  19. package/dist/identity/binding.js +1 -1
  20. package/dist/identity/source.d.ts +1 -1
  21. package/dist/identity/source.js +1 -1
  22. package/dist/release/deployment.d.ts +44 -0
  23. package/dist/release/deployment.js +141 -0
  24. package/dist/release/index.d.ts +2 -2
  25. package/dist/release/index.js +2 -2
  26. package/dist/release/staged-worker-name.d.ts +3 -0
  27. package/dist/release/staged-worker-name.js +10 -0
  28. package/dist/worker/entry.d.ts +1 -1
  29. package/dist/worker/entry.js +1 -1
  30. package/dist/worker/index.d.ts +0 -1
  31. package/dist/worker/index.js +0 -1
  32. package/package.json +7 -2
  33. package/dist/build/codegen/gateway.d.ts +0 -1
  34. package/dist/build/codegen/gateway.js +0 -1
  35. package/dist/build/gateway/prepare.d.ts +0 -8
  36. package/dist/build/gateway/prepare.js +0 -33
  37. package/dist/build/gateway/source.d.ts +0 -1
  38. package/dist/build/gateway/source.js +0 -7
  39. package/dist/build/wrangler/namespace.d.ts +0 -10
  40. package/dist/build/wrangler/namespace.js +0 -26
  41. package/dist/build/wrangler/release.d.ts +0 -11
  42. package/dist/build/wrangler/release.js +0 -27
  43. package/dist/release/namespace.d.ts +0 -2
  44. package/dist/release/namespace.js +0 -6
  45. package/dist/release/target.d.ts +0 -2
  46. package/dist/release/target.js +0 -9
  47. package/dist/worker/gateway.d.ts +0 -15
  48. package/dist/worker/gateway.js +0 -26
package/README.md CHANGED
@@ -9,3 +9,17 @@ npm install @astrale-os/sdk@beta @astrale-os/adapter-cloudflare@beta
9
9
  ```
10
10
 
11
11
  Bare installs return to stable releases when the package set is promoted and npm `latest` advances.
12
+
13
+ ## Provider-local staging
14
+
15
+ Managed Cloudflare providers may stage immutable implementation candidates without exposing their
16
+ identity to Publications or installed Kernels:
17
+
18
+ ```ts
19
+ import { stagedWorkerName } from '@astrale-os/adapter-cloudflare/release'
20
+ ```
21
+
22
+ This subpath is runtime-safe. `stagedWorkerName(providerDeployment)` addresses one private staged
23
+ candidate. The public Worker name and `/invoke` endpoint remain stable across compatible
24
+ implementation and Schema updates. Provider staging identity never enters Release, Publication,
25
+ Kernel routing, or graph identity.
package/dist/adapter.js CHANGED
@@ -9,7 +9,7 @@ import { resolveRouter, workerName } from './build/configuration.js';
9
9
  import { startFrontend } from './build/frontend-v1.js';
10
10
  import { loadWorkerArtifact } from './build/worker/index.js';
11
11
  import { workerModules } from './build/worker/modules.js';
12
- import { ensureWranglerDispatchNamespace, runWranglerDeploymentStatus, runWranglerDeploy, runWranglerDev, runWranglerReleaseDeploy, } from './build/wrangler-cli.js';
12
+ import { runWranglerDeploymentStatus, runWranglerDeploy, runWranglerDev, } from './build/wrangler-cli.js';
13
13
  import { deployCloudflare } from './deploy/index.js';
14
14
  import { signingIdentitySecrets } from './identity/secret.js';
15
15
  import { signingIdentity } from './identity/source.js';
@@ -19,9 +19,7 @@ export function cloudflare(environments) {
19
19
  return cloudflareWithDependencies(environments, {
20
20
  artifact,
21
21
  materialize,
22
- ensureWranglerDispatchNamespace,
23
22
  runWranglerDeploy,
24
- runWranglerReleaseDeploy,
25
23
  runWranglerDeploymentStatus,
26
24
  runWranglerDev,
27
25
  startFrontend,
@@ -1,7 +1,7 @@
1
1
  import type { ArtifactSource, PrepareContext } from '@astrale-os/sdk/deployment/adapter';
2
2
  import type { CloudflareParams } from '../params.js';
3
3
  export { materialize } from './materialize.js';
4
- /** Prepare one revision Service and its stateless gateway without provider mutation. */
4
+ /** Prepare one portable Worker whose public provider address remains stable across builds. */
5
5
  export declare function artifact(params: CloudflareParams, context: PrepareContext): Promise<ArtifactSource>;
6
6
  /** Prepare the complete portable Cloudflare Worker without direct Wrangler placement files. */
7
7
  export declare function prepareWorkerArtifact(params: CloudflareParams, context: PrepareContext): Promise<ArtifactSource>;
@@ -1,19 +1,18 @@
1
1
  import { addressing } from '@astrale-os/sdk/deployment/release';
2
- import { mkdir } from 'node:fs/promises';
2
+ import { mkdir, mkdtemp, rm } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
4
  import { SIGNING_IDENTITY_BINDING } from '../identity/binding.js';
5
- import { releaseNamespace, releaseWorkerName } from '../release/index.js';
5
+ import { workerDeployment } from '../release/index.js';
6
6
  import { generateWranglerConfig } from './codegen/wrangler.js';
7
7
  import { deploymentAddressing, resolveRouter, workerName } from './configuration.js';
8
8
  import { frontendFiles } from './frontend-v1.js';
9
9
  import { frontendRoutes } from './frontend/routes.js';
10
- import { prepareGateway } from './gateway/prepare.js';
11
10
  import { encodeWorkerArtifactManifest, inferMediaType, workerContentDigest, WORKER_MANIFEST_PATH, } from './worker/artifact.manifest.js';
12
11
  import { prepareExecution, RELEASE_ENTRY, RELEASE_SERVICE, runtimeVars, } from './worker/execution.prepare.js';
13
12
  import { admitWorkerRuntimeConfiguration } from './worker/runtime.js';
14
13
  export { materialize } from './materialize.js';
15
14
  const encoder = new TextEncoder();
16
- /** Prepare one revision Service and its stateless gateway without provider mutation. */
15
+ /** Prepare one portable Worker whose public provider address remains stable across builds. */
17
16
  export async function artifact(params, context) {
18
17
  return prepare(params, context, true);
19
18
  }
@@ -23,129 +22,142 @@ export async function prepareWorkerArtifact(params, context) {
23
22
  }
24
23
  async function prepare(params, context, direct) {
25
24
  const stateDirectory = join(context.projectDir, '.astrale');
26
- const directory = join(stateDirectory, 'runtime');
27
- await mkdir(directory, { recursive: true });
28
- const router = resolveRouter(params.router);
29
- const name = workerName(params, context.build.schema.compiled.root.origin);
30
- const revision = context.build.schema.compiled.root.revision;
31
- const namespace = releaseNamespace(name);
32
- const target = releaseWorkerName(revision);
33
- const configuredIssuer = deploymentAddressing(params);
34
- const execution = await prepareExecution({
35
- params,
36
- context,
37
- directory,
38
- name,
39
- direct,
40
- configuredIssuer,
41
- router,
42
- });
43
- const frontend = await frontendFiles({
44
- frontend: context.build.frontend,
45
- projectDir: context.projectDir,
46
- });
47
- const gatewayBundle = await prepareGateway({
48
- projectDir: context.projectDir,
49
- directory,
50
- name,
51
- ...(params.route === undefined ? {} : { route: params.route }),
52
- namespace,
53
- revision,
54
- });
55
- const releaseConfig = generateWranglerConfig({
56
- workerName: target,
57
- main: `./${RELEASE_ENTRY}`,
58
- vars: runtimeVars(params, configuredIssuer),
59
- secretBindings: [SIGNING_IDENTITY_BINDING],
60
- modules: { baseDir: './bundle', rules: [{ type: 'ESModule', globs: ['service.mjs'] }] },
61
- ...(context.build.frontend?.source.kind === 'vite'
62
- ? {
63
- frontend: {
64
- directory: './frontend',
65
- routes: frontendRoutes(context.build.frontend),
66
- dev: false,
67
- },
68
- }
69
- : {}),
70
- ...(router === undefined
71
- ? {}
72
- : { router: { binding: router.binding, service: router.service } }),
73
- ...(params.wrangler === undefined ? {} : { wrangler: params.wrangler }),
74
- selfBinding: false,
75
- });
76
- const gatewayConfig = generateWranglerConfig({
77
- workerName: name,
78
- main: './gateway/index.mjs',
79
- ...(params.route === undefined ? {} : { route: params.route }),
80
- releases: { binding: 'RELEASES', namespace },
81
- selfBinding: false,
82
- });
83
- const runtime = admitWorkerRuntimeConfiguration(releaseConfig);
84
- const manifest = encodeWorkerArtifactManifest({
85
- origin: context.build.schema.compiled.root.origin,
86
- revision,
87
- release: {
25
+ await mkdir(stateDirectory, { recursive: true });
26
+ const directory = await mkdtemp(join(stateDirectory, 'prepare-'));
27
+ try {
28
+ const router = resolveRouter(params.router);
29
+ const name = workerName(params, context.build.schema.compiled.root.origin);
30
+ const revision = context.build.schema.compiled.root.revision;
31
+ const configuredIssuer = deploymentAddressing(params);
32
+ const modules = await prepareExecution({
33
+ params,
34
+ context,
35
+ directory,
36
+ name,
37
+ direct,
38
+ configuredIssuer,
39
+ router,
40
+ });
41
+ const frontend = await frontendFiles({
42
+ frontend: context.build.frontend,
43
+ projectDir: context.projectDir,
44
+ });
45
+ const releaseConfig = generateWranglerConfig({
46
+ workerName: name,
47
+ main: `./${RELEASE_ENTRY}`,
48
+ ...(params.route === undefined ? {} : { route: params.route }),
49
+ vars: runtimeVars(params, configuredIssuer),
50
+ secretBindings: [SIGNING_IDENTITY_BINDING],
51
+ modules: { baseDir: './bundle', rules: [{ type: 'ESModule', globs: ['service.mjs'] }] },
52
+ ...(context.build.frontend?.source.kind === 'vite'
53
+ ? {
54
+ frontend: {
55
+ directory: './frontend',
56
+ routes: frontendRoutes(context.build.frontend),
57
+ dev: false,
58
+ },
59
+ }
60
+ : {}),
61
+ ...(router === undefined
62
+ ? {}
63
+ : { router: { binding: router.binding, service: router.service } }),
64
+ ...(params.wrangler === undefined ? {} : { wrangler: params.wrangler }),
65
+ selfBinding: false,
66
+ });
67
+ const runtime = admitWorkerRuntimeConfiguration(releaseConfig);
68
+ const deployment = workerDeployment({
69
+ release: {
70
+ entrypoint: RELEASE_ENTRY,
71
+ modules: [
72
+ { path: RELEASE_ENTRY, kind: 'esm', content: modules.entry },
73
+ { path: RELEASE_SERVICE, kind: 'esm', content: modules.service },
74
+ ],
75
+ },
76
+ runtime,
77
+ bindings: {
78
+ vars: runtime.vars,
79
+ services: runtime.services,
80
+ requiredSecrets: [SIGNING_IDENTITY_BINDING],
81
+ },
82
+ ...(frontend.length === 0
83
+ ? {}
84
+ : {
85
+ assets: {
86
+ files: frontend.map((file) => {
87
+ const contentType = file.mediaType ?? inferMediaType(file.path);
88
+ return {
89
+ path: `/${file.path}`,
90
+ content: file.bytes(),
91
+ ...(contentType === undefined ? {} : { contentType }),
92
+ };
93
+ }),
94
+ notFound: 'none',
95
+ runWorkerFirst: true,
96
+ htmlHandling: 'none',
97
+ },
98
+ }),
99
+ });
100
+ const manifest = encodeWorkerArtifactManifest({
101
+ origin: context.build.schema.compiled.root.origin,
102
+ revision,
103
+ deployment,
104
+ release: {
105
+ entrypoint: RELEASE_ENTRY,
106
+ modules: [
107
+ { path: RELEASE_ENTRY, kind: 'esm', digest: workerContentDigest(modules.entry) },
108
+ { path: RELEASE_SERVICE, kind: 'esm', digest: workerContentDigest(modules.service) },
109
+ ],
110
+ },
111
+ runtime: {
112
+ compatibilityDate: runtime.compatibilityDate,
113
+ compatibilityFlags: runtime.compatibilityFlags,
114
+ },
115
+ bindings: {
116
+ vars: runtime.vars,
117
+ services: runtime.services,
118
+ requiredSecrets: [SIGNING_IDENTITY_BINDING],
119
+ },
120
+ ...(frontend.length === 0
121
+ ? {}
122
+ : {
123
+ assets: {
124
+ files: frontend.map((file) => {
125
+ const contentType = file.mediaType ?? inferMediaType(file.path);
126
+ return {
127
+ path: `/${file.path}`,
128
+ artifactPath: `frontend/${file.path}`,
129
+ digest: workerContentDigest(file.bytes()),
130
+ ...(contentType === undefined ? {} : { contentType }),
131
+ };
132
+ }),
133
+ notFound: 'none',
134
+ runWorkerFirst: true,
135
+ htmlHandling: 'none',
136
+ },
137
+ }),
138
+ });
139
+ const files = [
140
+ { path: RELEASE_ENTRY, content: modules.entry },
141
+ { path: RELEASE_SERVICE, content: modules.service },
142
+ { path: WORKER_MANIFEST_PATH, content: manifest },
143
+ ...frontend.map((file) => ({
144
+ path: `frontend/${file.path}`,
145
+ content: file.bytes(),
146
+ })),
147
+ ...(direct ? [{ path: 'wrangler.jsonc', content: encoder.encode(releaseConfig) }] : []),
148
+ ];
149
+ return Object.freeze({
88
150
  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
- htmlHandling: 'none',
125
- },
126
- }),
127
- });
128
- const files = [
129
- { path: RELEASE_ENTRY, content: execution.entry },
130
- { path: RELEASE_SERVICE, content: execution.service },
131
- { path: 'gateway/index.mjs', content: gatewayBundle },
132
- { path: WORKER_MANIFEST_PATH, content: manifest },
133
- ...frontend.map((file) => ({
134
- path: `frontend/${file.path}`,
135
- content: file.bytes(),
136
- })),
137
- ...(direct
138
- ? [
139
- { path: 'wrangler.release.jsonc', content: encoder.encode(releaseConfig) },
140
- { path: 'wrangler.gateway.jsonc', content: encoder.encode(gatewayConfig) },
141
- ]
142
- : []),
143
- ];
144
- return Object.freeze({
145
- entrypoint: RELEASE_ENTRY,
146
- files: Object.freeze(files),
147
- addressing: configuredIssuer === undefined
148
- ? Object.freeze({ kind: 'provider-assigned', claim: name })
149
- : Object.freeze({ kind: 'configured', addressing: addressing(configuredIssuer) }),
150
- });
151
+ files: Object.freeze(files),
152
+ addressing: configuredIssuer === undefined
153
+ ? Object.freeze({ kind: 'provider-assigned', claim: name })
154
+ : Object.freeze({
155
+ kind: 'configured',
156
+ addressing: addressing(configuredIssuer),
157
+ }),
158
+ });
159
+ }
160
+ finally {
161
+ await rm(directory, { recursive: true, force: true });
162
+ }
151
163
  }
@@ -37,11 +37,6 @@ export interface WranglerCodegenOptions {
37
37
  };
38
38
  /** Add the SELF service binding (autobinding). */
39
39
  selfBinding: boolean;
40
- /** Bind the stable gateway to its private revision namespace. */
41
- releases?: {
42
- readonly binding: string;
43
- readonly namespace: string;
44
- };
45
40
  /**
46
41
  * Add a service binding to a router Worker for instance-host subrequest
47
42
  * routing (see `CloudflareParams.router`). Pairs with the worker
@@ -35,8 +35,7 @@ export function generateWranglerConfig(opts) {
35
35
  run_worker_first: opts.frontend.dev
36
36
  ? true
37
37
  : [
38
- '/releases',
39
- '/releases/*',
38
+ '/invoke',
40
39
  '/install',
41
40
  '/install/*',
42
41
  '/health',
@@ -70,9 +69,6 @@ export function generateWranglerConfig(opts) {
70
69
  fallthrough: true,
71
70
  }));
72
71
  }
73
- if (opts.releases !== undefined) {
74
- config.dispatch_namespaces = [opts.releases];
75
- }
76
72
  const merged = opts.wrangler ? mergeUserConfig(config, opts.wrangler) : config;
77
73
  return JSON.stringify(merged, null, 2) + '\n';
78
74
  }
@@ -1,13 +1,11 @@
1
1
  import { isDeepStrictEqual } from 'node:util';
2
- import { releaseNamespace, releaseWorkerName } from '../release/index.js';
3
2
  import { generateWranglerConfig } from './codegen/wrangler.js';
4
3
  import { resolveRouter, workerName } from './configuration.js';
5
4
  import { frontendRoutes } from './frontend/routes.js';
6
5
  import { workerModules } from './worker/modules.js';
7
6
  export function admitDirectPlacement(artifact, worker, parameters) {
8
7
  const name = workerName(parameters, worker.origin);
9
- const release = config(artifact, 'wrangler.release.jsonc');
10
- const gateway = config(artifact, 'wrangler.gateway.jsonc');
8
+ const release = config(artifact, 'wrangler.jsonc');
11
9
  const router = resolveRouter(parameters.router);
12
10
  const frontend = artifact.build.frontend;
13
11
  const hasViteFrontend = frontend?.source.kind === 'vite';
@@ -17,8 +15,9 @@ export function admitDirectPlacement(artifact, worker, parameters) {
17
15
  equal(worker.assets.runWorkerFirst, true);
18
16
  }
19
17
  equal(release, generated({
20
- workerName: releaseWorkerName(worker.revision),
18
+ workerName: name,
21
19
  main: `./${worker.release.entrypoint}`,
20
+ ...(parameters.route === undefined ? {} : { route: parameters.route }),
22
21
  vars: worker.bindings.vars,
23
22
  secretBindings: worker.bindings.requiredSecrets,
24
23
  modules: directModules(worker.release),
@@ -41,13 +40,6 @@ export function admitDirectPlacement(artifact, worker, parameters) {
41
40
  equalStringCollection(release.compatibility_flags, worker.runtime.compatibilityFlags);
42
41
  equal(release.services ?? [], worker.bindings.services.map(serviceBinding));
43
42
  equal(record(release.assets).html_handling, worker.assets?.htmlHandling);
44
- equal(gateway, generated({
45
- workerName: name,
46
- main: `./${worker.gateway.entrypoint}`,
47
- ...(parameters.route === undefined ? {} : { route: parameters.route }),
48
- releases: { binding: 'RELEASES', namespace: releaseNamespace(name) },
49
- selfBinding: false,
50
- }));
51
43
  }
52
44
  function directModules(worker) {
53
45
  try {
@@ -83,8 +75,11 @@ function record(input) {
83
75
  : {};
84
76
  }
85
77
  function equal(actual, expected) {
86
- if (!isDeepStrictEqual(actual, expected))
87
- mismatch();
78
+ if (!isDeepStrictEqual(actual, expected)) {
79
+ throw new TypeError('Direct Cloudflare placement differs from its admitted Worker artifact.', {
80
+ cause: { actual, expected },
81
+ });
82
+ }
88
83
  }
89
84
  function equalStringCollection(actual, expected) {
90
85
  if (!Array.isArray(actual) ||
@@ -1,3 +1,4 @@
1
+ import type { WorkerDeploymentId } from '../../release/deployment.js';
1
2
  export type WorkerModuleKind = 'esm' | 'wasm' | 'text' | 'data';
2
3
  export interface WorkerArtifactModule {
3
4
  readonly path: string;
@@ -11,8 +12,8 @@ export interface WorkerArtifactExecutable {
11
12
  export interface WorkerArtifact {
12
13
  readonly origin: string;
13
14
  readonly revision: string;
15
+ readonly deployment: WorkerDeploymentId;
14
16
  readonly release: WorkerArtifactExecutable;
15
- readonly gateway: WorkerArtifactExecutable;
16
17
  readonly runtime: {
17
18
  readonly compatibilityDate: string;
18
19
  readonly compatibilityFlags: readonly string[];
@@ -1,5 +1,6 @@
1
1
  import { isPreparedArtifact } from '@astrale-os/sdk/deployment/verify';
2
2
  import { createHash } from 'node:crypto';
3
+ import { workerDeployment } from '../../release/deployment.js';
3
4
  import { WORKER_ARTIFACT_FORMAT, WORKER_ARTIFACT_VERSION } from './artifact.manifest.js';
4
5
  import { artifactPath, assetPath, comparePath, WORKER_MANIFEST_PATH } from './artifact.paths.js';
5
6
  const decoder = new TextDecoder('utf-8', { fatal: true });
@@ -29,7 +30,6 @@ export function loadWorkerArtifact(artifact) {
29
30
  }
30
31
  const claimed = new Set([WORKER_MANIFEST_PATH]);
31
32
  const release = executable(artifact, manifest.release, claimed, 'release');
32
- const gateway = executable(artifact, manifest.gateway, claimed, 'gateway');
33
33
  const assets = manifest.assets?.files.map((file) => {
34
34
  claim(claimed, file.artifactPath);
35
35
  const source = requiredFile(artifact, file.artifactPath);
@@ -42,11 +42,42 @@ export function loadWorkerArtifact(artifact) {
42
42
  bytes: () => new Uint8Array(content),
43
43
  });
44
44
  });
45
+ const deployment = workerDeployment({
46
+ release: {
47
+ entrypoint: release.entrypoint,
48
+ modules: release.modules.map((module) => ({
49
+ path: module.path,
50
+ kind: module.kind,
51
+ content: module.bytes(),
52
+ })),
53
+ },
54
+ runtime: manifest.runtime,
55
+ bindings: manifest.bindings,
56
+ ...(manifest.assets === undefined
57
+ ? {}
58
+ : {
59
+ assets: {
60
+ files: assets.map((file) => ({
61
+ path: file.path,
62
+ content: file.bytes(),
63
+ ...(file.contentType === undefined ? {} : { contentType: file.contentType }),
64
+ })),
65
+ notFound: manifest.assets.notFound,
66
+ runWorkerFirst: manifest.assets.runWorkerFirst,
67
+ ...(manifest.assets.htmlHandling === undefined
68
+ ? {}
69
+ : { htmlHandling: manifest.assets.htmlHandling }),
70
+ },
71
+ }),
72
+ });
73
+ if (deployment !== manifest.deployment) {
74
+ throw new TypeError('Cloudflare Worker deployment identity differs from its material.');
75
+ }
45
76
  return Object.freeze({
46
77
  origin,
47
78
  revision,
79
+ deployment,
48
80
  release,
49
- gateway,
50
81
  runtime: Object.freeze({
51
82
  compatibilityDate: manifest.runtime.compatibilityDate,
52
83
  compatibilityFlags: Object.freeze([...manifest.runtime.compatibilityFlags]),
@@ -96,8 +127,8 @@ function admitManifest(input) {
96
127
  'version',
97
128
  'origin',
98
129
  'revision',
130
+ 'deployment',
99
131
  'release',
100
- 'gateway',
101
132
  'runtime',
102
133
  'bindings',
103
134
  'assets',
@@ -107,11 +138,11 @@ function admitManifest(input) {
107
138
  }
108
139
  if (typeof value.origin !== 'string' ||
109
140
  value.origin.length === 0 ||
110
- !REVISION.test(String(value.revision))) {
141
+ !REVISION.test(String(value.revision)) ||
142
+ !REVISION.test(String(value.deployment))) {
111
143
  invalid();
112
144
  }
113
145
  const release = admitExecutable(value.release);
114
- const gateway = admitExecutable(value.gateway);
115
146
  const runtime = record(value.runtime, ['compatibilityDate', 'compatibilityFlags']);
116
147
  if (typeof runtime.compatibilityDate !== 'string' || !DATE.test(runtime.compatibilityDate))
117
148
  invalid();
@@ -136,8 +167,8 @@ function admitManifest(input) {
136
167
  version: WORKER_ARTIFACT_VERSION,
137
168
  origin: value.origin,
138
169
  revision: value.revision,
170
+ deployment: value.deployment,
139
171
  release,
140
- gateway,
141
172
  runtime: Object.freeze({
142
173
  compatibilityDate: runtime.compatibilityDate,
143
174
  compatibilityFlags,
@@ -1,14 +1,15 @@
1
+ import type { WorkerDeploymentId } from '../../release/deployment.js';
1
2
  import type { WorkerModuleKind } from './artifact.js';
2
3
  import { WORKER_MANIFEST_PATH } from './artifact.paths.js';
3
4
  export declare const WORKER_ARTIFACT_FORMAT = "astrale.cloudflare.worker";
4
- export declare const WORKER_ARTIFACT_VERSION = 1;
5
- export interface WorkerArtifactManifestV1 {
5
+ export declare const WORKER_ARTIFACT_VERSION = 2;
6
+ export interface WorkerArtifactManifestV2 {
6
7
  readonly format: typeof WORKER_ARTIFACT_FORMAT;
7
8
  readonly version: typeof WORKER_ARTIFACT_VERSION;
8
9
  readonly origin: string;
9
10
  readonly revision: string;
11
+ readonly deployment: WorkerDeploymentId;
10
12
  readonly release: ManifestExecutable;
11
- readonly gateway: ManifestExecutable;
12
13
  readonly runtime: {
13
14
  readonly compatibilityDate: string;
14
15
  readonly compatibilityFlags: readonly string[];
@@ -41,7 +42,7 @@ interface ManifestExecutable {
41
42
  readonly digest: string;
42
43
  }[];
43
44
  }
44
- export declare function encodeWorkerArtifactManifest(input: Omit<WorkerArtifactManifestV1, 'format' | 'version'>): Uint8Array;
45
+ export declare function encodeWorkerArtifactManifest(input: Omit<WorkerArtifactManifestV2, 'format' | 'version'>): Uint8Array;
45
46
  export declare function workerContentDigest(input: Uint8Array): string;
46
47
  export declare function inferMediaType(path: string): string | undefined;
47
48
  export { WORKER_MANIFEST_PATH };
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { artifactPath, assetPath, comparePath, WORKER_MANIFEST_PATH } from './artifact.paths.js';
3
3
  export const WORKER_ARTIFACT_FORMAT = 'astrale.cloudflare.worker';
4
- export const WORKER_ARTIFACT_VERSION = 1;
4
+ export const WORKER_ARTIFACT_VERSION = 2;
5
5
  const encoder = new TextEncoder();
6
6
  export function encodeWorkerArtifactManifest(input) {
7
7
  const manifest = {
@@ -9,8 +9,8 @@ export function encodeWorkerArtifactManifest(input) {
9
9
  version: WORKER_ARTIFACT_VERSION,
10
10
  origin: input.origin,
11
11
  revision: input.revision,
12
+ deployment: input.deployment,
12
13
  release: canonicalExecutable(input.release),
13
- gateway: canonicalExecutable(input.gateway),
14
14
  runtime: {
15
15
  compatibilityDate: input.runtime.compatibilityDate,
16
16
  compatibilityFlags: Object.freeze([...input.runtime.compatibilityFlags].sort()),
@@ -1,5 +1,6 @@
1
1
  export interface DeployArgs {
2
2
  configPath: string;
3
+ secrets?: Readonly<Record<string, string>>;
3
4
  route?: string;
4
5
  onLog?: (line: string) => void;
5
6
  signal?: AbortSignal;
@@ -1,5 +1,6 @@
1
1
  import { parseDeployUrl, parseDeployVersionId } from '../parse-output.js';
2
2
  import { runCapture, wranglerCommand } from './process.js';
3
+ import { secretRedactor, withSecretsFile } from './secrets.js';
3
4
  import { runWranglerTypes } from './type-generation.js';
4
5
  export class WranglerDeployError extends Error {
5
6
  applied;
@@ -13,7 +14,15 @@ export class WranglerDeployError extends Error {
13
14
  export async function runWranglerDeploy(args) {
14
15
  await runWranglerTypes(args);
15
16
  const { cmd, prefix } = wranglerCommand(args.projectDir);
16
- const { code, out } = await runCapture(cmd, [...prefix, 'deploy', '--config', args.configPath], args.projectDir, args.onLog, args.signal);
17
+ const secrets = args.secrets ?? {};
18
+ const execute = (secretsFile) => runCapture(cmd, [
19
+ ...prefix,
20
+ 'deploy',
21
+ '--config',
22
+ args.configPath,
23
+ ...(secretsFile === undefined ? [] : ['--secrets-file', secretsFile]),
24
+ ], args.projectDir, args.onLog, args.signal, secretRedactor(secrets));
25
+ const { code, out } = await withSecretsFile(secrets, execute);
17
26
  const url = parseDeployUrl(out, args.route);
18
27
  const deploymentVersion = parseDeployVersionId(out);
19
28
  if (code !== 0) {
@@ -1,8 +1,6 @@
1
1
  export { runWranglerBundle } from './wrangler/bundle.js';
2
2
  export { runWranglerDeploy, WranglerDeployError, type DeployArgs } from './wrangler/deploy.js';
3
3
  export { runWranglerDev, type DevHandle } from './wrangler/development.js';
4
- export { ensureWranglerDispatchNamespace, WranglerDispatchNamespaceError, } from './wrangler/namespace.js';
5
4
  export { wranglerProcessEnv } from './wrangler/process.js';
6
- export { runWranglerReleaseDeploy } from './wrangler/release.js';
7
5
  export { admitWranglerDeploymentStatus, runWranglerDeploymentStatus, type WranglerDeploymentStatus, } from './wrangler/status.js';
8
6
  export { runWranglerTypes } from './wrangler/type-generation.js';
@@ -1,8 +1,6 @@
1
1
  export { runWranglerBundle } from './wrangler/bundle.js';
2
2
  export { runWranglerDeploy, WranglerDeployError } from './wrangler/deploy.js';
3
3
  export { runWranglerDev } from './wrangler/development.js';
4
- export { ensureWranglerDispatchNamespace, WranglerDispatchNamespaceError, } from './wrangler/namespace.js';
5
4
  export { wranglerProcessEnv } from './wrangler/process.js';
6
- export { runWranglerReleaseDeploy } from './wrangler/release.js';
7
5
  export { admitWranglerDeploymentStatus, runWranglerDeploymentStatus, } from './wrangler/status.js';
8
6
  export { runWranglerTypes } from './wrangler/type-generation.js';