alchemy 0.73.1 → 0.74.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 (96) hide show
  1. package/bin/alchemy.js +3311 -4413
  2. package/bin/alchemy.ts +2 -0
  3. package/bin/commands/configure.ts +4 -1
  4. package/bin/commands/util.ts +510 -0
  5. package/lib/cloudflare/bound.d.ts +1 -1
  6. package/lib/cloudflare/bound.d.ts.map +1 -1
  7. package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts.map +1 -1
  8. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +6 -14
  9. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
  10. package/lib/cloudflare/miniflare/remote-binding-proxy.d.ts.map +1 -1
  11. package/lib/cloudflare/miniflare/remote-binding-proxy.js +12 -4
  12. package/lib/cloudflare/miniflare/remote-binding-proxy.js.map +1 -1
  13. package/lib/cloudflare/tanstack-start/tanstack-start.d.ts.map +1 -1
  14. package/lib/cloudflare/tanstack-start/tanstack-start.js +8 -1
  15. package/lib/cloudflare/tanstack-start/tanstack-start.js.map +1 -1
  16. package/lib/cloudflare/vite/plugin.d.ts.map +1 -1
  17. package/lib/cloudflare/vite/plugin.js +23 -9
  18. package/lib/cloudflare/vite/plugin.js.map +1 -1
  19. package/lib/planetscale/branch.d.ts +6 -0
  20. package/lib/planetscale/branch.d.ts.map +1 -1
  21. package/lib/planetscale/branch.js +2 -1
  22. package/lib/planetscale/branch.js.map +1 -1
  23. package/lib/planetscale/database.d.ts +6 -0
  24. package/lib/planetscale/database.d.ts.map +1 -1
  25. package/lib/planetscale/database.js +2 -1
  26. package/lib/planetscale/database.js.map +1 -1
  27. package/lib/planetscale/password.d.ts +6 -0
  28. package/lib/planetscale/password.d.ts.map +1 -1
  29. package/lib/planetscale/password.js +2 -1
  30. package/lib/planetscale/password.js.map +1 -1
  31. package/lib/planetscale/role.d.ts +6 -0
  32. package/lib/planetscale/role.d.ts.map +1 -1
  33. package/lib/planetscale/role.js +2 -1
  34. package/lib/planetscale/role.js.map +1 -1
  35. package/lib/prisma-postgres/api/client.gen.d.ts +13 -0
  36. package/lib/prisma-postgres/api/client.gen.d.ts.map +1 -0
  37. package/lib/prisma-postgres/api/client.gen.js +6 -0
  38. package/lib/prisma-postgres/api/client.gen.js.map +1 -0
  39. package/lib/prisma-postgres/api/sdk.gen.d.ts +120 -0
  40. package/lib/prisma-postgres/api/sdk.gen.d.ts.map +1 -0
  41. package/lib/prisma-postgres/api/sdk.gen.js +219 -0
  42. package/lib/prisma-postgres/api/sdk.gen.js.map +1 -0
  43. package/lib/prisma-postgres/api/types.gen.d.ts +957 -0
  44. package/lib/prisma-postgres/api/types.gen.d.ts.map +1 -0
  45. package/lib/prisma-postgres/api/types.gen.js +2 -0
  46. package/lib/prisma-postgres/api/types.gen.js.map +1 -0
  47. package/lib/prisma-postgres/api.d.ts +29 -0
  48. package/lib/prisma-postgres/api.d.ts.map +1 -0
  49. package/lib/prisma-postgres/api.js +49 -0
  50. package/lib/prisma-postgres/api.js.map +1 -0
  51. package/lib/prisma-postgres/connection.d.ts +87 -0
  52. package/lib/prisma-postgres/connection.d.ts.map +1 -0
  53. package/lib/prisma-postgres/connection.js +73 -0
  54. package/lib/prisma-postgres/connection.js.map +1 -0
  55. package/lib/prisma-postgres/database.d.ts +104 -0
  56. package/lib/prisma-postgres/database.d.ts.map +1 -0
  57. package/lib/prisma-postgres/database.js +88 -0
  58. package/lib/prisma-postgres/database.js.map +1 -0
  59. package/lib/prisma-postgres/index.d.ts +5 -0
  60. package/lib/prisma-postgres/index.d.ts.map +1 -0
  61. package/lib/prisma-postgres/index.js +5 -0
  62. package/lib/prisma-postgres/index.js.map +1 -0
  63. package/lib/prisma-postgres/project.d.ts +69 -0
  64. package/lib/prisma-postgres/project.d.ts.map +1 -0
  65. package/lib/prisma-postgres/project.js +62 -0
  66. package/lib/prisma-postgres/project.js.map +1 -0
  67. package/lib/prisma-postgres/workspace.d.ts +18 -0
  68. package/lib/prisma-postgres/workspace.d.ts.map +1 -0
  69. package/lib/prisma-postgres/workspace.js +21 -0
  70. package/lib/prisma-postgres/workspace.js.map +1 -0
  71. package/lib/util/http.d.ts +5 -2
  72. package/lib/util/http.d.ts.map +1 -1
  73. package/lib/util/http.js +71 -26
  74. package/lib/util/http.js.map +1 -1
  75. package/package.json +9 -1
  76. package/src/cloudflare/bound.ts +3 -1
  77. package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +10 -13
  78. package/src/cloudflare/miniflare/remote-binding-proxy.ts +12 -4
  79. package/src/cloudflare/tanstack-start/tanstack-start.ts +9 -1
  80. package/src/cloudflare/vite/plugin.ts +24 -10
  81. package/src/planetscale/branch.ts +9 -1
  82. package/src/planetscale/database.ts +9 -1
  83. package/src/planetscale/password.ts +9 -1
  84. package/src/planetscale/role.ts +9 -1
  85. package/src/prisma-postgres/api/client.gen.ts +27 -0
  86. package/src/prisma-postgres/api/sdk.gen.ts +437 -0
  87. package/src/prisma-postgres/api/types.gen.ts +1096 -0
  88. package/src/prisma-postgres/api.ts +79 -0
  89. package/src/prisma-postgres/connection.ts +154 -0
  90. package/src/prisma-postgres/database.ts +178 -0
  91. package/src/prisma-postgres/index.ts +4 -0
  92. package/src/prisma-postgres/project.ts +131 -0
  93. package/src/prisma-postgres/workspace.ts +27 -0
  94. package/src/util/http.ts +79 -33
  95. package/workers/cloudflare-state-store.js +1 -1
  96. package/workers/tunnel-proxy.js +1 -1
