alchemy 0.63.1 → 0.65.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 (235) hide show
  1. package/bin/alchemy.js +7664 -5857
  2. package/bin/commands/init.ts +130 -9
  3. package/bin/constants.ts +4 -0
  4. package/bin/services/cdp-manager/cdp-proxy.ts +69 -0
  5. package/bin/services/cdp-manager/server.ts +173 -0
  6. package/bin/services/execute-alchemy.ts +83 -4
  7. package/bin/types.ts +1 -0
  8. package/lib/alchemy.d.ts +4 -0
  9. package/lib/alchemy.d.ts.map +1 -1
  10. package/lib/alchemy.js +10 -4
  11. package/lib/alchemy.js.map +1 -1
  12. package/lib/apply.d.ts +3 -0
  13. package/lib/apply.d.ts.map +1 -1
  14. package/lib/apply.js +11 -1
  15. package/lib/apply.js.map +1 -1
  16. package/lib/cloudflare/bindings.d.ts +3 -1
  17. package/lib/cloudflare/bindings.d.ts.map +1 -1
  18. package/lib/cloudflare/bucket.d.ts +2 -1
  19. package/lib/cloudflare/bucket.d.ts.map +1 -1
  20. package/lib/cloudflare/bucket.js.map +1 -1
  21. package/lib/cloudflare/bundle/cloudflare-internal.d.ts +6 -0
  22. package/lib/cloudflare/bundle/cloudflare-internal.d.ts.map +1 -0
  23. package/lib/cloudflare/bundle/cloudflare-internal.js +39 -0
  24. package/lib/cloudflare/bundle/cloudflare-internal.js.map +1 -0
  25. package/lib/cloudflare/bundle/nodejs-builtin-modules.d.ts +2 -0
  26. package/lib/cloudflare/bundle/nodejs-builtin-modules.d.ts.map +1 -0
  27. package/lib/cloudflare/bundle/nodejs-builtin-modules.js +9 -0
  28. package/lib/cloudflare/bundle/nodejs-builtin-modules.js.map +1 -0
  29. package/lib/cloudflare/bundle/plugin-als-external.d.ts +6 -0
  30. package/lib/cloudflare/bundle/plugin-als-external.d.ts.map +1 -0
  31. package/lib/cloudflare/bundle/plugin-als-external.js +12 -0
  32. package/lib/cloudflare/bundle/plugin-als-external.js.map +1 -0
  33. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.d.ts +4 -1
  34. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.d.ts.map +1 -1
  35. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js +23 -23
  36. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js.map +1 -1
  37. package/lib/cloudflare/bundle/plugin-node-compat.d.ts +11 -0
  38. package/lib/cloudflare/bundle/plugin-node-compat.d.ts.map +1 -0
  39. package/lib/cloudflare/bundle/plugin-node-compat.js +93 -0
  40. package/lib/cloudflare/bundle/plugin-node-compat.js.map +1 -0
  41. package/lib/cloudflare/bundle/plugin-wasm.d.ts.map +1 -1
  42. package/lib/cloudflare/bundle/plugin-wasm.js +20 -11
  43. package/lib/cloudflare/bundle/plugin-wasm.js.map +1 -1
  44. package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
  45. package/lib/cloudflare/compatibility-date.gen.js +1 -1
  46. package/lib/cloudflare/d1-local-migrations.js.map +1 -1
  47. package/lib/cloudflare/durable-object-namespace.d.ts +1 -0
  48. package/lib/cloudflare/durable-object-namespace.d.ts.map +1 -1
  49. package/lib/cloudflare/durable-object-namespace.js.map +1 -1
  50. package/lib/cloudflare/hyperdrive.d.ts +7 -2
  51. package/lib/cloudflare/hyperdrive.d.ts.map +1 -1
  52. package/lib/cloudflare/hyperdrive.js +39 -57
  53. package/lib/cloudflare/hyperdrive.js.map +1 -1
  54. package/lib/cloudflare/index.d.ts +1 -0
  55. package/lib/cloudflare/index.d.ts.map +1 -1
  56. package/lib/cloudflare/index.js +1 -0
  57. package/lib/cloudflare/index.js.map +1 -1
  58. package/lib/cloudflare/next.d.ts +13 -0
  59. package/lib/cloudflare/next.d.ts.map +1 -0
  60. package/lib/cloudflare/next.js +91 -0
  61. package/lib/cloudflare/next.js.map +1 -0
  62. package/lib/cloudflare/website.d.ts.map +1 -1
  63. package/lib/cloudflare/website.js +80 -82
  64. package/lib/cloudflare/website.js.map +1 -1
  65. package/lib/cloudflare/worker-assets.d.ts +3 -3
  66. package/lib/cloudflare/worker-assets.d.ts.map +1 -1
  67. package/lib/cloudflare/worker-assets.js +22 -47
  68. package/lib/cloudflare/worker-assets.js.map +1 -1
  69. package/lib/cloudflare/worker-bundle.d.ts +6 -0
  70. package/lib/cloudflare/worker-bundle.d.ts.map +1 -1
  71. package/lib/cloudflare/worker-bundle.js +34 -10
  72. package/lib/cloudflare/worker-bundle.js.map +1 -1
  73. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  74. package/lib/cloudflare/worker-metadata.js +1 -0
  75. package/lib/cloudflare/worker-metadata.js.map +1 -1
  76. package/lib/cloudflare/worker.d.ts.map +1 -1
  77. package/lib/cloudflare/worker.js +24 -6
  78. package/lib/cloudflare/worker.js.map +1 -1
  79. package/lib/cloudflare/wrangler.json.d.ts +4 -6
  80. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  81. package/lib/cloudflare/wrangler.json.js +20 -15
  82. package/lib/cloudflare/wrangler.json.js.map +1 -1
  83. package/lib/context.d.ts +3 -1
  84. package/lib/context.d.ts.map +1 -1
  85. package/lib/context.js +2 -2
  86. package/lib/context.js.map +1 -1
  87. package/lib/destroy.d.ts +8 -0
  88. package/lib/destroy.d.ts.map +1 -1
  89. package/lib/destroy.js +20 -4
  90. package/lib/destroy.js.map +1 -1
  91. package/lib/planetscale/api/client.gen.d.ts +1750 -0
  92. package/lib/planetscale/api/client.gen.d.ts.map +1 -0
  93. package/lib/planetscale/api/client.gen.js +2401 -0
  94. package/lib/planetscale/api/client.gen.js.map +1 -0
  95. package/lib/planetscale/api/index.d.ts +3 -0
  96. package/lib/planetscale/api/index.d.ts.map +1 -0
  97. package/lib/planetscale/api/index.js +4 -0
  98. package/lib/planetscale/api/index.js.map +1 -0
  99. package/lib/planetscale/api/types.gen.d.ts +12156 -0
  100. package/lib/planetscale/api/types.gen.d.ts.map +1 -0
  101. package/lib/planetscale/api/types.gen.js +2 -0
  102. package/lib/planetscale/api/types.gen.js.map +1 -0
  103. package/lib/planetscale/branch.d.ts +5 -8
  104. package/lib/planetscale/branch.d.ts.map +1 -1
  105. package/lib/planetscale/branch.js +122 -97
  106. package/lib/planetscale/branch.js.map +1 -1
  107. package/lib/planetscale/database.d.ts +24 -11
  108. package/lib/planetscale/database.d.ts.map +1 -1
  109. package/lib/planetscale/database.js +163 -118
  110. package/lib/planetscale/database.js.map +1 -1
  111. package/lib/planetscale/index.d.ts +2 -1
  112. package/lib/planetscale/index.d.ts.map +1 -1
  113. package/lib/planetscale/index.js +2 -1
  114. package/lib/planetscale/index.js.map +1 -1
  115. package/lib/planetscale/password.d.ts +7 -8
  116. package/lib/planetscale/password.d.ts.map +1 -1
  117. package/lib/planetscale/password.js +74 -57
  118. package/lib/planetscale/password.js.map +1 -1
  119. package/lib/planetscale/role.d.ts +126 -0
  120. package/lib/planetscale/role.d.ts.map +1 -0
  121. package/lib/planetscale/role.js +144 -0
  122. package/lib/planetscale/role.js.map +1 -0
  123. package/lib/planetscale/utils.d.ts +23 -7
  124. package/lib/planetscale/utils.d.ts.map +1 -1
  125. package/lib/planetscale/utils.js +169 -75
  126. package/lib/planetscale/utils.js.map +1 -1
  127. package/lib/scope.d.ts +5 -1
  128. package/lib/scope.d.ts.map +1 -1
  129. package/lib/scope.js +11 -3
  130. package/lib/scope.js.map +1 -1
  131. package/lib/secret.d.ts +0 -3
  132. package/lib/secret.d.ts.map +1 -1
  133. package/lib/secret.js +0 -2
  134. package/lib/secret.js.map +1 -1
  135. package/lib/state/cloudflare-state-store.js +3 -3
  136. package/lib/state/cloudflare-state-store.js.map +1 -1
  137. package/lib/test/bun.d.ts +2 -2
  138. package/lib/test/bun.d.ts.map +1 -1
  139. package/lib/test/vitest.d.ts +2 -2
  140. package/lib/test/vitest.d.ts.map +1 -1
  141. package/lib/test/vitest.js +4 -4
  142. package/lib/test/vitest.js.map +1 -1
  143. package/lib/util/content-type.js +2 -2
  144. package/lib/util/content-type.js.map +1 -1
  145. package/lib/util/dedent.d.ts +3 -14
  146. package/lib/util/dedent.d.ts.map +1 -1
  147. package/lib/util/dedent.js +33 -45
  148. package/lib/util/dedent.js.map +1 -1
  149. package/lib/util/memoize.d.ts.map +1 -1
  150. package/lib/util/memoize.js +11 -1
  151. package/lib/util/memoize.js.map +1 -1
  152. package/package.json +8 -3
  153. package/src/alchemy.ts +14 -6
  154. package/src/apply.ts +13 -1
  155. package/src/cloudflare/bindings.ts +3 -1
  156. package/src/cloudflare/bucket.ts +3 -1
  157. package/src/cloudflare/bundle/cloudflare-internal.ts +42 -0
  158. package/src/cloudflare/bundle/nodejs-builtin-modules.ts +14 -0
  159. package/src/cloudflare/bundle/plugin-als-external.ts +13 -0
  160. package/src/cloudflare/bundle/plugin-hybrid-node-compat.ts +29 -28
  161. package/src/cloudflare/bundle/plugin-node-compat.ts +114 -0
  162. package/src/cloudflare/bundle/plugin-wasm.ts +34 -14
  163. package/src/cloudflare/compatibility-date.gen.ts +1 -1
  164. package/src/cloudflare/d1-local-migrations.ts +2 -2
  165. package/src/cloudflare/durable-object-namespace.ts +1 -0
  166. package/src/cloudflare/hyperdrive.ts +136 -95
  167. package/src/cloudflare/index.ts +1 -0
  168. package/src/cloudflare/next.ts +123 -0
  169. package/src/cloudflare/website.ts +88 -89
  170. package/src/cloudflare/worker-assets.ts +43 -105
  171. package/src/cloudflare/worker-bundle.ts +46 -9
  172. package/src/cloudflare/worker-metadata.ts +2 -0
  173. package/src/cloudflare/worker.ts +35 -7
  174. package/src/cloudflare/wrangler.json.ts +114 -113
  175. package/src/context.ts +5 -3
  176. package/src/destroy.ts +26 -8
  177. package/src/planetscale/api/client.gen.ts +2882 -0
  178. package/src/planetscale/api/index.ts +4 -0
  179. package/src/planetscale/api/types.gen.ts +13041 -0
  180. package/src/planetscale/branch.ts +170 -162
  181. package/src/planetscale/database.ts +263 -243
  182. package/src/planetscale/index.ts +2 -1
  183. package/src/planetscale/password.ts +89 -86
  184. package/src/planetscale/role.ts +278 -0
  185. package/src/planetscale/utils.ts +289 -128
  186. package/src/scope.ts +12 -3
  187. package/src/secret.ts +0 -4
  188. package/src/state/cloudflare-state-store.ts +4 -4
  189. package/src/test/bun.ts +2 -2
  190. package/src/test/vitest.ts +6 -6
  191. package/src/util/content-type.ts +2 -2
  192. package/src/util/dedent.ts +34 -50
  193. package/src/util/memoize.ts +13 -1
  194. package/templates/astro/alchemy.run.ts +1 -3
  195. package/templates/hono/alchemy.run.ts +0 -1
  196. package/templates/nextjs/README.md +85 -0
  197. package/templates/nextjs/_env +1 -0
  198. package/templates/nextjs/_env.example +1 -0
  199. package/templates/nextjs/_gitignore +46 -0
  200. package/templates/nextjs/alchemy.run.ts +16 -0
  201. package/templates/nextjs/eslint.config.mjs +16 -0
  202. package/templates/nextjs/next-env.d.ts +5 -0
  203. package/templates/nextjs/next.config.ts +10 -0
  204. package/templates/nextjs/open-next.config.ts +5 -0
  205. package/templates/nextjs/package.json +31 -0
  206. package/templates/nextjs/src/app/api/hello/route.ts +19 -0
  207. package/templates/nextjs/src/app/favicon.ico +0 -0
  208. package/templates/nextjs/src/app/globals.css +72 -0
  209. package/templates/nextjs/src/app/layout.tsx +19 -0
  210. package/templates/nextjs/src/app/page.tsx +55 -0
  211. package/templates/nextjs/tsconfig.json +33 -0
  212. package/templates/nextjs/types/env.d.ts +14 -0
  213. package/templates/nuxt/alchemy.run.ts +1 -3
  214. package/templates/react-router/alchemy.run.ts +1 -3
  215. package/templates/rwsdk/alchemy.run.ts +0 -2
  216. package/templates/sveltekit/alchemy.run.ts +1 -3
  217. package/templates/tanstack-start/alchemy.run.ts +1 -3
  218. package/templates/typescript/alchemy.run.ts +0 -1
  219. package/templates/vite/alchemy.run.ts +0 -1
  220. package/workers/cloudflare-state-store.js +58 -58
  221. package/lib/cloudflare/bundle/externals.d.ts +0 -3
  222. package/lib/cloudflare/bundle/externals.d.ts.map +0 -1
  223. package/lib/cloudflare/bundle/externals.js +0 -35
  224. package/lib/cloudflare/bundle/externals.js.map +0 -1
  225. package/lib/cloudflare/bundle/plugin-compat-warning.d.ts +0 -10
  226. package/lib/cloudflare/bundle/plugin-compat-warning.d.ts.map +0 -1
  227. package/lib/cloudflare/bundle/plugin-compat-warning.js +0 -67
  228. package/lib/cloudflare/bundle/plugin-compat-warning.js.map +0 -1
  229. package/lib/planetscale/api.d.ts +0 -53
  230. package/lib/planetscale/api.d.ts.map +0 -1
  231. package/lib/planetscale/api.js +0 -84
  232. package/lib/planetscale/api.js.map +0 -1
  233. package/src/cloudflare/bundle/externals.ts +0 -36
  234. package/src/cloudflare/bundle/plugin-compat-warning.ts +0 -94
  235. package/src/planetscale/api.ts +0 -115
