alchemy 0.63.1 → 0.64.0

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 (157) hide show
  1. package/bin/alchemy.js +96 -86
  2. package/lib/alchemy.d.ts +4 -0
  3. package/lib/alchemy.d.ts.map +1 -1
  4. package/lib/alchemy.js +10 -4
  5. package/lib/alchemy.js.map +1 -1
  6. package/lib/apply.d.ts +3 -0
  7. package/lib/apply.d.ts.map +1 -1
  8. package/lib/apply.js +11 -1
  9. package/lib/apply.js.map +1 -1
  10. package/lib/cloudflare/bindings.d.ts +3 -1
  11. package/lib/cloudflare/bindings.d.ts.map +1 -1
  12. package/lib/cloudflare/bucket.d.ts +2 -1
  13. package/lib/cloudflare/bucket.d.ts.map +1 -1
  14. package/lib/cloudflare/bucket.js.map +1 -1
  15. package/lib/cloudflare/bundle/cloudflare-internal.d.ts +6 -0
  16. package/lib/cloudflare/bundle/cloudflare-internal.d.ts.map +1 -0
  17. package/lib/cloudflare/bundle/cloudflare-internal.js +39 -0
  18. package/lib/cloudflare/bundle/cloudflare-internal.js.map +1 -0
  19. package/lib/cloudflare/bundle/nodejs-builtin-modules.d.ts +2 -0
  20. package/lib/cloudflare/bundle/nodejs-builtin-modules.d.ts.map +1 -0
  21. package/lib/cloudflare/bundle/nodejs-builtin-modules.js +9 -0
  22. package/lib/cloudflare/bundle/nodejs-builtin-modules.js.map +1 -0
  23. package/lib/cloudflare/bundle/plugin-als-external.d.ts +6 -0
  24. package/lib/cloudflare/bundle/plugin-als-external.d.ts.map +1 -0
  25. package/lib/cloudflare/bundle/plugin-als-external.js +12 -0
  26. package/lib/cloudflare/bundle/plugin-als-external.js.map +1 -0
  27. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.d.ts +4 -1
  28. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.d.ts.map +1 -1
  29. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js +23 -23
  30. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js.map +1 -1
  31. package/lib/cloudflare/bundle/plugin-node-compat.d.ts +11 -0
  32. package/lib/cloudflare/bundle/plugin-node-compat.d.ts.map +1 -0
  33. package/lib/cloudflare/bundle/plugin-node-compat.js +93 -0
  34. package/lib/cloudflare/bundle/plugin-node-compat.js.map +1 -0
  35. package/lib/cloudflare/d1-local-migrations.js.map +1 -1
  36. package/lib/cloudflare/durable-object-namespace.d.ts +1 -0
  37. package/lib/cloudflare/durable-object-namespace.d.ts.map +1 -1
  38. package/lib/cloudflare/durable-object-namespace.js.map +1 -1
  39. package/lib/cloudflare/website.d.ts.map +1 -1
  40. package/lib/cloudflare/website.js +80 -82
  41. package/lib/cloudflare/website.js.map +1 -1
  42. package/lib/cloudflare/worker-bundle.d.ts +6 -0
  43. package/lib/cloudflare/worker-bundle.d.ts.map +1 -1
  44. package/lib/cloudflare/worker-bundle.js +34 -10
  45. package/lib/cloudflare/worker-bundle.js.map +1 -1
  46. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  47. package/lib/cloudflare/worker-metadata.js +1 -0
  48. package/lib/cloudflare/worker-metadata.js.map +1 -1
  49. package/lib/cloudflare/worker.d.ts.map +1 -1
  50. package/lib/cloudflare/worker.js +24 -6
  51. package/lib/cloudflare/worker.js.map +1 -1
  52. package/lib/cloudflare/wrangler.json.d.ts +2 -4
  53. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  54. package/lib/cloudflare/wrangler.json.js +16 -14
  55. package/lib/cloudflare/wrangler.json.js.map +1 -1
  56. package/lib/context.d.ts +3 -1
  57. package/lib/context.d.ts.map +1 -1
  58. package/lib/context.js +2 -2
  59. package/lib/context.js.map +1 -1
  60. package/lib/destroy.d.ts +8 -0
  61. package/lib/destroy.d.ts.map +1 -1
  62. package/lib/destroy.js +20 -4
  63. package/lib/destroy.js.map +1 -1
  64. package/lib/planetscale/api/client.gen.d.ts +1750 -0
  65. package/lib/planetscale/api/client.gen.d.ts.map +1 -0
  66. package/lib/planetscale/api/client.gen.js +2401 -0
  67. package/lib/planetscale/api/client.gen.js.map +1 -0
  68. package/lib/planetscale/api/index.d.ts +3 -0
  69. package/lib/planetscale/api/index.d.ts.map +1 -0
  70. package/lib/planetscale/api/index.js +4 -0
  71. package/lib/planetscale/api/index.js.map +1 -0
  72. package/lib/planetscale/api/types.gen.d.ts +12156 -0
  73. package/lib/planetscale/api/types.gen.d.ts.map +1 -0
  74. package/lib/planetscale/api/types.gen.js +2 -0
  75. package/lib/planetscale/api/types.gen.js.map +1 -0
  76. package/lib/planetscale/branch.d.ts +5 -8
  77. package/lib/planetscale/branch.d.ts.map +1 -1
  78. package/lib/planetscale/branch.js +111 -97
  79. package/lib/planetscale/branch.js.map +1 -1
  80. package/lib/planetscale/database.d.ts +2 -6
  81. package/lib/planetscale/database.d.ts.map +1 -1
  82. package/lib/planetscale/database.js +157 -118
  83. package/lib/planetscale/database.js.map +1 -1
  84. package/lib/planetscale/index.d.ts +1 -1
  85. package/lib/planetscale/index.d.ts.map +1 -1
  86. package/lib/planetscale/index.js +1 -1
  87. package/lib/planetscale/index.js.map +1 -1
  88. package/lib/planetscale/password.d.ts +4 -7
  89. package/lib/planetscale/password.d.ts.map +1 -1
  90. package/lib/planetscale/password.js +71 -56
  91. package/lib/planetscale/password.js.map +1 -1
  92. package/lib/planetscale/utils.d.ts +8 -6
  93. package/lib/planetscale/utils.d.ts.map +1 -1
  94. package/lib/planetscale/utils.js +85 -70
  95. package/lib/planetscale/utils.js.map +1 -1
  96. package/lib/scope.d.ts +5 -1
  97. package/lib/scope.d.ts.map +1 -1
  98. package/lib/scope.js +11 -3
  99. package/lib/scope.js.map +1 -1
  100. package/lib/util/dedent.d.ts +3 -14
  101. package/lib/util/dedent.d.ts.map +1 -1
  102. package/lib/util/dedent.js +28 -52
  103. package/lib/util/dedent.js.map +1 -1
  104. package/package.json +4 -3
  105. package/src/alchemy.ts +14 -6
  106. package/src/apply.ts +13 -1
  107. package/src/cloudflare/bindings.ts +3 -1
  108. package/src/cloudflare/bucket.ts +3 -1
  109. package/src/cloudflare/bundle/cloudflare-internal.ts +42 -0
  110. package/src/cloudflare/bundle/nodejs-builtin-modules.ts +14 -0
  111. package/src/cloudflare/bundle/plugin-als-external.ts +13 -0
  112. package/src/cloudflare/bundle/plugin-hybrid-node-compat.ts +29 -28
  113. package/src/cloudflare/bundle/plugin-node-compat.ts +114 -0
  114. package/src/cloudflare/d1-local-migrations.ts +2 -2
  115. package/src/cloudflare/durable-object-namespace.ts +1 -0
  116. package/src/cloudflare/website.ts +88 -89
  117. package/src/cloudflare/worker-bundle.ts +46 -9
  118. package/src/cloudflare/worker-metadata.ts +2 -0
  119. package/src/cloudflare/worker.ts +35 -7
  120. package/src/cloudflare/wrangler.json.ts +108 -110
  121. package/src/context.ts +5 -3
  122. package/src/destroy.ts +26 -8
  123. package/src/planetscale/api/client.gen.ts +2882 -0
  124. package/src/planetscale/api/index.ts +4 -0
  125. package/src/planetscale/api/types.gen.ts +13041 -0
  126. package/src/planetscale/branch.ts +152 -169
  127. package/src/planetscale/database.ts +195 -204
  128. package/src/planetscale/index.ts +1 -1
  129. package/src/planetscale/password.ts +86 -85
  130. package/src/planetscale/utils.ts +141 -122
  131. package/src/scope.ts +12 -3
  132. package/src/util/dedent.ts +33 -61
  133. package/templates/astro/alchemy.run.ts +1 -3
  134. package/templates/hono/alchemy.run.ts +0 -1
  135. package/templates/nuxt/alchemy.run.ts +1 -3
  136. package/templates/react-router/alchemy.run.ts +1 -3
  137. package/templates/rwsdk/alchemy.run.ts +0 -2
  138. package/templates/sveltekit/alchemy.run.ts +1 -3
  139. package/templates/tanstack-start/alchemy.run.ts +1 -3
  140. package/templates/typescript/alchemy.run.ts +0 -1
  141. package/templates/vite/alchemy.run.ts +0 -1
  142. package/workers/cloudflare-state-store.js +58 -58
  143. package/lib/cloudflare/bundle/externals.d.ts +0 -3
  144. package/lib/cloudflare/bundle/externals.d.ts.map +0 -1
  145. package/lib/cloudflare/bundle/externals.js +0 -35
  146. package/lib/cloudflare/bundle/externals.js.map +0 -1
  147. package/lib/cloudflare/bundle/plugin-compat-warning.d.ts +0 -10
  148. package/lib/cloudflare/bundle/plugin-compat-warning.d.ts.map +0 -1
  149. package/lib/cloudflare/bundle/plugin-compat-warning.js +0 -67
  150. package/lib/cloudflare/bundle/plugin-compat-warning.js.map +0 -1
  151. package/lib/planetscale/api.d.ts +0 -53
  152. package/lib/planetscale/api.d.ts.map +0 -1
  153. package/lib/planetscale/api.js +0 -84
  154. package/lib/planetscale/api.js.map +0 -1
  155. package/src/cloudflare/bundle/externals.ts +0 -36
  156. package/src/cloudflare/bundle/plugin-compat-warning.ts +0 -94
  157. package/src/planetscale/api.ts +0 -115
