alchemy 0.12.6 → 0.12.8

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 (80) hide show
  1. package/lib/cloudflare/ai-gateway.d.ts.map +1 -1
  2. package/lib/cloudflare/ai-gateway.js +1 -2
  3. package/lib/cloudflare/ai-gateway.js.map +1 -1
  4. package/lib/cloudflare/bindings.d.ts +2 -1
  5. package/lib/cloudflare/bindings.d.ts.map +1 -1
  6. package/lib/cloudflare/bound.d.ts +2 -1
  7. package/lib/cloudflare/bound.d.ts.map +1 -1
  8. package/lib/cloudflare/bucket.d.ts +8 -2
  9. package/lib/cloudflare/bucket.d.ts.map +1 -1
  10. package/lib/cloudflare/bucket.js +1 -1
  11. package/lib/cloudflare/bucket.js.map +1 -1
  12. package/lib/cloudflare/d1-database.d.ts +8 -2
  13. package/lib/cloudflare/d1-database.d.ts.map +1 -1
  14. package/lib/cloudflare/d1-database.js +2 -2
  15. package/lib/cloudflare/d1-database.js.map +1 -1
  16. package/lib/cloudflare/event-source.d.ts +26 -0
  17. package/lib/cloudflare/event-source.d.ts.map +1 -0
  18. package/lib/cloudflare/event-source.js +9 -0
  19. package/lib/cloudflare/event-source.js.map +1 -0
  20. package/lib/cloudflare/hyperdrive.d.ts +216 -0
  21. package/lib/cloudflare/hyperdrive.d.ts.map +1 -0
  22. package/lib/cloudflare/hyperdrive.js +184 -0
  23. package/lib/cloudflare/hyperdrive.js.map +1 -0
  24. package/lib/cloudflare/index.d.ts +2 -0
  25. package/lib/cloudflare/index.d.ts.map +1 -1
  26. package/lib/cloudflare/index.js +2 -0
  27. package/lib/cloudflare/index.js.map +1 -1
  28. package/lib/cloudflare/queue-consumer.d.ts +162 -0
  29. package/lib/cloudflare/queue-consumer.d.ts.map +1 -0
  30. package/lib/cloudflare/queue-consumer.js +197 -0
  31. package/lib/cloudflare/queue-consumer.js.map +1 -0
  32. package/lib/cloudflare/queue.d.ts +15 -3
  33. package/lib/cloudflare/queue.d.ts.map +1 -1
  34. package/lib/cloudflare/queue.js +8 -2
  35. package/lib/cloudflare/queue.js.map +1 -1
  36. package/lib/cloudflare/website.d.ts.map +1 -1
  37. package/lib/cloudflare/website.js +8 -10
  38. package/lib/cloudflare/website.js.map +1 -1
  39. package/lib/cloudflare/worker.d.ts +13 -2
  40. package/lib/cloudflare/worker.d.ts.map +1 -1
  41. package/lib/cloudflare/worker.js +75 -3
  42. package/lib/cloudflare/worker.js.map +1 -1
  43. package/lib/cloudflare/wrangler.json.d.ts +13 -3
  44. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  45. package/lib/cloudflare/wrangler.json.js +27 -5
  46. package/lib/cloudflare/wrangler.json.js.map +1 -1
  47. package/lib/neon/api-error.d.ts +31 -0
  48. package/lib/neon/api-error.d.ts.map +1 -0
  49. package/lib/neon/api-error.js +73 -0
  50. package/lib/neon/api-error.js.map +1 -0
  51. package/lib/neon/api.d.ts +70 -0
  52. package/lib/neon/api.d.ts.map +1 -0
  53. package/lib/neon/api.js +128 -0
  54. package/lib/neon/api.js.map +1 -0
  55. package/lib/neon/index.d.ts +4 -0
  56. package/lib/neon/index.d.ts.map +1 -0
  57. package/lib/neon/index.js +4 -0
  58. package/lib/neon/index.js.map +1 -0
  59. package/lib/neon/project.d.ts +345 -0
  60. package/lib/neon/project.d.ts.map +1 -0
  61. package/lib/neon/project.js +305 -0
  62. package/lib/neon/project.js.map +1 -0
  63. package/package.json +2 -1
  64. package/src/cloudflare/ai-gateway.ts +0 -1
  65. package/src/cloudflare/bindings.ts +4 -2
  66. package/src/cloudflare/bound.ts +20 -17
  67. package/src/cloudflare/bucket.ts +9 -2
  68. package/src/cloudflare/d1-database.ts +10 -3
  69. package/src/cloudflare/event-source.ts +33 -0
  70. package/src/cloudflare/hyperdrive.ts +375 -0
  71. package/src/cloudflare/index.ts +2 -0
  72. package/src/cloudflare/queue-consumer.ts +433 -0
  73. package/src/cloudflare/queue.ts +83 -63
  74. package/src/cloudflare/website.ts +9 -13
  75. package/src/cloudflare/worker.ts +109 -5
  76. package/src/cloudflare/wrangler.json.ts +52 -8
  77. package/src/neon/api-error.ts +81 -0
  78. package/src/neon/api.ts +178 -0
  79. package/src/neon/index.ts +3 -0
  80. package/src/neon/project.ts +870 -0