@@ -1 +1 @@
1
- {"version":3,"file":"password.js","sourceRoot":"","sources":["../../src/planetscale/password.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"password.js","sourceRoot":"","sources":["../../src/planetscale/password.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAyB,MAAM,qBAAqB,CAAC;AAiG/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyJG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAC9B,uBAAuB,EACvB,KAAK,WAEH,EAAU,EACV,KAAoB;IAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa;QACjC,CAAC,CAAC,WAAW,EAAE;QACf,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,WAAW,EAAE,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,QAAQ,EAAE,CAAC;IAEnH,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,QAAQ,GACZ,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5E,MAAM,MAAM,GACV,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;QAC9B,CAAC,CAAC,KAAK,CAAC,MAAM;QACd,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC,CAAC;IACrC,MAAM,YAAY,GAChB,KAAK,CAAC,cAAc;QACpB,CAAC,CAAC,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC;YACjE,CAAC,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;IAE3E,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CACrE;gBACE,IAAI,EAAE;oBACJ,YAAY;oBACZ,QAAQ;oBACR,MAAM;oBACN,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;iBACnB;gBACD,MAAM,EAAE,MAAM;aACf,CACF,CAAC;YAEF,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,GAAG,EAAE;oBACrD,KAAK,EAAE,GAAG,CAAC,KAAK;iBACjB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,yFAAyF;QACzF,IACE,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CACxC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO,CAC9C,EACD,CAAC;YACD,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;QACD,MAAM,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC;YACzD,IAAI,EAAE;gBACJ,YAAY;gBACZ,QAAQ;gBACR,MAAM;gBACN,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;aACnB;YACD,IAAI,EAAE;gBACJ,IAAI;gBACJ,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB;SACF,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;YACV,GAAG,IAAI,CAAC,MAAM;YACd,GAAG,KAAK;YACR,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;QACrE,IAAI,EAAE;YACJ,YAAY;YACZ,QAAQ;YACR,MAAM;SACP;QACD,IAAI,EAAE;YACJ,IAAI;YACJ,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB;KACF,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;QACV,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,SAAS,EAAE,IAAI,CAAC,UAAU;QAC1B,IAAI,EAAE,IAAI,CAAC,eAAe;QAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;QACzC,QAAQ;QACR,GAAG,KAAK;QACR,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,QAAQ,EAAE;KAClC,CAAC,CAAC;AACL,CAAC,CACF,CAAC;AAEF;;GAEG;AACH,MAAM,IAAI,GAAG,CAAI,CAAI,EAAE,CAAa,EAAE,EAAE;IACtC,MAAM,IAAI,GAAgB,EAAE,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;QACpB,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
@@ -0,0 +1,126 @@
1
+ import type { Context } from "../context.ts";
2
+ import { Resource } from "../resource.ts";
3
+ import type { Secret } from "../secret.ts";
4
+ import { type PlanetScaleProps } from "./api/client.gen.ts";
5
+ import type { Branch } from "./branch.ts";
6
+ import type { Database } from "./database.ts";
7
+ /**
8
+ * Properties for creating or updating a PlanetScale PostgreSQL Role
9
+ */
10
+ export interface RoleProps extends PlanetScaleProps {
11
+ /**
12
+ * The organization ID where the role will be created
13
+ * Required when using string database name, optional when using Database resource
14
+ */
15
+ organizationId?: string;
16
+ /**
17
+ * The database where the role will be created
18
+ * Can be either a database name (string) or Database resource
19
+ */
20
+ database: string | Database;
21
+ /**
22
+ * The branch where the role will be created
23
+ * Can be either a branch name (string) or Branch resource
24
+ * @default "main"
25
+ */
26
+ branch?: string | Branch;
27
+ /**
28
+ * Time to live in seconds
29
+ */
30
+ ttl?: number;
31
+ /**
32
+ * Roles to inherit from.
33
+ * The `"postgres"` role provides full administrator access to the database.
34
+ * You can also inherit from another Role resource.
35
+ */
36
+ inheritedRoles: InheritedRole[] | Role;
37
+ }
38
+ /**
39
+ * Roles that can be inherited from.
40
+ */
41
+ export type InheritedRole = "postgres" | "pg_checkpoint" | "pg_create_subscription" | "pg_maintain" | "pg_monitor" | "pg_read_all_data" | "pg_read_all_settings" | "pg_read_all_stats" | "pg_signal_backend" | "pg_stat_scan_tables" | "pg_use_reserved_connections" | "pg_write_all_data" | (string & {});
42
+ export interface Role extends Resource<"planetscale::Role">, Omit<RoleProps, "inheritedRoles"> {
43
+ /**
44
+ * The unique identifier for the role
45
+ */
46
+ id: string;
47
+ /**
48
+ * The name of the role
49
+ */
50
+ name: string;
51
+ /**
52
+ * The timestamp when the role expires (ISO 8601 format)
53
+ */
54
+ expiresAt: string;
55
+ /**
56
+ * The host URL for database connection
57
+ */
58
+ host: string;
59
+ /**
60
+ * The username for database authentication
61
+ */
62
+ username: string;
63
+ /**
64
+ * The encrypted password for database authentication
65
+ */
66
+ password: Secret<string>;
67
+ /**
68
+ * The database name
69
+ */
70
+ databaseName: string;
71
+ /**
72
+ * The direct connection URL for the database.
73
+ */
74
+ connectionUrl: Secret<string>;
75
+ /**
76
+ * The pooled connection URL for the database.
77
+ * Uses PSBouncer on port 6432. Recommended for production.
78
+ * @see https://planetscale.com/docs/postgres/connecting/psbouncer
79
+ */
80
+ connectionUrlPooled: Secret<string>;
81
+ /**
82
+ * The roles that this role inherits from.
83
+ */
84
+ inheritedRoles: InheritedRole[];
85
+ }
86
+ /**
87
+ * Create and manage database roles for PlanetScale PostgreSQL branches. Database roles provide secure access to your database with specific roles and permissions.
88
+ *
89
+ * For MySQL, use [Passwords](./password.ts) instead.
90
+ *
91
+ * @example
92
+ * ## Basic Role
93
+ *
94
+ * Create a default role with all permissions:
95
+ *
96
+ * ```ts
97
+ * const role = await Role("my-role", {
98
+ * database: "my-database",
99
+ * inheritedRoles: ["postgres"],
100
+ * });
101
+ * ```
102
+ *
103
+ * ## Role with TTL
104
+ *
105
+ * Create a role with a TTL of 1 hour:
106
+ *
107
+ * ```ts
108
+ * const role = await Role("my-role", {
109
+ * database: "my-database",
110
+ * ttl: 3600,
111
+ * });
112
+ * ```
113
+ *
114
+ * ## Role with Inherited Permissions
115
+ *
116
+ * Create a role with read-only access to all data and settings:
117
+ *
118
+ * ```ts
119
+ * const role = await Role("my-role", {
120
+ * database: "my-database",
121
+ * inheritedRoles: ["pg_read_all_data", "pg_read_all_settings"],
122
+ * });
123
+ * ```
124
+ */
125
+ export declare const Role: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<Role, RoleProps>, id: string, props: RoleProps) => Promise<Role>);
126
+ //# sourceMappingURL=role.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role.d.ts","sourceRoot":"","sources":["../../src/planetscale/role.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG9C;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,gBAAgB;IACjD;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC;IAE5B;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEzB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,cAAc,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,UAAU,GACV,eAAe,GACf,wBAAwB,GACxB,aAAa,GACb,YAAY,GACZ,kBAAkB,GAClB,sBAAsB,GACtB,mBAAmB,GACnB,mBAAmB,GACnB,qBAAqB,GACrB,6BAA6B,GAC7B,mBAAmB,GACnB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB,MAAM,WAAW,IACf,SAAQ,QAAQ,CAAC,mBAAmB,CAAC,EACnC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACnC;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAEzB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAE9B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAEpC;;OAEG;IACH,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,IAAI,yFAGP,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,MAC1B,MAAM,SACH,SAAS,KACf,OAAO,CAAC,IAAI,CAAC,CA+GjB,CAAC"}
@@ -0,0 +1,144 @@
1
+ import { alchemy } from "../alchemy.js";
2
+ import { Resource } from "../resource.js";
3
+ import { logger } from "../util/logger.js";
4
+ import { PlanetScaleClient } from "./api/client.gen.js";
5
+ import { waitForBranchReady } from "./utils.js";
6
+ /**
7
+ * Create and manage database roles for PlanetScale PostgreSQL branches. Database roles provide secure access to your database with specific roles and permissions.
8
+ *
9
+ * For MySQL, use [Passwords](./password.ts) instead.
10
+ *
11
+ * @example
12
+ * ## Basic Role
13
+ *
14
+ * Create a default role with all permissions:
15
+ *
16
+ * ```ts
17
+ * const role = await Role("my-role", {
18
+ * database: "my-database",
19
+ * inheritedRoles: ["postgres"],
20
+ * });
21
+ * ```
22
+ *
23
+ * ## Role with TTL
24
+ *
25
+ * Create a role with a TTL of 1 hour:
26
+ *
27
+ * ```ts
28
+ * const role = await Role("my-role", {
29
+ * database: "my-database",
30
+ * ttl: 3600,
31
+ * });
32
+ * ```
33
+ *
34
+ * ## Role with Inherited Permissions
35
+ *
36
+ * Create a role with read-only access to all data and settings:
37
+ *
38
+ * ```ts
39
+ * const role = await Role("my-role", {
40
+ * database: "my-database",
41
+ * inheritedRoles: ["pg_read_all_data", "pg_read_all_settings"],
42
+ * });
43
+ * ```
44
+ */
45
+ export const Role = Resource("planetscale::Role", async function (id, props) {
46
+ const api = new PlanetScaleClient(props);
47
+ const organization = typeof props.branch === "object"
48
+ ? props.branch.organizationId
49
+ : typeof props.database === "object"
50
+ ? props.database.organizationId
51
+ : props.organizationId;
52
+ const database = typeof props.database === "string" ? props.database : props.database.name;
53
+ const branch = typeof props.branch === "string"
54
+ ? props.branch
55
+ : (props.branch?.name ?? "main");
56
+ const inheritedRoles = Array.isArray(props.inheritedRoles)
57
+ ? props.inheritedRoles
58
+ : props.inheritedRoles.inheritedRoles;
59
+ if (!organization) {
60
+ throw new Error("Organization ID is required");
61
+ }
62
+ switch (this.phase) {
63
+ case "delete": {
64
+ if (this.output?.id) {
65
+ const res = await api.organizations.databases.branches.roles.delete({
66
+ path: {
67
+ organization,
68
+ database,
69
+ branch,
70
+ id: this.output.id,
71
+ },
72
+ result: "full",
73
+ });
74
+ if (res.error) {
75
+ switch (res.error.status) {
76
+ case 404:
77
+ break;
78
+ case 422:
79
+ // This is a workaround for 422 unprocessable: Role is still referenced and cannot be dropped.
80
+ // Essentially, the role is still linked to a branch, so we can't delete it here, but it'll be deleted when the branch is deleted.
81
+ logger.warn([
82
+ `Failed to delete role "${id}" (name: "${this.output.name}").`,
83
+ `Error: ${res.error.message}`,
84
+ `If you are deleting database "${database}" or branch "${branch}", the role will be deleted automatically.`,
85
+ `Otherwise, consider manually deleting the role at: https://app.planetscale.com/${organization}/${database}/settings/roles`,
86
+ ].join("\n"));
87
+ break;
88
+ default:
89
+ throw new Error(`Failed to delete role "${id}"`, {
90
+ cause: res.error,
91
+ });
92
+ }
93
+ }
94
+ }
95
+ return this.destroy();
96
+ }
97
+ case "create": {
98
+ const { kind, ready } = await api.organizations.databases.branches.get({
99
+ path: {
100
+ organization,
101
+ database,
102
+ name: branch,
103
+ },
104
+ });
105
+ if (kind !== "postgresql") {
106
+ throw new Error(`Cannot create a role on MySQL database "${database}". Roles are only supported on PostgreSQL databases. For MySQL databases, please use the Password resource instead.`);
107
+ }
108
+ // Cannot create role until branch is ready
109
+ if (!ready) {
110
+ await waitForBranchReady(api, organization, database, branch);
111
+ }
112
+ const role = await api.organizations.databases.branches.roles.post({
113
+ path: {
114
+ organization,
115
+ database,
116
+ branch,
117
+ },
118
+ body: {
119
+ ttl: props.ttl,
120
+ inherited_roles: inheritedRoles,
121
+ },
122
+ });
123
+ return this({
124
+ ...props,
125
+ id: role.id,
126
+ name: role.name,
127
+ host: role.access_host_url,
128
+ username: role.username,
129
+ password: alchemy.secret(role.password),
130
+ expiresAt: role.expires_at,
131
+ databaseName: role.database_name,
132
+ inheritedRoles,
133
+ connectionUrl: alchemy.secret(`postgresql://${role.username}:${role.password}@${role.access_host_url}:5432/${role.database_name}?sslmode=verify-full`),
134
+ connectionUrlPooled: alchemy.secret(`postgresql://${role.username}:${role.password}@${role.access_host_url}:6432/${role.database_name}?sslmode=verify-full`),
135
+ });
136
+ }
137
+ case "update": {
138
+ // According to the types, the only property that can be updated is the name.
139
+ // However, I was getting 500 errors when trying to update the name, so we'll just replace.
140
+ return this.replace();
141
+ }
142
+ }
143
+ });
144
+ //# sourceMappingURL=role.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role.js","sourceRoot":"","sources":["../../src/planetscale/role.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,31 @@
1
- import type { PlanetScaleApi } from "./api.ts";
1
+ import type { PlanetScaleClient } from "./api/client.gen.ts";
2
+ import type { DatabaseBranch } from "./api/types.gen.ts";
2
3
  export type PlanetScaleClusterSize = "PS_DEV" | "PS_10" | "PS_20" | "PS_40" | "PS_80" | "PS_160" | "PS_320" | "PS_400" | "PS_640" | "PS_700" | "PS_900" | "PS_1280" | "PS_1400" | "PS_1800" | "PS_2100" | "PS_2560" | "PS_2700" | "PS_2800" | (string & {});