@@ -1,9 +1,9 @@
1
1
  import type { Context } from "../context.ts";
2
2
  import { Resource } from "../resource.ts";
3
- import type { Secret } from "../secret.ts";
4
- import { PlanetScaleApi } from "./api.ts";
3
+ import type { PlanetScaleProps } from "./api/client.gen.ts";
4
+ import { PlanetScaleClient } from "./api/client.gen.ts";
5
5
  import {
6
- fixClusterSize,
6
+ ensureProductionBranchClusterSize,
7
7
  waitForDatabaseReady,
8
8
  type PlanetScaleClusterSize,
9
9
  } from "./utils.ts";
@@ -11,7 +11,7 @@ import {
11
11
  /**
12
12
  * Properties for creating or updating a PlanetScale Branch
13
13
  */
14
- export interface BranchProps {
14
+ export interface BranchProps extends PlanetScaleProps {
15
15
  /**
16
16
  * The name of the branch
17
17
  *
@@ -29,11 +29,6 @@ export interface BranchProps {
29
29
  */
30
30
  databaseName: string;
31
31
 
32
- /**
33
- * PlanetScale API token (overrides environment variable)
34
- */
35
- apiKey?: Secret;
36
-
37
32
  /**
38
33
  * Whether or not the branch should be set to a production branch or not.
39
34
  */
@@ -49,6 +44,7 @@ export interface BranchProps {
49
44
 
50
45
  /**
51
46
  * The parent branch name or Branch object
47
+ * @default "main"
52
48
  */
53
49
  parentBranch?: string | Branch;
54
50
 
@@ -64,11 +60,11 @@ export interface BranchProps {
64
60
  * If provided, restores the last successful backup's schema and data to the new branch.
65
61
  * Must have restore_production_branch_backup(s) or restore_backup(s) access,
66
62
  * in addition to Data Branching being enabled for the branch.
67
- * Use 'last_successful_backup' or empty string.
63
+ * Use 'last_successful_backup' or undefined.
68
64
  *
69
65
  * Ignored if the branch already exists.
70
66
  */
71
- seedData?: string;
67
+ seedData?: "last_successful_backup";
72
68
 
73
69
  /**
74
70
  * The database cluster size is required if a backup_id is provided. If the branch is not a production branch, the cluster size MUST be "PS_DEV".
@@ -158,13 +154,8 @@ export const Branch = Resource(
158
154
  props: BranchProps,
159
155
  ): Promise<Branch> {
160
156
  const adopt = props.adopt ?? this.scope.adopt;
161
- const apiKey =
162
- props.apiKey?.unencrypted || process.env.PLANETSCALE_API_TOKEN;
163
- if (!apiKey) {
164
- throw new Error("PLANETSCALE_API_TOKEN environment variable is required");
165
- }
166
157
 
167
- const api = new PlanetScaleApi({ apiKey });
158
+ const api = new PlanetScaleClient(props);
168
159
 
169
160
  const branchName =
170
161
  props.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
@@ -175,189 +166,181 @@ export const Branch = Resource(
175
166
  }
176
167
 
177
168
  if (this.phase === "delete") {
178
- try {
179
- if (this.output?.name) {
180
- const response = await api.delete(
181
- `/organizations/${props.organizationId}/databases/${props.databaseName}/branches/${this.output.name}`,
182
- );
169
+ if (this.output?.name) {
170
+ const response = await api.organizations.databases.branches.delete({
171
+ path: {
172
+ organization: props.organizationId,
173
+ database: props.databaseName,
174
+ name: this.output.name,
175
+ },
176
+ result: "full",
177
+ });
183
178
 
184
- if (!response.ok && response.status !== 404) {
185
- throw new Error(
186
- `Failed to delete branch: ${response.statusText} ${await response.text()}`,
187
- );
188
- }
179
+ if (response.error && response.error.status !== 404) {
180
+ throw new Error(
181
+ `Failed to delete branch: ${response.error.message}`,
182
+ {
183
+ cause: response.error,
184
+ },
185
+ );
189
186
  }
190
- } catch (error) {
191
- console.error("Error deleting branch:", error);
192
- throw error;
193
187
  }
194
188
  return this.destroy();
195
189
  }
196
190
 
197
- try {
198
- const parentBranchName = !props.parentBranch
199
- ? "main"
200
- : typeof props.parentBranch === "string"
201
- ? props.parentBranch
202
- : props.parentBranch.name;
203
-
204
- if (typeof props.parentBranch !== "string" && props.parentBranch) {
205
- await waitForDatabaseReady(
206
- api,
207
- props.organizationId,
208
- props.databaseName,
209
- props.parentBranch.name,
210
- );
211
- }
212
-
213
- // Check if branch exists
214
- const getResponse = await api.get(
215
- `/organizations/${props.organizationId}/databases/${props.databaseName}/branches/${branchName}`,
191
+ const parentBranchName = !props.parentBranch
192
+ ? "main"
193
+ : typeof props.parentBranch === "string"
194
+ ? props.parentBranch
195
+ : props.parentBranch.name;
196
+
197
+ if (typeof props.parentBranch !== "string" && props.parentBranch) {
198
+ await waitForDatabaseReady(
199
+ api,
200
+ props.organizationId,
201
+ props.databaseName,
202
+ props.parentBranch.name,
216
203
  );
204
+ }
205
+
206
+ // Check if branch exists
207
+ const getResponse = await api.organizations.databases.branches.get({
208
+ path: {
209
+ organization: props.organizationId,
210
+ database: props.databaseName,
211
+ name: branchName,
212
+ },
213
+ result: "full",
214
+ });
215
+
216
+ if (getResponse.error && getResponse.error.status !== 404) {
217
+ // Error getting branch
218
+ throw new Error(`Failed to get branch: ${getResponse.error.message}`, {
219
+ cause: getResponse.error,
220
+ });
221
+ }
217
222
 
218
- if (!getResponse.ok && getResponse.status !== 404) {
219
- // Error getting branch
223
+ if (getResponse.data) {
224
+ // Branch exists
225
+ if (!adopt) {
220
226
  throw new Error(
221
- `Failed to get branch: ${getResponse.statusText} ${await getResponse.text()}`,
227
+ `Branch ${branchName} already exists and adopt is false`,
222
228
  );
223
229
  }
224
230
 
225
- if (getResponse.ok) {
226
- // Branch exists
227
- if (!adopt) {
228
- throw new Error(
229
- `Branch ${branchName} already exists and adopt is false`,
230
- );
231
- }
232
-
233
- const data = await getResponse.json<any>();
234
- const currentParentBranch = data.parent_branch || "main";
235
-
236
- // Check immutable properties
237
- if (props.parentBranch && parentBranchName !== currentParentBranch) {
238
- throw new Error(
239
- `Cannot change parent branch from ${currentParentBranch} to ${parentBranchName}`,
240
- );
241
- }
242
- if (this.output?.backupId) {
243
- console.warn(
244
- "BackupID is set, but branch already exists, so it will be ignored",
245
- );
246
- }
247
-
248
- if (this.output?.seedData) {
249
- console.warn(
250
- "SeedData is set, but branch already exists, so it will be ignored",
251
- );
252
- }
253
-
254
- // Update mutable properties if they've changed
255
- if (props.safeMigrations !== undefined) {
256
- const safeMigrationsResponse = await api[
257
- props.safeMigrations ? "post" : "delete"
258
- ](
259
- `/organizations/${props.organizationId}/databases/${props.databaseName}/branches/${branchName}/safe-migrations`,
260
- );
261
-
262
- if (!safeMigrationsResponse.ok) {
263
- throw new Error(
264
- `Failed to ${props.safeMigrations ? "enable" : "disable"} safe migrations: ${safeMigrationsResponse.statusText}`,
265
- );
266
- }
267
- }
268
-
269
- if (props.clusterSize && data.cluster_size !== props.clusterSize) {
270
- const clusterResponse = await api.patch(
271
- `/organizations/${props.organizationId}/databases/${props.databaseName}/branches/${branchName}/cluster`,
272
- {
273
- cluster_size: props.clusterSize,
274
- },
275
- );
276
-
277
- if (!clusterResponse.ok) {
278
- throw new Error(
279
- `Failed to update cluster size: ${clusterResponse.statusText}`,
280
- );
281
- }
282
- }
283
-
284
- return this({
285
- ...props,
286
- name: branchName,
287
- parentBranch: currentParentBranch,
288
- createdAt: data.created_at,
289
- updatedAt: data.updated_at,
290
- htmlUrl: data.html_url,
291
- });
292
- }
293
- await waitForDatabaseReady(api, props.organizationId, props.databaseName);
294
-
295
- // Branch doesn't exist, create it
296
- const createResponse = await api.post(
297
- `/organizations/${props.organizationId}/databases/${props.databaseName}/branches`,
298
- {
299
- name: branchName,
300
- parent_branch: parentBranchName,
301
- backup_id: props.backupId,
302
- seed_data: props.seedData,
303
- cluster_size: props.clusterSize,
304
- },
305
- );
231
+ const data = getResponse.data;
232
+ const currentParentBranch = data.parent_branch || "main";
306
233
 
307
- if (!createResponse.ok) {
234
+ // Check immutable properties
235
+ if (props.parentBranch && parentBranchName !== currentParentBranch) {
308
236
  throw new Error(
309
- `Failed to create branch: ${createResponse.statusText} ${await createResponse.text()}`,
237
+ `Cannot change parent branch from ${currentParentBranch} to ${parentBranchName}`,
238
+ );
239
+ }
240
+ if (this.output?.backupId) {
241
+ console.warn(
242
+ "BackupID is set, but branch already exists, so it will be ignored",
310
243
  );
311
244
  }
312
245
 
313
- const data = await createResponse.json<any>();
246
+ if (this.output?.seedData) {
247
+ console.warn(
248
+ "SeedData is set, but branch already exists, so it will be ignored",
249
+ );
250
+ }
314
251
 
315
- // Handle safe migrations if specified
252
+ // Update mutable properties if they've changed
316
253
  if (props.safeMigrations !== undefined) {
317
- // We can't change the migrations mode if the database is not ready
318
- await waitForDatabaseReady(
319
- api,
320
- props.organizationId,
321
- props.databaseName,
322
- branchName,
323
- );
324
- const safeMigrationsResponse = await api[
254
+ await api.organizations.databases.branches.safeMigrations[
325
255
  props.safeMigrations ? "post" : "delete"
326
- ](
327
- `/organizations/${props.organizationId}/databases/${props.databaseName}/branches/${branchName}/safe-migrations`,
328
- );
329
-
330
- if (!safeMigrationsResponse.ok) {
331
- throw new Error(
332
- `Failed to ${props.safeMigrations ? "enable" : "disable"} safe migrations: ${safeMigrationsResponse.statusText} : ${await safeMigrationsResponse.text()}`,
333
- );
334
- }
256
+ ]({
257
+ path: {
258
+ organization: props.organizationId,
259
+ database: props.databaseName,
260
+ name: branchName,
261
+ },
262
+ });
335
263
  }
336
264
 
337
- // Handle cluster size update if specified
338
- if (props.clusterSize) {
339
- // Wait for database to be ready before modifying cluster size
340
- await fixClusterSize(
341
- api,
342
- props.organizationId,
343
- props.databaseName,
344
- branchName,
345
- props.clusterSize,
346
- true,
347
- );
265
+ if (props.clusterSize && data.cluster_name !== props.clusterSize) {
266
+ await api.organizations.databases.branches.cluster.patch({
267
+ path: {
268
+ organization: props.organizationId,
269
+ database: props.databaseName,
270
+ name: branchName,
271
+ },
272
+ body: {
273
+ cluster_size: props.clusterSize,
274
+ },
275
+ });
348
276
  }
349
277
 
350
278
  return this({
351
279
  ...props,
352
280
  name: branchName,
353
- parentBranch: data.parent_branch,
281
+ parentBranch: currentParentBranch,
354
282
  createdAt: data.created_at,
355
283
  updatedAt: data.updated_at,
356
284
  htmlUrl: data.html_url,
357
285
  });
358
- } catch (error) {
359
- console.error("Error managing branch:", error);
360
- throw error;
361
286
  }
287
+ await waitForDatabaseReady(api, props.organizationId, props.databaseName);
288
+
289
+ // Branch doesn't exist, create it
290
+ const data = await api.organizations.databases.branches.post({
291
+ path: {
292
+ organization: props.organizationId,
293
+ database: props.databaseName,
294
+ },
295
+ body: {
296
+ name: branchName,
297
+ parent_branch: parentBranchName,
298
+ backup_id: props.backupId,
299
+ seed_data: props.seedData,
300
+ cluster_size: props.clusterSize,
301
+ },
302
+ });
303
+
304
+ // Handle safe migrations if specified
305
+ if (props.safeMigrations !== undefined) {
306
+ // We can't change the migrations mode if the database is not ready
307
+ await waitForDatabaseReady(
308
+ api,
309
+ props.organizationId,
310
+ props.databaseName,
311
+ branchName,
312
+ );
313
+ await api.organizations.databases.branches.safeMigrations[
314
+ props.safeMigrations ? "post" : "delete"
315
+ ]({
316
+ path: {
317
+ organization: props.organizationId,
318
+ database: props.databaseName,
319
+ name: branchName,
320
+ },
321
+ });
322
+ }
323
+
324
+ // Handle cluster size update if specified
325
+ if (props.clusterSize) {
326
+ // Wait for database to be ready before modifying cluster size
327
+ await ensureProductionBranchClusterSize(
328
+ api,
329
+ props.organizationId,
330
+ props.databaseName,
331
+ branchName,
332
+ props.clusterSize,
333
+ true,
334
+ );
335
+ }
336
+
337
+ return this({
338
+ ...props,
339
+ name: branchName,
340
+ parentBranch: data.parent_branch,
341
+ createdAt: data.created_at,
342
+ updatedAt: data.updated_at,
343
+ htmlUrl: data.html_url,
344
+ });
362
345
  },
363
346
  );