@@ -0,0 +1,375 @@
1
+ import type { Context } from "../context.js";
2
+ import { Resource } from "../resource.js";
3
+ import type { Secret } from "../secret.js";
4
+ import { handleApiError } from "./api-error.js";
5
+ import { createCloudflareApi, type CloudflareApiOptions } from "./api.js";
6
+
7
+ /**
8
+ * Origin configuration for a PostgreSQL database connection
9
+ */
10
+ export interface HyperdriveOrigin {
11
+ /**
12
+ * Database name
13
+ */
14
+ database: string;
15
+
16
+ /**
17
+ * Database host
18
+ */
19
+ host: string;
20
+
21
+ /**
22
+ * Database password
23
+ * Use alchemy.secret() to securely store this value
24
+ */
25
+ password: Secret;
26
+
27
+ /**
28
+ * Database port
29
+ * @default 5432
30
+ */
31
+ port?: number;
32
+
33
+ /**
34
+ * Connection scheme
35
+ * @default "postgres"
36
+ */
37
+ scheme?: "postgres";
38
+
39
+ /**
40
+ * Database user
41
+ */
42
+ user: string;
43
+ }
44
+
45
+ /**
46
+ * Origin configuration for a database connection with access tokens
47
+ */
48
+ export interface HyperdriveOriginWithAccess {
49
+ /**
50
+ * Access client ID
51
+ */
52
+ access_client_id: string;
53
+
54
+ /**
55
+ * Access client secret
56
+ * Use alchemy.secret() to securely store this value
57
+ */
58
+ access_client_secret: Secret;
59
+
60
+ /**
61
+ * Database host
62
+ */
63
+ host: string;
64
+
65
+ /**
66
+ * Database name
67
+ */
68
+ database: string;
69
+
70
+ /**
71
+ * Database port
72
+ * @default 5432
73
+ */
74
+ port?: number;
75
+
76
+ /**
77
+ * Connection scheme
78
+ * @default "postgres"
79
+ */
80
+ scheme?: "postgres";
81
+
82
+ /**
83
+ * Database user
84
+ */
85
+ user: string;
86
+ }
87
+
88
+ /**
89
+ * Caching configuration for Hyperdrive
90
+ */
91
+ export interface HyperdriveCaching {
92
+ /**
93
+ * Whether caching is disabled
94
+ * @default false
95
+ */
96
+ disabled?: boolean;
97
+ }
98
+
99
+ /**
100
+ * mTLS configuration for Hyperdrive
101
+ */
102
+ export interface HyperdriveMtls {
103
+ /**
104
+ * CA certificate ID
105
+ */
106
+ ca_certificate_id?: string;
107
+
108
+ /**
109
+ * mTLS certificate ID
110
+ */
111
+ mtls_certificate_id?: string;
112
+
113
+ /**
114
+ * SSL mode
115
+ * @default "verify-full"
116
+ */
117
+ sslmode?: "verify-ca" | "verify-full";
118
+ }
119
+
120
+ /**
121
+ * Properties for creating or updating a Cloudflare Hyperdrive.
122
+ */
123
+ export interface HyperdriveProps extends CloudflareApiOptions {
124
+ /**
125
+ * Name of the Hyperdrive configuration
126
+ */
127
+ name: string;
128
+
129
+ /**
130
+ * Database connection origin configuration
131
+ */
132
+ origin: HyperdriveOrigin | HyperdriveOriginWithAccess;
133
+
134
+ /**
135
+ * Caching configuration
136
+ */
137
+ caching?: HyperdriveCaching;
138
+
139
+ /**
140
+ * mTLS configuration
141
+ */
142
+ mtls?: HyperdriveMtls;
143
+
144
+ /**
145
+ * UUID of the hyperdrive (only used for update/delete operations)
146
+ * This is provided by Cloudflare and is different from the resource ID
147
+ * @internal
148
+ */
149
+ hyperdriveId?: string;
150
+ }
151
+
152
+ /**
153
+ * Output returned after Cloudflare Hyperdrive creation/update.
154
+ * IMPORTANT: The interface name MUST match the exported resource name.
155
+ */
156
+ export interface Hyperdrive
157
+ extends Resource<"cloudflare::Hyperdrive">,
158
+ Omit<HyperdriveProps, "origin"> {
159
+ /**
160
+ * The ID of the resource
161
+ */
162
+ id: string;
163
+
164
+ /**
165
+ * The Cloudflare-generated UUID of the hyperdrive
166
+ */
167
+ hyperdriveId: string;
168
+
169
+ /**
170
+ * Database connection origin configuration
171
+ */
172
+ origin: HyperdriveOrigin | HyperdriveOriginWithAccess;
173
+
174
+ /**
175
+ * Resource type identifier for binding.
176
+ * @internal
177
+ */
178
+ type: "hyperdrive";
179
+ }
180
+
181
+ /**
182
+ * Represents a Cloudflare Hyperdrive configuration.
183
+ *
184
+ * @example
185
+ * // Create a basic Hyperdrive connection to a PostgreSQL database
186
+ * const basicHyperdrive = await Hyperdrive("my-postgres-db", {
187
+ * name: "my-postgres-db",
188
+ * origin: {
189
+ * database: "postgres",
190
+ * host: "database.example.com",
191
+ * password: alchemy.secret("your-password"),
192
+ * port: 5432,
193
+ * user: "postgres"
194
+ * }
195
+ * });
196
+ *
197
+ * @example
198
+ * // Create a Hyperdrive with caching disabled
199
+ * const noCacheHyperdrive = await Hyperdrive("no-cache-db", {
200
+ * name: "no-cache-db",
201
+ * origin: {
202
+ * database: "postgres",
203
+ * host: "database.example.com",
204
+ * password: alchemy.secret(process.env.DB_PASSWORD),
205
+ * port: 5432,
206
+ * user: "postgres"
207
+ * },
208
+ * caching: {
209
+ * disabled: true
210
+ * }
211
+ * });
212
+ *
213
+ * @example
214
+ * // Create a Hyperdrive with mTLS configuration
215
+ * const mtlsHyperdrive = await Hyperdrive("secure-db", {
216
+ * name: "secure-db",
217
+ * origin: {
218
+ * database: "postgres",
219
+ * host: "database.example.com",
220
+ * password: alchemy.secret(process.env.DB_PASSWORD),
221
+ * port: 5432,
222
+ * user: "postgres"
223
+ * },
224
+ * mtls: {
225
+ * ca_certificate_id: "00000000-0000-0000-0000-0000000000",
226
+ * mtls_certificate_id: "00000000-0000-0000-0000-0000000000",
227
+ * sslmode: "verify-full"
228
+ * }
229
+ * });
230
+ *
231
+ * @example
232
+ * // Create a Hyperdrive with access client credentials
233
+ * const accessHyperdrive = await Hyperdrive("access-db", {
234
+ * name: "access-db",
235
+ * origin: {
236
+ * database: "postgres",
237
+ * host: "database.example.com",
238
+ * access_client_id: "client-id",
239
+ * access_client_secret: alchemy.secret(process.env.ACCESS_CLIENT_SECRET),
240
+ * port: 5432,
241
+ * user: "postgres"
242
+ * }
243
+ * });
244
+ */
245
+ export const Hyperdrive = Resource(
246
+ "cloudflare::Hyperdrive",
247
+ async function (
248
+ this: Context<Hyperdrive>,
249
+ id: string,
250
+ props: HyperdriveProps
251
+ ): Promise<Hyperdrive> {
252
+ const api = await createCloudflareApi(props);
253
+ const configsPath = `/accounts/${api.accountId}/hyperdrive/configs`;
254
+
255
+ // For create operations, we don't have a hyperdriveId yet
256
+ // For update/delete operations, we need to use the hyperdriveId from props or output
257
+ const hyperdriveId = props.hyperdriveId || this.output?.hyperdriveId;
258
+ const configPath = hyperdriveId
259
+ ? `${configsPath}/${hyperdriveId}`
260
+ : `${configsPath}`;
261
+
262
+ if (this.phase === "delete") {
263
+ if (!hyperdriveId) {
264
+ console.warn(`No hyperdriveId found for ${id}, skipping delete`);
265
+ return this.destroy();
266
+ }
267
+
268
+ try {
269
+ const deleteResponse = await api.delete(configPath);
270
+ // Only swallow 404 Not Found errors, all other errors should be handled
271
+ if (!deleteResponse.ok && deleteResponse.status !== 404) {
272
+ await handleApiError(deleteResponse, "delete", "hyperdrive", id);
273
+ }
274
+ } catch (error) {
275
+ console.error(`Error deleting Hyperdrive ${id}:`, error);
276
+ throw error;
277
+ }
278
+ return this.destroy();
279
+ }
280
+
281
+ let response: Response | undefined;
282
+ let apiResource: any;
283
+
284
+ // Prepare request body with unwrapped secrets
285
+ const requestBody = prepareRequestBody(props);
286
+
287
+ try {
288
+ if (this.phase === "update" && hyperdriveId) {
289
+ // Update existing hyperdrive
290
+ response = await api.put(configPath, requestBody);
291
+ } else {
292
+ // Create new hyperdrive
293
+ if (hyperdriveId) {
294
+ // If we have a hyperdriveId but we're in create phase, it could be because
295
+ // the resource exists but wasn't in state. Do a GET to check.
296
+ const getResponse = await api.get(configPath);
297
+ if (getResponse.status === 200) {
298
+ // Hyperdrive exists, update it
299
+ console.log(
300
+ `Hyperdrive '${id}' already exists. Updating existing resource.`
301
+ );
302
+ response = await api.put(configPath, requestBody);
303
+ } else if (getResponse.status === 404) {
304
+ // Hyperdrive doesn't exist, create new
305
+ response = await api.post(configsPath, {
306
+ ...requestBody,
307
+ // Ensure name is set correctly if not already set
308
+ name: props.name || id,
309
+ });
310
+ } else {
311
+ // Unexpected error during GET check
312
+ await handleApiError(getResponse, "get", "hyperdrive", id);
313
+ }
314
+ } else {
315
+ // No hyperdriveId, create new
316
+ response = await api.post(configsPath, {
317
+ ...requestBody,
318
+ // Ensure name is set correctly if not already set
319
+ name: props.name || id,
320
+ });
321
+ }
322
+ }
323
+
324
+ if (!response?.ok) {
325
+ const action = this.phase === "update" ? "update" : "create";
326
+ await handleApiError(response!, action, "hyperdrive", id);
327
+ }
328
+
329
+ const data: { result: Record<string, any> } = await response!.json();
330
+ apiResource = data.result;
331
+ } catch (error) {
332
+ console.error(`Error ${this.phase} Hyperdrive '${id}':`, error);
333
+ throw error;
334
+ }
335
+
336
+ // Construct the output object from API response and props
337
+ return this({
338
+ id,
339
+ hyperdriveId: apiResource.id, // Store the Cloudflare-assigned UUID
340
+ name: apiResource.name,
341
+ origin: props.origin, // Keep the original origin with secrets
342
+ caching: apiResource.caching,
343
+ mtls: apiResource.mtls,
344
+ type: "hyperdrive",
345
+ });
346
+ }
347
+ );
348
+
349
+ /**
350
+ * Prepare the request body by unwrapping secret values
351
+ */
352
+ function prepareRequestBody(props: HyperdriveProps): any {
353
+ const requestBody: any = { ...props };
354
+
355
+ // Remove internal props
356
+ delete requestBody.hyperdriveId;
357
+
358
+ // Deep clone and unwrap secrets in the origin object
359
+ if ("password" in props.origin) {
360
+ // Regular origin with password
361
+ requestBody.origin = {
362
+ ...props.origin,
363
+ password: props.origin.password.unencrypted,
364
+ scheme: props.origin.scheme ?? "postgres",
365
+ };
366
+ } else if ("access_client_secret" in props.origin) {
367
+ // Origin with access client secret
368
+ requestBody.origin = {
369
+ ...props.origin,
370
+ access_client_secret: props.origin.access_client_secret.unencrypted,
371
+ };
372
+ }
373
+
374
+ return requestBody;
375
+ }
@@ -9,11 +9,13 @@ export * from "./custom-domain.js";
9
9
  export * from "./d1-database.js";
10
10
  export * from "./dns-records.js";
11
11
  export * from "./durable-object-namespace.js";
12
+ export * from "./hyperdrive.js";
12
13
  export * from "./kv-namespace.js";
13
14
  export * from "./local-dev-cloudflare-shim.js";
14
15
  export * from "./nuxt.js";
15
16
  export * from "./permission-groups.js";
16
17
  export * from "./pipeline.js";
18
+ export * from "./queue-consumer.js";
17
19
  export * from "./queue.js";
18
20
  export * from "./r2-rest-state-store.js";
19
21
  export * from "./redwood.js";