3
4
  /**
4
- * Wait for a database to be ready with exponential backoff
5
+ * Ensures that the given cluster size is in the correct format.
5
6
  */
6
- export declare function waitForDatabaseReady(api: PlanetScaleApi, organizationId: string, databaseName: string, branchName?: string): Promise<void>;
7
+ export declare function sanitizeClusterSize(input: {
8
+ size: PlanetScaleClusterSize;
9
+ kind?: "mysql" | "postgresql";
10
+ arch?: "x86" | "arm";
11
+ region?: string;
12
+ }): string;
7
13
  /**
8
- * Wait for a keyspace to be ready
14
+ * Polls a branch until it is ready.
9
15
  */
10
- export declare function waitForKeyspaceReady(api: PlanetScaleApi, org: string, db: string, branch: string, keyspace: string): Promise<void>;
16
+ export declare function waitForBranchReady(api: PlanetScaleClient, organization: string, database: string, branch: string): Promise<DatabaseBranch>;
11
17
  /**
12
- * Fix cluster size for a branch
18
+ * Polls a database until it is ready.
13
19
  */
14
- export declare function fixClusterSize(api: PlanetScaleApi, organizationId: string, databaseName: string, branchName: string, expectedClusterSize: PlanetScaleClusterSize, isDBReady: boolean): Promise<void>;
20
+ export declare function waitForDatabaseReady(api: PlanetScaleClient, organization: string, database: string): Promise<void>;
21
+ /**
22
+ * Polls a keyspace until it is finished resizing.
23
+ */
24
+ export declare function waitForKeyspaceReady(api: PlanetScaleClient, organization: string, database: string, branch: string, keyspace: string): Promise<void>;
25
+ /**
26
+ * Ensure a branch is production and has the correct cluster size.
27
+ * If a branch is not production, it will be promoted to production because
28
+ * cluster sizes can only be configured for production branches.
29
+ */
30
+ export declare function ensureProductionBranchClusterSize(api: PlanetScaleClient, organization: string, database: string, branch: string, kind: "mysql" | "postgresql", expectedClusterSize: PlanetScaleClusterSize): Promise<void>;
15
31
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/planetscale/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,MAAM,sBAAsB,GAC9B,QAAQ,GACR,OAAO,GACP,OAAO,GACP,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,cAAc,EACnB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,EACnB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,mBAAmB,EAAE,sBAAsB,EAC3C,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CA0Ef"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/planetscale/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,MAAM,sBAAsB,GAC9B,QAAQ,GACR,OAAO,GACP,OAAO,GACP,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;IAC9B,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAaT;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,CAAC,CASzB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;;GAIG;AACH,wBAAsB,iCAAiC,CACrD,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GAAG,YAAY,EAC5B,mBAAmB,EAAE,sBAAsB,GAC1C,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
@@ -1,95 +1,189 @@
1
1
  /**
2
- * Wait for a database to be ready with exponential backoff
2
+ * Ensures that the given cluster size is in the correct format.
3
3
  */