@@ -0,0 +1,62 @@
1
+ import { Resource } from "../resource.js";
2
+ import { createPrismaApi } from "./api.js";
3
+ /**
4
+ * Creates and manages Prisma Postgres projects.
5
+ *
6
+ * Prisma Postgres projects are containers for your databases and
7
+ * their configurations. Projects belong to a workspace and can
8
+ * contain multiple databases.
9
+ *
10
+ * @example
11
+ * // Create a database for a project
12
+ * import { Project, Database } from "alchemy/prisma-postgres";
13
+ * const project = await Project("my-app");
14
+ */
15
+ export const Project = Resource("prisma::Project", async function (id, props) {
16
+ const api = createPrismaApi({
17
+ serviceToken: props?.serviceToken,
18
+ });
19
+ const name = props?.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
20
+ const shouldDelete = props?.delete ?? false;
21
+ if (this.phase === "delete") {
22
+ if (shouldDelete) {
23
+ await api.deleteProject({
24
+ path: { id: this.output.id },
25
+ });
26
+ }
27
+ return this.destroy();
28
+ }
29
+ if (this.phase === "update") {
30
+ return this.replace();
31
+ }
32
+ const project = await api
33
+ .createProjectWithPostgresDatabase({
34
+ body: {
35
+ createDatabase: false,
36
+ name,
37
+ //! prisma seems to not support setting the workspace on project creation?
38
+ },
39
+ })
40
+ .then((response) => response.data.data);
41
+ return {
42
+ id: project.id,
43
+ name: project.name,
44
+ createdAt: project.createdAt,
45
+ workspace: project.workspace,
46
+ };
47
+ });
48
+ export async function findProjectByName(props) {
49
+ const api = createPrismaApi(props);
50
+ let hasMore = true;
51
+ let project;
52
+ while (hasMore) {
53
+ const response = await api.listProjects();
54
+ project = response.data.data.find((project) => project.name === props.name);
55
+ if (project != null) {
56
+ break;
57
+ }
58
+ hasMore = response.data.pagination.hasMore;
59
+ }
60
+ return project;
61
+ }
62
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/prisma-postgres/project.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAqD3C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAC7B,iBAAiB,EACjB,KAAK,WAEH,EAAU,EACV,KAAoB;IAEpB,MAAM,GAAG,GAAG,eAAe,CAAC;QAC1B,YAAY,EAAE,KAAK,EAAE,YAAY;KAClC,CAAC,CAAC;IACH,MAAM,IAAI,GACR,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACxE,MAAM,YAAY,GAAG,KAAK,EAAE,MAAM,IAAI,KAAK,CAAC;IAE5C,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,GAAG,CAAC,aAAa,CAAC;gBACtB,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE;aAC7B,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,GAAG;SACtB,iCAAiC,CAAC;QACjC,IAAI,EAAE;YACJ,cAAc,EAAE,KAAK;YACrB,IAAI;YACJ,0EAA0E;SAC3E;KACF,CAAC;SACD,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAK,CAAC,CAAC;IAE3C,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAmB;IACzD,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,OAIS,CAAC;IACd,OAAO,OAAO,EAAE,CAAC;QACf,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,YAAY,EAAE,CAAC;QAC1C,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5E,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,MAAM;QACR,CAAC;QACD,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;IAC7C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { type PrismaApiOptions } from "./api.ts";
2
+ /**
3
+ * Get a prisma workspace by id or name.
4
+ *
5
+ * @example
6
+ * const workspace = await WorkspaceRef("alchemy-test");
7
+ *
8
+ * @param identifier The id or name of the workspace to get.
9
+ * @param props The api credentials to use.
10
+ * @returns The workspace.
11
+ */
12
+ export declare function WorkspaceRef(identifier: string, props?: PrismaApiOptions): Promise<{
13
+ id: string;
14
+ type: "workspace";
15
+ name: string;
16
+ createdAt: string;
17
+ }>;
18
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/prisma-postgres/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAElE;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,gBAAgB;;;;;GAYzB"}
@@ -0,0 +1,21 @@
1
+ import { createPrismaApi } from "./api.js";
2
+ /**
3
+ * Get a prisma workspace by id or name.
4
+ *
5
+ * @example
6
+ * const workspace = await WorkspaceRef("alchemy-test");
7
+ *
8
+ * @param identifier The id or name of the workspace to get.
9
+ * @param props The api credentials to use.
10
+ * @returns The workspace.
11
+ */
12
+ export async function WorkspaceRef(identifier, props) {
13
+ const api = createPrismaApi(props);
14
+ const workspaces = await api.listWorkspaces();
15
+ const workspace = workspaces.data.data.find((workspace) => workspace.id === identifier || workspace.name === identifier);
16
+ if (!workspace) {
17
+ throw new Error(`Workspace with identifier ${identifier} not found`);
18
+ }
19
+ return workspace;
20
+ }
21
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/prisma-postgres/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AAElE;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAkB,EAClB,KAAwB;IAExB,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAEnC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,cAAc,EAAE,CAAC;IAC9C,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CACzC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,UAAU,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU,CAC5E,CAAC;IACF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,UAAU,YAAY,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import http from "node:http";
2
2
  import { type Duplex } from "node:stream";
