alchemy 0.7.0 → 0.7.2

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.
@@ -1,243 +1,140 @@
1
1
  import type { Context } from "../context";
2
2
  import { Resource } from "../resource";
3
+ import type { Worker } from "./worker";
3
4
  /**
4
5
  * Properties for wrangler.json configuration file
5
6
  */
6
7
  export interface WranglerJsonProps {
8
+ name?: string;
7
9
  /**
8
- * The name of your worker
10
+ * The worker to generate the wrangler.json file for
9
11
  */
10
- name: string;
12
+ worker: Worker;
11
13
  /**
12
- * The directory containing your worker entry point
13
- * @default "src"
14
+ * Path to write the wrangler.json file to
15
+ *
16
+ * @default cwd/wrangler.json
14
17
  */
15
- main?: string;
18
+ path?: string;
19
+ }
20
+ /**
21
+ * Output returned after WranglerJson creation/update
22
+ */
23
+ export interface WranglerJson extends Resource<"cloudflare::WranglerJson">, WranglerJsonProps {
16
24
  /**
17
- * The entry point for your worker
18
- * @default "index.ts" or "index.js"
25
+ * Time at which the file was created
19
26
  */
20
- entrypoint?: string;
27
+ createdAt: number;
21
28
  /**
22
- * The directory to store build artifacts
23
- * @default "dist"
29
+ * Time at which the file was last updated
24
30
  */
25
- outdir?: string;
31
+ updatedAt: number;
26
32
  /**
27
- * The directory to serve static assets from
33
+ * Path to the wrangler.json file
28
34
  */
29
- assets?: string;
35
+ path: string;
36
+ }
37
+ /**
38
+ * Resource for managing wrangler.json configuration files
39
+ */
40
+ export declare const WranglerJson: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<WranglerJson>, id: string, props: WranglerJsonProps) => Promise<WranglerJson>);
41
+ /**
42
+ * Wrangler.json configuration specification based on Cloudflare's schema
43
+ */
44
+ export interface WranglerJsonSpec {
30
45
  /**
31
- * Minify the worker script
32
- * @default true
46
+ * The name of the worker
33
47
  */
34
- minify?: boolean;
48
+ name: string;
35
49
  /**
36
- * Node.js compatibility mode
37
- * @default false
50
+ * Main entry point for the worker
38
51
  */
39
- node_compat?: boolean;
52
+ main?: string;
40
53
  /**
41
- * First-party worker service bindings
54
+ * A date in the form yyyy-mm-dd used to determine Workers runtime version
42
55
  */
43
- services?: Array<{
44
- /**
45
- * Binding name
46
- */
47
- name: string;
48
- /**
49
- * Service environment
50
- */
51
- environment?: string;
52
- }>;
56
+ compatibility_date?: string;
53
57
  /**
54
- * Worker environment variables
58
+ * A list of flags that enable features from upcoming Workers runtime
55
59
  */
56
- vars?: Record<string, string>;
60
+ compatibility_flags?: string[];
57
61
  /**
58
- * KV Namespace bindings
62
+ * Whether to enable a workers.dev URL for this worker
59
63
  */
60
- kv_namespaces?: Array<{
61
- /**
62
- * Binding name
63
- */
64
- binding: string;
65
- /**
66
- * KV namespace ID
67
- */
68
- id: string;
69
- /**
70
- * Preview KV namespace ID
71
- */
72
- preview_id?: string;
73
- }>;
64
+ workers_dev?: boolean;
74
65
  /**
75
- * R2 bucket bindings
66
+ * Routes to attach to the worker
76
67
  */
77
- r2_buckets?: Array<{
78
- /**
79
- * Binding name
80
- */
81
- binding: string;
82
- /**
83
- * Bucket name
84
- */
85
- bucket_name: string;
86
- /**
87
- * Preview bucket name
88
- */
89
- preview_bucket_name?: string;
90
- }>;
91
- /**
92
- * D1 database bindings
93
- */
94
- d1_databases?: Array<{
95
- /**
96
- * Binding name
97
- */
68
+ routes?: string[];
69
+ /**
70
+ * KV Namespace bindings
71
+ */
72
+ kv_namespaces?: {
98
73
  binding: string;
99
- /**
100
- * Database name
101
- */
102
- database_name: string;
103
- /**
104
- * Database ID
105
- */
106
- database_id: string;
107
- /**
108
- * Preview database ID
109
- */
110
- preview_database_id?: string;
111
- }>;
74
+ id: string;
75
+ }[];
112
76
  /**
113
77
  * Durable Object bindings
114
78
  */
115
79
  durable_objects?: {
116
- /**
117
- * Durable Object bindings
118
- */
119
- bindings: Array<{
120
- /**
121
- * Binding name
122
- */
80
+ bindings: {
123
81
  name: string;
124
- /**
125
- * Class name
126
- */
127
82
  class_name: string;
128
- /**
129
- * Script name
130
- */
131
83
  script_name?: string;
132
- /**
133
- * Environment name
134
- */
135
84
  environment?: string;
136
- }>;
137
- };
138
- /**
139
- * Queue bindings
140
- */
141
- queues?: {
142
- /**
143
- * Producer bindings
144
- */
145
- producers?: Array<{
146
- /**
147
- * Binding name
148
- */
149
- binding: string;
150
- /**
151
- * Queue name
152
- */
153
- queue: string;
154
- }>;
155
- /**
156
- * Consumer configuration
157
- */
158
- consumers?: Array<{
159
- /**
160
- * Queue name
161
- */
162
- queue: string;
163
- /**
164
- * Maximum batch size
165
- */
166
- max_batch_size?: number;
167
- /**
168
- * Maximum batch timeout
169
- */
170
- max_batch_timeout?: number;
171
- /**
172
- * Maximum retries
173
- */
174
- max_retries?: number;
175
- /**
176
- * Dead letter queue
177
- */
178
- dead_letter_queue?: string;
179
- }>;
85
+ }[];
180
86
  };
181
87
  /**
182
- * Analytics Engine bindings
88
+ * R2 bucket bindings
183
89
  */
184
- analytics_engine_datasets?: Array<{
185
- /**
186
- * Binding name
187
- */
90
+ r2_buckets?: {
188
91
  binding: string;
189
- /**
190
- * Dataset name
191
- */
192
- dataset?: string;
193
- }>;
92
+ bucket_name: string;
93
+ }[];
194
94
  /**
195
- * Route configuration
95
+ * Queue bindings
196
96
  */
197
- routes?: Array<string>;
97
+ queues?: {
98
+ binding: string;
99
+ queue: string;
100
+ }[];
198
101
  /**
199
- * Triggers configuration
102
+ * Service bindings
200
103
  */
201
- triggers?: {
202
- /**
203
- * Cron triggers
204
- */
205
- crons: Array<string>;
206
- };
104
+ services?: {
105
+ binding: string;
106
+ service: string;
107
+ environment?: string;
108
+ }[];
207
109
  /**
208
- * Worker compatibility date
110
+ * Workflow bindings
209
111
  */
210
- compatibility_date?: string;
112
+ workflows?: {
113
+ name: string;
114
+ binding: string;
115
+ class_name: string;
116
+ }[];
211
117
  /**
212
- * Worker compatibility flags
118
+ * Plain text bindings (vars)
213
119
  */
214
- compatibility_flags?: Array<string>;
120
+ vars?: Record<string, string>;
215
121
  /**
216
- * Worker usage model
217
- * "bundled" - Includes resources like CPU and memory. Better for consistent workloads.
218
- * "unbound" - Pay only for what you use. Better for sporadic workloads.
122
+ * Assets bindings
219
123
  */
220
- usage_model?: "bundled" | "unbound";
124
+ assets?: {
125
+ directory: string;
126
+ binding: string;
127
+ };
221
128
  /**
222
- * Path to the wrangler.json file
223
- * @internal
129
+ * Workflow bindings
224
130
  */
225
- path?: string;
226
- }
227
- /**
228
- * Output returned after WranglerJson creation/update
229
- */
230
- export interface WranglerJson extends Resource<"cloudflare::WranglerJson">, WranglerJsonProps {
131
+ wasm_modules?: Record<string, string>;
231
132
  /**
232
- * Time at which the file was created
133
+ * Safe mode configuration
233
134
  */
234
- createdAt: number;
135
+ node_compat?: boolean;
235
136
  /**
236
- * Time at which the file was last updated
137
+ * Whether to minify the worker script
237
138
  */
238
- updatedAt: number;
139
+ minify?: boolean;
239
140
  }