4
- export async function waitForDatabaseReady(api, organizationId, databaseName, branchName) {
5
- const startTime = Date.now();
6
- let waitMs = 100;
7
- const branchSuffix = branchName ? `/branches/${branchName}` : "";
8
- while (true) {
9
- const response = await api.get(`/organizations/${organizationId}/databases/${databaseName}${branchSuffix}`);
10
- if (!response.ok) {
11
- throw new Error(`Failed to check database state: ${response.statusText}`);
12
- }
13
- const data = await response.json();
14
- if (data.ready === true) {
15
- return;
16
- }
17
- if (Date.now() - startTime >= 60000) {
18
- throw new Error(`Timeout waiting for database ${databaseName} to be ready`);
19
- }
20
- await new Promise((resolve) => setTimeout(resolve, waitMs));
21
- waitMs = Math.min(waitMs * 2, 1000); // Cap at 1s intervals
4
+ export function sanitizeClusterSize(input) {
5
+ // NAS-backed Postgres cluster sizes are formatted as `PS_<size>_<provider>_<arch>`,
6
+ // where <provider> is either "AWS" or "GCP", and <arch> is either "ARM" or "X86".
7
+ // Postgres clusters backed by PlanetScale Metal are more complex (e.g. "M6_160_AWS_INTEL_D_METAL_118"),
8
+ // so to avoid messing with those, we just check for AWS or GCP in the size.
9
+ if (input.kind === "postgresql" && !input.size.match(/(AWS|GCP)/)) {
10
+ // Infer the provider from the region.
11
+ // Not all AWS regions start with "aws-", but all GCP regions start with "gcp-".
12
+ const provider = input.region?.startsWith("gcp") ? "GCP" : "AWS";
13
+ const arch = (input.arch ?? "x86").toUpperCase();
14
+ return `${input.size}_${provider}_${arch}`;
22
15
  }
16
+ return input.size;
23
17
  }
24
18
  /**
25
- * Wait for a keyspace to be ready
19
+ * Polls a branch until it is ready.
26
20
  */
27
- export async function waitForKeyspaceReady(api, org, db, branch, keyspace) {
28
- const start = Date.now();
29
- let delay = 100;
30
- while (true) {
31
- const res = await api.get(`/organizations/${org}/databases/${db}/branches/${branch}/keyspaces/${keyspace}/resizes`);
32
- if (!res.ok) {
33
- throw new Error(`Error fetching keyspace "${keyspace}": ${res.statusText}`);
34
- }
35
- const ks = await res.json();
36
- // once it's fully ready, we can proceed
37
- if (ks.data.every((item) => item.state !== "resizing")) {
38
- return;
21
+ export async function waitForBranchReady(api, organization, database, branch) {
22
+ return await poll({
23
+ description: `branch "${branch}" ready`,
24
+ fn: () => api.organizations.databases.branches.get({
25
+ path: { organization, database, name: branch },
26
+ }),
27
+ predicate: (branch) => branch.ready,
28
+ });
29
+ }
30
+ /**
31
+ * Polls a database until it is ready.
32
+ */
33
+ export async function waitForDatabaseReady(api, organization, database) {
34
+ await poll({
35
+ description: `database "${database}" ready`,
36
+ fn: () => api.organizations.databases.get({
37
+ path: { organization, name: database },
38
+ }),
39
+ predicate: (database) => database.ready,
40
+ });
41
+ }
42
+ /**
43
+ * Polls a keyspace until it is finished resizing.
44
+ */
45
+ export async function waitForKeyspaceReady(api, organization, database, branch, keyspace) {
46
+ await poll({
47
+ description: `keyspace "${keyspace}" ready`,
48
+ fn: () => api.organizations.databases.branches.keyspaces.resizes.list({
49
+ path: { organization, database, branch, name: keyspace },
50
+ }),
51
+ predicate: (response) => response.data.every((item) => item.state !== "resizing"),
52
+ initialDelay: 100,
53
+ maxDelay: 1000,
54
+ });
55
+ }
56
+ /**
57
+ * Ensure a branch is production and has the correct cluster size.
58
+ * If a branch is not production, it will be promoted to production because
59
+ * cluster sizes can only be configured for production branches.
60
+ */
61
+ export async function ensureProductionBranchClusterSize(api, organization, database, branch, kind, expectedClusterSize) {
62
+ switch (kind) {
63
+ case "mysql": {
64
+ // Vitess databases must be promoted before resizing
65
+ await ensureProductionBranch(api, organization, database, branch);
66
+ await ensureMySQLClusterSize(api, organization, database, branch, expectedClusterSize);
67
+ break;
39
68
  }
40
- if (Date.now() - start > 600_000) {
41
- throw new Error(`Timeout waiting for keyspace "${keyspace}" to be ready`);
69
+ case "postgresql": {
70
+ // Postgres databases must be resized first before promoting, otherwise 500 error
71
+ await ensurePostgresClusterSize(api, organization, database, branch, expectedClusterSize);
72
+ await ensureProductionBranch(api, organization, database, branch);
73
+ break;
42
74
  }
43
- await new Promise((r) => setTimeout(r, delay));
44
- delay = Math.min(delay * 2, 1_000);
45
75
  }
46
76
  }
47
77
  /**
48
- * Fix cluster size for a branch
78
+ * Checks if a branch is production and promotes it if it is not.
49
79
  */
50
- export async function fixClusterSize(api, organizationId, databaseName, branchName, expectedClusterSize, isDBReady) {
51
- if (!isDBReady) {
52
- await waitForDatabaseReady(api, organizationId, databaseName);
53
- }
54
- // 1. Ensure branch is production
55
- let branchRes = await api.get(`/organizations/${organizationId}/databases/${databaseName}/branches/${branchName}`);
56
- if (!branchRes.ok) {
57
- throw new Error(`Unable to get branch data: ${branchRes.statusText}`);
58
- }
59
- let branchData = await branchRes.json();
60
- if (!branchData.production) {
61
- if (!branchData.ready) {
62
- await waitForDatabaseReady(api, organizationId, databaseName, branchName);
80
+ async function ensureProductionBranch(api, organization, database, name) {
81
+ const data = await api.organizations.databases.branches.get({
82
+ path: {
83
+ organization,
84
+ database,
85
+ name,
86
+ },
87
+ });
88
+ if (!data.production) {
89
+ if (!data.ready) {
90
+ await waitForBranchReady(api, organization, database, name);
63
91
  }
64
- const promoteRes = await api.post(`/organizations/${organizationId}/databases/${databaseName}/branches/${branchName}/promote`);
65
- if (!promoteRes.ok) {
66
- throw new Error(`Unable to promote branch: ${promoteRes.statusText}`);
67
- }
68
- }
69
- // 2. Load default keyspace
70
- const ksListRes = await api.get(`/organizations/${organizationId}/databases/${databaseName}/branches/${branchName}/keyspaces`);
71
- if (!ksListRes.ok) {
72
- throw new Error(`Failed to list keyspaces: ${ksListRes.statusText}`);
92
+ await api.organizations.databases.branches.promote.post({
93
+ path: { organization, database, name },
94
+ });
73
95
  }
74
- const ksList = (await ksListRes.json()).data;
75
- const defaultKsData = ksList.find((x) => x.name === databaseName); // Default keypsace is always the same name as the database
76
- if (ksList.length === 0 || !defaultKsData) {
77
- throw new Error(`No default keyspace found for branch ${branchName}`);
96
+ }
97
+ /**
98
+ * Ensures that a MySQL branch has the correct cluster size.
99
+ */
100
+ async function ensureMySQLClusterSize(api, organization, database, branch, expectedClusterSize) {
101
+ // 1. Load default keyspace
102
+ const keyspaces = await api.organizations.databases.branches.keyspaces.list({
103
+ path: {
104
+ organization,
105
+ database,
106
+ branch,
107
+ },
108
+ });
109
+ const defaultKeyspace = keyspaces.data.find((x) => x.name === database); // Default keyspace is always the same name as the database
110
+ if (!defaultKeyspace) {
111
+ throw new Error(`No default keyspace found for branch ${branch}`);
78
112
  }
79
- const defaultKs = defaultKsData.name;
80
- let currentSize = defaultKsData.cluster_name;
81
- // 3. Wait until any in-flight resize is done
82
- await waitForKeyspaceReady(api, organizationId, databaseName, branchName, defaultKs);
83
- // 4. If size mismatch, trigger resize and wait again
113
+ // 2. Wait until any in-flight resize is done
114
+ await waitForKeyspaceReady(api, organization, database, branch, defaultKeyspace.name);
115
+ // 3. If size mismatch, trigger resize and wait again
84
116
  // Ideally this would use the undocumented Keyspaces API, but there seems to be a missing oauth scope that we cannot add via the console yet
85
- if (currentSize !== expectedClusterSize) {
86
- const resizeRes = await api.patch(`/organizations/${organizationId}/databases/${databaseName}/branches/${branchName}/cluster`, { cluster_size: expectedClusterSize });
87
- if (!resizeRes.ok) {
88
- const text = await resizeRes.text();
89
- throw new Error(`Failed to start resize: ${resizeRes.statusText} ${text}`);
90
- }
117
+ if (defaultKeyspace.cluster_name !== expectedClusterSize) {
118
+ await api.organizations.databases.branches.cluster.patch({
119
+ path: {
120
+ organization,
121
+ database,
122
+ name: branch,
123
+ },
124
+ body: { cluster_size: expectedClusterSize },
125
+ });
91
126
  // Poll until the resize completes
92
- await waitForKeyspaceReady(api, organizationId, databaseName, branchName, defaultKs);
127
+ await waitForKeyspaceReady(api, organization, database, branch, defaultKeyspace.name);
128
+ }
129
+ }
130
+ /**
131
+ * Ensures that a Postgres branch has the correct cluster size.
132
+ */
133
+ async function ensurePostgresClusterSize(api, organization, database, branch, expectedClusterSize) {
134
+ const data = await api.organizations.databases.branches.get({
135
+ path: {
136
+ organization,
137
+ database,
138
+ name: branch,
139
+ },
140
+ });
141
+ if (data.cluster_name === expectedClusterSize) {
142
+ return;
143
+ }
144
+ await waitForPendingPostgresChanges(api, organization, database, branch);
145
+ const change = await api.organizations.databases.branches.changes.patch({
146
+ path: {
147
+ organization,
148
+ database,
149
+ branch,
150
+ },
151
+ body: {
152
+ cluster_size: expectedClusterSize,
153
+ },
154
+ });
155
+ await waitForPendingPostgresChanges(api, organization, database, branch, change.id);
156
+ }
157
+ /**
158
+ * Polls for a pending Postgres change to be completed.
159
+ */
160
+ async function waitForPendingPostgresChanges(api, organization, database, branch, changeId) {
161
+ await poll({
162
+ description: `changes for branch "${branch}"`,
163
+ fn: () => api.organizations.databases.branches.changes.list({
164
+ path: { organization, database, branch },
165
+ }),
166
+ predicate: (response) => response.data.every((change) => change.state === "completed" ||
167
+ change.state === "canceled" ||
168
+ (changeId && change.id === changeId)),
169
+ });
170
+ }
171
+ /**
172
+ * Polls a function until it returns a result that satisfies the predicate.
173
+ */
174
+ async function poll(input) {
175
+ const start = Date.now();
176
+ let delay = input.initialDelay ?? 250;
177
+ while (true) {
178
+ const result = await input.fn();
179
+ if (input.predicate(result)) {
180
+ return result;
181
+ }
182
+ if (Date.now() - start >= (input.timeout ?? 1_000_000)) {
183
+ throw new Error(`Timed out waiting for ${input.description} after ${Math.round((input.timeout ?? 1_000_000) / 1000)}s`);
184
+ }
185
+ await new Promise((resolve) => setTimeout(resolve, delay));
186
+ delay = Math.min(delay * 2, input.maxDelay ?? 5_000);
93
187
  }
94
188
  }
95
189
  //# sourceMappingURL=utils.js.map