3
- import { WebSocketServer, type WebSocket } from "ws";
3
+ import { WebSocket, WebSocketServer } from "ws";
4
4
  export declare class HTTPServer {
5
5
  httpServer: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
6
6
  webSocketServer?: WebSocketServer;
@@ -12,7 +12,10 @@ export declare class HTTPServer {
12
12
  get url(): string;
13
13
  close(): Promise<void>;
14
14
  }
15
- export declare function coupleWebSocket(wss: WebSocketServer, req: http.IncomingMessage, socket: Duplex, head: Buffer, server: WebSocket): void;
15
+ export declare function createUpgradeHandler(props: {
16
+ wss: WebSocketServer;
17
+ createServerWebSocket: (req: http.IncomingMessage) => Promise<WebSocket>;
18
+ }): (req: http.IncomingMessage, socket: Duplex, head: Buffer) => Promise<void>;
16
19
  export declare function toWebRequest(req: http.IncomingMessage, host?: string): Request;
17
20
  export declare function writeNodeResponse(res: http.ServerResponse, response: Response): Promise<void>;
18
21
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/util/http.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,IAAI,CAAC;AAErD,qBAAa,UAAU;IACrB,UAAU,uEAAuB;IACjC,eAAe,CAAC,EAAE,eAAe,CAAC;gBAEtB,OAAO,EAAE;QACnB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;QACrD,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;KAChD;IAgBD,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM;IAYpB,IAAI,GAAG,WAON;IAEK,KAAK;CAWZ;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,QASlB;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAeT;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,QAAQ,EAAE,QAAQ,iBAoBnB"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/util/http.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,KAAK,MAAM,EAAY,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAEhD,qBAAa,UAAU;IACrB,UAAU,uEAAuB;IACjC,eAAe,CAAC,EAAE,eAAe,CAAC;gBAEtB,OAAO,EAAE;QACnB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;QACrD,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;KAChD;IAmBD,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM;IAYpB,IAAI,GAAG,WAON;IAEK,KAAK;CAIZ;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,GAAG,EAAE,eAAe,CAAC;IACrB,qBAAqB,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;CAC1E,IAoDe,KAAK,IAAI,CAAC,eAAe,EAAE,QAAQ,MAAM,EAAE,MAAM,MAAM,mBAQtE;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAeT;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,QAAQ,EAAE,QAAQ,iBAoBnB"}
package/lib/util/http.js CHANGED
@@ -1,23 +1,24 @@
1
+ import { once } from "node:events";
1
2
  import http from "node:http";