240
- /**
241
- * Resource for managing wrangler.json configuration files
242
- */
243
- export declare const WranglerJson: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<WranglerJson>, id: string, props: WranglerJsonProps) => Promise<WranglerJson>);
@@ -1,4 +1,4 @@
1
- import * as fs from "fs/promises";
1
+ import { StaticJsonFile } from "../fs";
2
2
  import { Resource } from "../resource";
3
3
  /**
4
4
  * Resource for managing wrangler.json configuration files
@@ -7,29 +7,136 @@ export const WranglerJson = Resource("cloudflare::WranglerJson", async function
7
7
  // Default path is wrangler.json in current directory
8
8
  const filePath = props.path || "wrangler.json";
9
9
  if (this.phase === "delete") {
10
- try {
11
- await fs.unlink(filePath);
12
- }
13
- catch (error) {
14
- // Ignore errors if file doesn't exist
15
- if (error.code !== "ENOENT") {
16
- throw error;
17
- }
18
- }
19
10
  return this.destroy();
20
11
  }
21
- // Create or update the file
22
- const config = {
23
- ...props,
24
- // Remove internal path property
25
- path: undefined,
12
+ if (props.worker.entrypoint === undefined) {
13
+ throw new Error("Worker must have an entrypoint to generate a wrangler.json");
14
+ }
15
+ const worker = props.worker;
16
+ const spec = {
17
+ name: worker.name,
18
+ // Use entrypoint as main if it exists
19
+ main: worker.entrypoint,
20
+ // see: https://developers.cloudflare.com/workers/configuration/compatibility-dates/
21
+ compatibility_date: "2022-04-05",
26
22
  };
27
- // Write the file
28
- await fs.writeFile(filePath, JSON.stringify(config, null, 2));
23
+ // Process bindings if they exist
24
+ if (worker.bindings) {
25
+ processBindings(spec, worker.bindings);
26
+ }
27
+ // Add environment variables as vars
28
+ if (worker.env) {
29
+ spec.vars = { ...worker.env };
30
+ }
31
+ await StaticJsonFile("wrangler.json", spec);
29
32
  // Return the resource
30
33
  return this({
31
34
  ...props,
35
+ path: filePath,
32
36
  createdAt: Date.now(),
33
37
  updatedAt: Date.now(),
34
38
  });
35
39
  });
40
+ /**
41
+ * Process worker bindings into wrangler.json format
42
+ */
43
+ function processBindings(spec, bindings) {
44
+ // Arrays to collect different binding types
45
+ const kvNamespaces = [];
46
+ const durableObjects = [];
47
+ const r2Buckets = [];
48
+ const services = [];
49
+ const secrets = [];
50
+ const workflows = [];
51
+ const d1Databases = [];
52
+ const queues = [];
53
+ // Process each binding
54
+ for (const [bindingName, binding] of Object.entries(bindings)) {
55
+ if (typeof binding === "string") {
56
+ // Plain text binding - add to vars
57
+ if (!spec.vars) {
58
+ spec.vars = {};
59
+ }
60
+ spec.vars[bindingName] = binding;
61
+ }
62
+ else if (binding.type === "kv_namespace") {
63
+ // KV Namespace binding
64
+ kvNamespaces.push({
65
+ binding: bindingName,
66
+ id: binding.namespaceId,
67
+ });
68
+ }
69
+ else if (typeof binding === "object" &&
70
+ binding.type === "durable_object_namespace") {
71
+ // Durable Object binding
72
+ const doBinding = binding;
73
+ durableObjects.push({
74
+ name: bindingName,
75
+ class_name: doBinding.className,
76
+ script_name: doBinding.scriptName,
77
+ environment: doBinding.environment,
78
+ });
79
+ }
80
+ else if (binding.type === "r2_bucket") {
81
+ r2Buckets.push({
82
+ binding: bindingName,
83
+ bucket_name: binding.name,
84
+ });
85
+ }
86
+ else if (binding.type === "service") {
87
+ // Service binding
88
+ services.push({
89
+ binding: bindingName,
90
+ service: binding.id,
91
+ });
92
+ }
93
+ else if (binding.type === "secret") {
94
+ // Secret binding
95
+ secrets.push(bindingName);
96
+ }
97
+ else if (binding.type === "assets") {
98
+ spec.assets = {
99
+ directory: binding.path,
100
+ binding: bindingName,
101
+ };
102
+ }
103
+ else if (binding.type === "workflow") {
104
+ workflows.push({
105
+ name: bindingName,
106
+ binding: binding.id,
107
+ class_name: binding.className,
108
+ });
109
+ }
110
+ else if (binding.type === "d1") {
111
+ d1Databases.push({
112
+ binding: bindingName,
113
+ database_id: binding.id,
114
+ database_name: binding.name,
115
+ });
116
+ }
117
+ else if (binding.type === "queue") {
118
+ queues.push({
119
+ binding: bindingName,
120
+ queue: binding.name,
121
+ });
122
+ }
123
+ }
124
+ // Add collected bindings to the spec
125
+ if (kvNamespaces.length > 0) {
126
+ spec.kv_namespaces = kvNamespaces;
127
+ }
128
+ if (durableObjects.length > 0) {
129
+ spec.durable_objects = {
130
+ bindings: durableObjects,
131
+ };
132
+ }
133
+ if (r2Buckets.length > 0) {
134
+ spec.r2_buckets = r2Buckets;
135
+ }
136
+ if (services.length > 0) {
137
+ spec.services = services;
138
+ }
139
+ if (queues.length > 0) {
140
+ spec.queues = queues;
141
+ }
142
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemy",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "type": "module",
5
5
  "module": "./lib/index.js",
6
6
  "scripts": {
@@ -6,8 +6,11 @@
6
6
  import type { Secret } from "../secret";
7
7
  import type { Assets } from "./assets";
8
8
  import type { R2Bucket } from "./bucket";
9
+ import type { D1Database } from "./d1-database";
9
10
  import type { DurableObjectNamespace } from "./durable-object-namespace";
10
11
  import type { KVNamespace } from "./kv-namespace";
12
+ import type { Pipeline } from "./pipeline";
13
+ import type { Queue } from "./queue";
11
14
  import type { Worker } from "./worker";
12
15
  import type { Workflow } from "./workflow";
13
16
 
@@ -19,14 +22,17 @@ export type Bindings = {
19
22
  * L2 Binding Resources.
20
23
  */
21
24
  export type Binding =
25
+ | Assets
26
+ | D1Database
22
27
  | DurableObjectNamespace
23
28
  | KVNamespace
24
- | Worker
25
- | Workflow
29
+ | Pipeline
30
+ | Queue
26
31
  | R2Bucket
27
32
  | Secret
28
33
  | string
29
- | Assets;
34
+ | Worker
35
+ | Workflow;
30
36
 
31
37
  /**
32
38
  * Union type for all Worker binding types (API spec)
@@ -43,6 +49,7 @@ export type WorkerBindingSpec =
43
49
  | WorkerBindingJson
44
50
  | WorkerBindingKVNamespace
45
51
  | WorkerBindingMTLSCertificate
52
+ | WorkerBindingPipeline
46
53
  | WorkerBindingPlainText
47
54
  | WorkerBindingQueue
48
55
  | WorkerBindingR2Bucket
@@ -331,3 +338,15 @@ export interface WorkerBindingWorkflow {
331
338
  */
332
339
  script_name?: string;
333
340
  }
341
+
342
+ /**
343
+ * Pipeline binding type
344
+ */
345
+ export interface WorkerBindingPipeline {
346
+ /** The name of the binding */
347
+ name: string;
348
+ /** Type identifier for Pipeline binding */
349
+ type: "pipelines";
350
+ /** Pipeline name */
351
+ pipeline: string;
352
+ }
@@ -1,9 +1,13 @@
1
+ import type { Pipeline } from "cloudflare:pipelines";
1
2
  import type { Secret } from "../secret";
2
3
  import type { Assets } from "./assets";
3
4
  import type { Binding } from "./bindings";
4
5
  import type { R2Bucket as _R2Bucket } from "./bucket";
6
+ import type { D1Database as _D1Database } from "./d1-database";
5
7
  import type { DurableObjectNamespace as _DurableObjectNamespace } from "./durable-object-namespace";
6
8
  import type { KVNamespace as _KVNamespace } from "./kv-namespace";
9
+ import type { Pipeline as _Pipeline } from "./pipeline";
10
+ import type { Queue as _Queue } from "./queue";
7
11
  import type { Worker as _Worker } from "./worker";
8
12
  import type { Workflow as _Workflow } from "./workflow";
9
13
 
@@ -21,4 +25,10 @@ export type Bound<T extends Binding> = T extends _DurableObjectNamespace
21
25
  ? Service
22
26
  : T extends _Workflow<infer P>
23
27
  ? Workflow<P>
24
- : Service;
28
+ : T extends _D1Database
29
+ ? D1Database
30
+ : T extends _Queue
31
+ ? Queue
32
+ : T extends _Pipeline<infer R>
33
+ ? Pipeline<R>
34
+ : Service;
@@ -415,6 +415,7 @@ export async function emptyBucket(
415
415
 
416
416
  try {
417
417
  do {
418
+ console.log(`Listing objects in bucket ${bucketName}`);
418
419
  // List objects in the bucket
419
420
  const { objects, continuationToken: nextToken } = await listObjects(
420
421
  r2,