2
3
  import { Readable } from "node:stream";
3
- import { WebSocketServer } from "ws";
4
+ import { WebSocket, WebSocketServer } from "ws";
4
5
  export class HTTPServer {
5
6
  httpServer = http.createServer();
6
7
  webSocketServer;
7
8
  constructor(options) {
9
+ const websocket = options.websocket;
10
+ if (websocket) {
11
+ const wss = new WebSocketServer({ noServer: true });
12
+ this.webSocketServer = wss;
13
+ this.httpServer.on("upgrade", createUpgradeHandler({
14
+ wss,
15
+ createServerWebSocket: (req) => websocket(toWebRequest(req)),
16
+ }));
17
+ }
8
18
  this.httpServer.on("request", async (req, res) => {
9
19
  const response = await options.fetch(toWebRequest(req));
10
20
  await writeNodeResponse(res, response);
11
21
  });
12
- const websocket = options.websocket;
13
- if (websocket) {
14
- const webSocketServer = new WebSocketServer({ noServer: true });
15
- this.webSocketServer = webSocketServer;
16
- this.httpServer.on("upgrade", async (req, socket, head) => {
17
- const ws = await websocket(toWebRequest(req));
18
- coupleWebSocket(webSocketServer, req, socket, head, ws);
19
- });
20
- }
21
22
  }
22
23
  listen(port) {
23
24
  return new Promise((resolve, reject) => {
@@ -39,25 +40,69 @@ export class HTTPServer {
39
40
  return `http://${hostname}:${address.port}`;
40
41
  }
41
42
  async close() {
42
- const webSocketServer = this.webSocketServer;
43
- if (webSocketServer) {
44
- await new Promise((resolve, reject) => {
45
- webSocketServer.close((err) => (err ? reject(err) : resolve()));
46
- });
43
+ this.webSocketServer?.close();
44
+ this.httpServer.close();
45
+ }
46
+ }
47
+ export function createUpgradeHandler(props) {
48
+ async function waitForWebSocketOpen(server) {
49
+ if (server.readyState === WebSocket.CONNECTING) {
50
+ // Wait for client to be open before accepting worker pair (which would
51
+ // release buffered messages). Note this will throw if an "error" event is
52
+ // dispatched (https://github.com/cloudflare/miniflare/issues/229).
53
+ await once(server, "open");
54
+ }
55
+ else if (server.readyState >= WebSocket.CLOSING) {
56
+ throw new TypeError("Incoming WebSocket connection already closed.");
47
57
  }
48
- await new Promise((resolve, reject) => {
49
- this.httpServer.close((err) => (err ? reject(err) : resolve()));
58
+ }
59
+ function forwardWebSocketEvents(from, to) {
60
+ const ready = waitForWebSocketOpen(to);
61
+ const ifOpen = (fn) => {
62
+ // Wait for target to be open before sending message
63
+ void ready.then(() => {
64
+ // Silently discard messages received after close:
65
+ // https://www.rfc-editor.org/rfc/rfc6455#section-1.4
66
+ if (to.readyState !== WebSocket.OPEN)
67
+ return;
68
+ fn();
69
+ });
70
+ };
71
+ from.on("message", (event, binary) => {
72
+ ifOpen(() => {
73
+ to.send(event, { binary });
74
+ });
75
+ });
76
+ from.on("close", (code, reason) => {
77
+ // Handle close events similar to Miniflare:
78
+ // https://github.com/cloudflare/workers-sdk/blob/88f081f4e2bd299e715d18bcfe181971f534ff76/packages/miniflare/src/http/websocket.ts#L276-L282
79
+ ifOpen(() => {
80
+ if (code === 1005 /* No Status Received */) {
81
+ to.close();
82
+ }
83
+ else if (code === 1006 /* Abnormal Closure */) {
84
+ to.terminate();
85
+ }
86
+ else {
87
+ to.close(code, reason);
88
+ }
89
+ });
90
+ });
91
+ from.on("error", (error) => {
92
+ console.error("Websocket error:", error);
93
+ ifOpen(() => {
94
+ to.terminate();
95
+ });
50
96
  });
51
97
  }
52
- }
53
- export function coupleWebSocket(wss, req, socket, head, server) {
54
- wss.handleUpgrade(req, socket, head, (client) => {
55
- client.on("message", (event, binary) => server.send(event, { binary }));
56
- client.on("close", (code, reason) => server.close(code, reason));
57
- server.on("message", (event, binary) => client.send(event, { binary }));
58
- server.on("close", (code, reason) => client.close(code, reason));
59
- wss.emit("connection", client, req);
60
- });
98
+ return async (req, socket, head) => {
99
+ const server = await props.createServerWebSocket(req);
100
+ props.wss.handleUpgrade(req, socket, head, async (client) => {
101
+ forwardWebSocketEvents(server, client);
102
+ forwardWebSocketEvents(client, server);
103
+ props.wss.emit("connection", client, req);
104
+ });
105
+ };
61
106
  }
62
107
  export function toWebRequest(req, host) {
63
108
  const method = req.method ?? "GET";
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/util/http.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAe,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,eAAe,EAAkB,MAAM,IAAI,CAAC;AAErD,MAAM,OAAO,UAAU;IACrB,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IACjC,eAAe,CAAmB;IAElC,YAAY,OAGX;QACC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YAC/C,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;YACxD,MAAM,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACpC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;YACvC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;gBACxD,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC9C,eAAe,CAAC,eAAe,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAa;QAClB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;gBACnC,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACpC,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,GAAG;QACL,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAwB,CAAC;QAChE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QAC1E,OAAO,UAAU,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;QAC7C,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAClE,CAAC,CAAC,CAAC;QACL,CAAC;QACD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED,MAAM,UAAU,eAAe,CAC7B,GAAoB,EACpB,GAAyB,EACzB,MAAc,EACd,IAAY,EACZ,MAAiB;IAEjB,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE;QAC9C,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACxE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACxE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACjE,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,GAAyB,EACzB,IAAa;IAEb,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,UAAU,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1E,MAAM,IAAI,GACR,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ;QAC1D,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;QACjC,MAAM;QACN,OAAO,EAAE,GAAG,CAAC,OAAiC;QAC9C,IAAI,EAAE,IAA2B;QACjC,yDAAyD;QACzD,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QACjC,QAAQ,EAAE,QAAQ;KACnB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAwB,EACxB,QAAkB;IAElB,GAAG,CAAC,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,QAAQ,CAAC,IAAI,CAAC,MAAM,CACxB,IAAI,cAAc,CAAC;YACjB,KAAK,CAAC,KAAK;gBACT,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;YACD,KAAK;gBACH,GAAG,CAAC,GAAG,EAAE,CAAC;YACZ,CAAC;SACF,CAAC,CACH,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/util/http.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemy",
3
- "version": "0.73.1",
3
+ "version": "0.74.0",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Sam Goodwin <sam@alchemy.run>",
6
6
  "homepage": "https://alchemy.run",
@@ -128,6 +128,10 @@
128
128
  "bun": "./src/planetscale/index.ts",
129
129
  "import": "./lib/planetscale/index.js"
130
130
  },
131
+ "./prisma-postgres": {
132
+ "bun": "./src/prisma-postgres/index.ts",
133
+ "import": "./lib/prisma-postgres/index.js"
134
+ },
131
135
  "./random": {
132
136
  "bun": "./src/random/index.ts",
133
137
  "import": "./lib/random/index.js"
@@ -209,6 +213,7 @@
209
213
  "drizzle-orm": "^0.44.2",
210
214
  "rwsdk": "^0.1.36",
211
215
  "stripe": "^18.5.0",
216
+ "vite": ">=6.0.0",
212
217
  "wrangler": "^4.42.2"
213
218
  },
214
219
  "peerDependenciesMeta": {
@@ -262,6 +267,9 @@
262
267
  },
263
268
  "stripe": {
264
269
  "optional": true
270
+ },
271
+ "vite": {
272
+ "optional": true
265
273
  }
266
274
  },
267
275
  "devDependencies": {
@@ -100,4 +100,6 @@ export type Bound<T extends Binding> = T extends _DurableObjectNamespace<
100
100
  Obj &
101
101
  Rpc.DurableObjectBranded
102
102
  >
103
- : Service;
103
+ : T extends undefined
104
+ ? undefined
105
+ : Service;
@@ -3,7 +3,7 @@ import { once } from "node:events";
3
3
  import http from "node:http";
4
4
  import { Readable } from "node:stream";
5
5
  import { WebSocket, WebSocketServer } from "ws";
6
- import { coupleWebSocket } from "../../util/http.ts";
6
+ import { createUpgradeHandler } from "../../util/http.ts";
7
7
 
8
8
  export interface MiniflareWorkerProxy {
9
9
  url: URL;
@@ -20,15 +20,14 @@ export async function createMiniflareWorkerProxy(options: {
20
20
  const server = http.createServer();
21
21
  const wss = new WebSocketServer({ noServer: true });
22
22
 
23
- server.on("upgrade", async (req, socket, head) => {
24
- try {
25
- const server = await createServerWebSocket(req);
26
- coupleWebSocket(wss, req, socket, head, server);
27
- } catch (error) {
28
- console.error(error);
29
- socket.destroy();
30
- }
31
- });
23
+ server.on(
24
+ "upgrade",
25
+ createUpgradeHandler({
26
+ wss,
27
+ createServerWebSocket: (req) => createServerWebSocket(req),
28
+ }),
29
+ );
30
+
32
31
  server.on("request", async (req, res) => {
33
32
  try {
34
33
  const response = await handleFetch(req);
@@ -84,13 +83,11 @@ export async function createMiniflareWorkerProxy(options: {
84
83
  options.transformRequest?.(info);
85
84
  const name = options.getWorkerName(info);
86
85
 
87
- const server = new WebSocket(url, protocols, {
86
+ return new WebSocket(url, protocols, {
88
87
  headers: {
89
88
  "MF-Route-Override": name,
90
89
  },
91
90
  });
92
- await once(server, "open");
93
- return server;
94
91
  };
95
92
 
96
93
  server.listen(options.port);
@@ -61,11 +61,19 @@ export async function createRemoteProxyWorker(input: {
61
61
  websocket: async (req) => {
62
62
  const input = new URL(req.url);
63
63
  const proxied = new URL(input.pathname + input.search, `https://${host}`);
64
+ const headers: Record<string, string> = {
65
+ "cf-workers-preview-token": token,
66
+ host,
67
+ };
68
+ // We don't want to include all headers because some can mess with websocket connections.
69
+ // However, it's important to include `mf-` prefixed headers to configure bindings for miniflare to work.
70
+ req.headers.forEach((value, key) => {
71
+ if (key.startsWith("mf-")) {
72
+ headers[key] = value;
73
+ }
74
+ });
64
75
  return new WebSocket(proxied, {
65
- headers: {
66
- "cf-workers-preview-token": token,
67
- host,
68
- },
76
+ headers,
69
77
  });
70
78
  },
71
79
  fetch: async (req) => {
@@ -1,3 +1,5 @@
1
+ import path from "node:path";
2
+ import { exists } from "../../util/exists.ts";
1
3
  import type { Assets } from "../assets.ts";
2
4
  import type { Bindings } from "../bindings.ts";
3
5
  import { Vite, type ViteProps } from "../vite/vite.ts";
@@ -14,6 +16,11 @@ export async function TanStackStart<B extends Bindings>(
14
16
  id: string,
15
17
  props?: Partial<TanStackStartProps<B>>,
16
18
  ): Promise<TanStackStart<B>> {
19
+ const main =
20
+ props?.wrangler?.main ??
21
+ ((await exists(path.resolve(props?.cwd ?? process.cwd(), "src/server.ts")))
22
+ ? "src/server.ts"
23
+ : undefined);
17
24
  return await Vite(id, {
18
25
  entrypoint: "dist/server/index.js",
19
26
  assets: "dist/client",
@@ -23,9 +30,10 @@ export async function TanStackStart<B extends Bindings>(
23
30
  ...props,
24
31
  wrangler: {
25
32
  ...props?.wrangler,
33
+ main,
26
34
  transform: async (spec) => {
27
35
  const transformed = (await props?.wrangler?.transform?.(spec)) ?? spec;
28
- if (!props?.wrangler?.main) {
36
+ if (!main) {
29
37
  transformed.main = "@tanstack/react-start/server-entry";
30
38
  }
31
39
  return transformed;
@@ -20,17 +20,31 @@ const alchemy = (config?: PluginConfig): PluginOption => {
20
20
  if (typeof persistState === "object" && persistState.path.endsWith("v3")) {
21
21
  persistState.path = path.dirname(persistState.path);
22
22
  }
23
- return cloudflare({
24
- ...config,
25
- configPath: validateConfigPath(
26
- // config path doesn't need to be in the root, it can be in the app dir
27
- config?.configPath ?? getDefaultConfigPath(),
28
- ),
29
- persistState,
30
- experimental: config?.experimental ?? {
31
- remoteBindings: true,
23
+ return [
24
+ cloudflare({
25
+ ...config,
26
+ configPath: validateConfigPath(
27
+ // config path doesn't need to be in the root, it can be in the app dir
28
+ config?.configPath ?? getDefaultConfigPath(),
29
+ ),
30
+ persistState,
31
+ experimental: config?.experimental ?? {
32
+ remoteBindings: true,
33
+ },
34
+ }),
35
+ {
36
+ name: "alchemy-supress-watch",
37
+ config() {
38
+ return {
39
+ server: {
40
+ watch: {
41
+ ignored: ["**/.alchemy/**"],
42
+ },
43
+ },
44
+ };
45
+ },
32
46
  },
33
- }) as PluginOption;
47
+ ] as PluginOption;
34
48
  };
35
49
 
36
50
  export default alchemy;
@@ -43,6 +43,13 @@ export interface BranchProps extends PlanetScaleProps {
43
43
  */
44
44
  adopt?: boolean;
45
45
 
46
+ /**
47
+ * Whether to delete the branch when the resource is destroyed.
48
+ * When false, the branch will only be removed from the state but not deleted via API.
49
+ * @default true
50
+ */
51
+ delete?: boolean;
52
+
46
53
  /**
47
54
  * The parent branch name or Branch object
48
55
  * @default "main"
@@ -179,6 +186,7 @@ export const Branch = Resource(
179
186
  (typeof props.database === "string"
180
187
  ? props.database
181
188
  : props.database.name);
189
+ const shouldDelete = props.delete ?? false;
182
190
 
183
191
  if (!organization) {
184
192
  throw new Error(
@@ -192,7 +200,7 @@ export const Branch = Resource(
192
200
  }
193
201
 
194
202
  if (this.phase === "delete") {
195
- if (this.output?.name) {
203
+ if (shouldDelete && this.output?.name) {
196
204
  const response = await api.deleteBranch({
197
205
  path: {
198
206
  organization,
@@ -28,6 +28,13 @@ interface BaseDatabaseProps extends PlanetScaleProps {
28
28
  */
29
29
  adopt?: boolean;
30
30
 
31
+ /**
32
+ * Whether to delete the database when the resource is destroyed.
33
+ * When false, the database will only be removed from the state but not deleted via API.
34
+ * @default true
35
+ */
36
+ delete?: boolean;
37
+
31
38
  /**
32
39
  * The region where the database will be created (create only)
33
40
  */
@@ -227,6 +234,7 @@ export const Database = Resource(
227
234
  "PlanetScale organization is required. Please set the `organization` property or the `PLANETSCALE_ORGANIZATION` environment variable.",
228
235
  );
229
236
  }
237
+ const shouldDelete = props.delete ?? false;
230
238
 
231
239
  if (this.phase === "update" && this.output.name !== databaseName) {
232
240
  await api.updateDatabaseSettings({
@@ -239,7 +247,7 @@ export const Database = Resource(
239
247
  }
240
248
 
241
249
  if (this.phase === "delete") {
242
- if (this.output?.name) {
250
+ if (shouldDelete && this.output?.name) {
243
251
  const response = await api.deleteDatabase({
244
252
  path: {
245
253
  organization,
@@ -58,6 +58,13 @@ export interface PasswordProps extends PlanetScaleProps {
58
58
  * The CIDRs of the password
59
59
  */
60
60
  cidrs?: string[];
61
+
62
+ /**
63
+ * Whether to delete the password when the resource is destroyed.
64
+ * When false, the password will only be removed from the state but not deleted via API.
65
+ * @default true
66
+ */
67
+ delete?: boolean;
61
68
  }
62
69
 
63
70
  /**
@@ -293,6 +300,7 @@ export const Password = Resource(
293
300
  typeof props.branch === "string"
294
301
  ? props.branch
295
302
  : (props.branch?.name ?? "main");
303
+ const shouldDelete = props.delete ?? false;
296
304
  if (!organization) {
297
305
  throw new Error(
298
306
  "PlanetScale organization is required. Please set the `organization` property or the `PLANETSCALE_ORGANIZATION` environment variable.",
@@ -300,7 +308,7 @@ export const Password = Resource(
300
308
  }
301
309
 
302
310
  if (this.phase === "delete") {
303
- if (this.output?.id) {
311
+ if (shouldDelete && this.output?.id) {
304
312
  const res = await api.deletePassword({
305
313
  path: {
306
314
  organization,
@@ -44,6 +44,13 @@ export interface RoleProps extends PlanetScaleProps {
44
44
  * You can also inherit from another Role resource.
45
45
  */
46
46
  inheritedRoles: InheritedRole[] | Role;
47
+
48
+ /**
49
+ * Whether to delete the role when the resource is destroyed.
50
+ * When false, the role will only be removed from the state but not deleted via API.
51
+ * @default true
52
+ */
53
+ delete?: boolean;
47
54
  }
48
55
 
49
56
  /**
@@ -189,10 +196,11 @@ export const Role = Resource(
189
196
  const inheritedRoles = Array.isArray(props.inheritedRoles)
190
197
  ? props.inheritedRoles
191
198
  : props.inheritedRoles.inheritedRoles;
199
+ const shouldDelete = props.delete ?? false;
192
200
 
193
201
  switch (this.phase) {
194
202
  case "delete": {
195
- if (this.output?.id) {
203
+ if (shouldDelete && this.output?.id) {
196
204
  const res = await api.deleteRole({
197
205
  path: {
198
206
  organization,
@@ -0,0 +1,27 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ import {
4
+ type ClientOptions,
5
+ type Config,
6
+ createClient,
7
+ createConfig,
8
+ } from "../../util/api/client/index.ts";
9
+ import type { ClientOptions as ClientOptions2 } from "./types.gen.ts";
10
+
11
+ /**
12
+ * The `createClientConfig()` function will be called on client initialization
13
+ * and the returned object will become the client's initial configuration.
14
+ *
15
+ * You may want to initialize your client this way instead of calling
16
+ * `setConfig()`. This is useful for example if you're using Next.js
17
+ * to ensure your client always has the correct values.
18
+ */
19
+ export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (
20
+ override?: Config<ClientOptions & T>,
21
+ ) => Config<Required<ClientOptions> & T>;
22
+
23
+ export const client = createClient(
24
+ createConfig<ClientOptions2>({
25
+ throwOnError: true,
26
+ }),
27
+ );