alchemy 0.73.0 → 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.
- package/bin/alchemy.js +3326 -4424
- package/bin/alchemy.ts +2 -0
- package/bin/commands/configure.ts +4 -1
- package/bin/commands/util.ts +510 -0
- package/bin/services/execute-alchemy.ts +2 -1
- package/bin/trpc.ts +22 -16
- package/lib/cloudflare/bound.d.ts +1 -1
- package/lib/cloudflare/bound.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +6 -14
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
- package/lib/cloudflare/miniflare/remote-binding-proxy.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/remote-binding-proxy.js +12 -4
- package/lib/cloudflare/miniflare/remote-binding-proxy.js.map +1 -1
- package/lib/cloudflare/tanstack-start/tanstack-start.d.ts.map +1 -1
- package/lib/cloudflare/tanstack-start/tanstack-start.js +8 -1
- package/lib/cloudflare/tanstack-start/tanstack-start.js.map +1 -1
- package/lib/cloudflare/vite/plugin.d.ts.map +1 -1
- package/lib/cloudflare/vite/plugin.js +23 -9
- package/lib/cloudflare/vite/plugin.js.map +1 -1
- package/lib/planetscale/branch.d.ts +6 -0
- package/lib/planetscale/branch.d.ts.map +1 -1
- package/lib/planetscale/branch.js +2 -1
- package/lib/planetscale/branch.js.map +1 -1
- package/lib/planetscale/database.d.ts +6 -0
- package/lib/planetscale/database.d.ts.map +1 -1
- package/lib/planetscale/database.js +2 -1
- package/lib/planetscale/database.js.map +1 -1
- package/lib/planetscale/password.d.ts +6 -0
- package/lib/planetscale/password.d.ts.map +1 -1
- package/lib/planetscale/password.js +2 -1
- package/lib/planetscale/password.js.map +1 -1
- package/lib/planetscale/role.d.ts +6 -0
- package/lib/planetscale/role.d.ts.map +1 -1
- package/lib/planetscale/role.js +2 -1
- package/lib/planetscale/role.js.map +1 -1
- package/lib/prisma-postgres/api/client.gen.d.ts +13 -0
- package/lib/prisma-postgres/api/client.gen.d.ts.map +1 -0
- package/lib/prisma-postgres/api/client.gen.js +6 -0
- package/lib/prisma-postgres/api/client.gen.js.map +1 -0
- package/lib/prisma-postgres/api/sdk.gen.d.ts +120 -0
- package/lib/prisma-postgres/api/sdk.gen.d.ts.map +1 -0
- package/lib/prisma-postgres/api/sdk.gen.js +219 -0
- package/lib/prisma-postgres/api/sdk.gen.js.map +1 -0
- package/lib/prisma-postgres/api/types.gen.d.ts +957 -0
- package/lib/prisma-postgres/api/types.gen.d.ts.map +1 -0
- package/lib/prisma-postgres/api/types.gen.js +2 -0
- package/lib/prisma-postgres/api/types.gen.js.map +1 -0
- package/lib/prisma-postgres/api.d.ts +29 -0
- package/lib/prisma-postgres/api.d.ts.map +1 -0
- package/lib/prisma-postgres/api.js +49 -0
- package/lib/prisma-postgres/api.js.map +1 -0
- package/lib/prisma-postgres/connection.d.ts +87 -0
- package/lib/prisma-postgres/connection.d.ts.map +1 -0
- package/lib/prisma-postgres/connection.js +73 -0
- package/lib/prisma-postgres/connection.js.map +1 -0
- package/lib/prisma-postgres/database.d.ts +104 -0
- package/lib/prisma-postgres/database.d.ts.map +1 -0
- package/lib/prisma-postgres/database.js +88 -0
- package/lib/prisma-postgres/database.js.map +1 -0
- package/lib/prisma-postgres/index.d.ts +5 -0
- package/lib/prisma-postgres/index.d.ts.map +1 -0
- package/lib/prisma-postgres/index.js +5 -0
- package/lib/prisma-postgres/index.js.map +1 -0
- package/lib/prisma-postgres/project.d.ts +69 -0
- package/lib/prisma-postgres/project.d.ts.map +1 -0
- package/lib/prisma-postgres/project.js +62 -0
- package/lib/prisma-postgres/project.js.map +1 -0
- package/lib/prisma-postgres/workspace.d.ts +18 -0
- package/lib/prisma-postgres/workspace.d.ts.map +1 -0
- package/lib/prisma-postgres/workspace.js +21 -0
- package/lib/prisma-postgres/workspace.js.map +1 -0
- package/lib/util/http.d.ts +5 -2
- package/lib/util/http.d.ts.map +1 -1
- package/lib/util/http.js +71 -26
- package/lib/util/http.js.map +1 -1
- package/package.json +9 -1
- package/src/cloudflare/bound.ts +3 -1
- package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +10 -13
- package/src/cloudflare/miniflare/remote-binding-proxy.ts +12 -4
- package/src/cloudflare/tanstack-start/tanstack-start.ts +9 -1
- package/src/cloudflare/vite/plugin.ts +24 -10
- package/src/planetscale/branch.ts +9 -1
- package/src/planetscale/database.ts +9 -1
- package/src/planetscale/password.ts +9 -1
- package/src/planetscale/role.ts +9 -1
- package/src/prisma-postgres/api/client.gen.ts +27 -0
- package/src/prisma-postgres/api/sdk.gen.ts +437 -0
- package/src/prisma-postgres/api/types.gen.ts +1096 -0
- package/src/prisma-postgres/api.ts +79 -0
- package/src/prisma-postgres/connection.ts +154 -0
- package/src/prisma-postgres/database.ts +178 -0
- package/src/prisma-postgres/index.ts +4 -0
- package/src/prisma-postgres/project.ts +131 -0
- package/src/prisma-postgres/workspace.ts +27 -0
- package/src/util/http.ts +79 -33
- package/workers/cloudflare-state-store.js +1 -1
- package/workers/tunnel-proxy.js +1 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Secret } from "../secret.ts";
|
|
2
|
+
import { createClient } from "../util/api/client/client.gen.ts";
|
|
3
|
+
import type { ClientOptions } from "../util/api/client/types.gen.ts";
|
|
4
|
+
import { createConfig } from "../util/api/client/utils.gen.ts";
|
|
5
|
+
import { PrismaClient } from "./api/sdk.gen.ts";
|
|
6
|
+
|
|
7
|
+
export interface PrismaApiOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The service token to use for the API
|
|
10
|
+
*/
|
|
11
|
+
serviceToken?: Secret<string>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class PrismaApi extends Error {
|
|
15
|
+
status: number;
|
|
16
|
+
method: string;
|
|
17
|
+
url: string;
|
|
18
|
+
code: string;
|
|
19
|
+
|
|
20
|
+
constructor(props: {
|
|
21
|
+
error: {
|
|
22
|
+
status?: number;
|
|
23
|
+
error?: string;
|
|
24
|
+
};
|
|
25
|
+
request: Request;
|
|
26
|
+
response: Response;
|
|
27
|
+
}) {
|
|
28
|
+
const { status, error } = props.error;
|
|
29
|
+
super(
|
|
30
|
+
`A request to the Prisma API failed (${props.response.status}): ${error}`,
|
|
31
|
+
);
|
|
32
|
+
this.status = props.response.status;
|
|
33
|
+
this.method = props.request.method;
|
|
34
|
+
this.url = props.request.url;
|
|
35
|
+
this.code = status?.toString() ?? "";
|
|
36
|
+
Object.assign(this, props.error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Create a PrismaApi instance with environment variable fallback
|
|
42
|
+
* @param options API options
|
|
43
|
+
* @returns PrismaApi instance
|
|
44
|
+
*/
|
|
45
|
+
export function createPrismaApi(
|
|
46
|
+
options: Partial<PrismaApiOptions> = {},
|
|
47
|
+
): PrismaClient {
|
|
48
|
+
const serviceToken =
|
|
49
|
+
options.serviceToken?.unencrypted ?? process.env.PRISMA_SERVICE_TOKEN;
|
|
50
|
+
if (!serviceToken) {
|
|
51
|
+
throw new Error("PRISMA_SERVICE_TOKEN is not set");
|
|
52
|
+
}
|
|
53
|
+
const client = createClient(
|
|
54
|
+
createConfig<ClientOptions>({
|
|
55
|
+
baseUrl: "https://api.prisma.io",
|
|
56
|
+
throwOnError: true,
|
|
57
|
+
headers: {
|
|
58
|
+
Authorization: `Bearer ${serviceToken}`,
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
client.interceptors.error.use((error, response, request, options) => {
|
|
64
|
+
if (options.throwOnError !== false) {
|
|
65
|
+
throw new PrismaApi({
|
|
66
|
+
error: error as {
|
|
67
|
+
status?: number;
|
|
68
|
+
error?: string;
|
|
69
|
+
},
|
|
70
|
+
request,
|
|
71
|
+
response,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return new PrismaClient({
|
|
77
|
+
client,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type { Context } from "../context.ts";
|
|
2
|
+
import { Resource } from "../resource.ts";
|
|
3
|
+
import { secret, type Secret } from "../secret.ts";
|
|
4
|
+
import { createPrismaApi } from "./api.ts";
|
|
5
|
+
import type { Database } from "./database.ts";
|
|
6
|
+
|
|
7
|
+
export interface ConnectionProps {
|
|
8
|
+
/**
|
|
9
|
+
* Database (id or resource) the connection belongs to
|
|
10
|
+
*/
|
|
11
|
+
database: Database | string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The name of the connection
|
|
15
|
+
*/
|
|
16
|
+
name?: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The service token to use for the API
|
|
20
|
+
*/
|
|
21
|
+
serviceToken?: Secret<string>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface Connection {
|
|
25
|
+
/**
|
|
26
|
+
* The prisma id of the connection
|
|
27
|
+
*/
|
|
28
|
+
id: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The name of the connection
|
|
32
|
+
*/
|
|
33
|
+
name: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The timestamp of the connection creation
|
|
37
|
+
*/
|
|
38
|
+
createdAt: string;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The prisma connection string (prefixed with `prisma+postgres://`)
|
|
42
|
+
*/
|
|
43
|
+
prismaConnectionString: Secret<string>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The connection string
|
|
47
|
+
*/
|
|
48
|
+
connectionString: Secret<string>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The prisma id of the database the connection belongs to
|
|
52
|
+
*/
|
|
53
|
+
database: string;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The host of the connection
|
|
57
|
+
*/
|
|
58
|
+
host: string | null;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The password of the connection
|
|
62
|
+
*/
|
|
63
|
+
password: Secret<string> | null;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The user of the connection
|
|
67
|
+
*/
|
|
68
|
+
user: string | null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Creates and manages Prisma Postgres database connections.
|
|
73
|
+
*
|
|
74
|
+
* Prisma Postgres database connections provide secure credentials
|
|
75
|
+
* and connection details for accessing your databases. Connections
|
|
76
|
+
* belong to a Prisma Postgres database.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Create a database connection for a database
|
|
80
|
+
* import { Database, Connection } from "alchemy/prisma-postgres";
|
|
81
|
+
* const project = await Project("my-project");
|
|
82
|
+
* const database = await Database("my-database", { project });
|
|
83
|
+
* const connection = await Connection("my-connection", {
|
|
84
|
+
* database: database,
|
|
85
|
+
* });
|
|
86
|
+
* console.log(`Connection String: ${connection.connectionString.unencrypted}`);
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* // Create a database connection and connect it to Cloudflare Hyperdrive
|
|
90
|
+
* import { Hyperdrive } from "alchemy/cloudflare";
|
|
91
|
+
* import { Database, Connection } from "alchemy/prisma-postgres";
|
|
92
|
+
* const project = await Project("my-project");
|
|
93
|
+
* const database = await Database("my-database", { project });
|
|
94
|
+
* const connection = await Connection("my-connection", {
|
|
95
|
+
* database: database,
|
|
96
|
+
* });
|
|
97
|
+
* const db = await Hyperdrive("prisma-postgres", {
|
|
98
|
+
* origin: connection.connectionString.unencrypted,
|
|
99
|
+
* });
|
|
100
|
+
*/
|
|
101
|
+
export const Connection = Resource(
|
|
102
|
+
"prisma::Connection",
|
|
103
|
+
async function (
|
|
104
|
+
this: Context<Connection>,
|
|
105
|
+
id: string,
|
|
106
|
+
props: ConnectionProps,
|
|
107
|
+
): Promise<Connection> {
|
|
108
|
+
const api = createPrismaApi({
|
|
109
|
+
serviceToken: props.serviceToken,
|
|
110
|
+
});
|
|
111
|
+
const name =
|
|
112
|
+
props.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
|
|
113
|
+
const database =
|
|
114
|
+
typeof props.database === "string" ? props.database : props.database.id;
|
|
115
|
+
|
|
116
|
+
if (this.phase === "delete") {
|
|
117
|
+
await api.deleteDatabaseConnectionString({
|
|
118
|
+
path: {
|
|
119
|
+
id: this.output.id,
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
return this.destroy();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (this.phase === "update") {
|
|
126
|
+
return this.replace();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const connection = await api
|
|
130
|
+
.createDatabaseConnectionString({
|
|
131
|
+
path: {
|
|
132
|
+
databaseId: database,
|
|
133
|
+
},
|
|
134
|
+
body: {
|
|
135
|
+
name,
|
|
136
|
+
},
|
|
137
|
+
})
|
|
138
|
+
.then((response) => response.data.data);
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
id: connection.id,
|
|
142
|
+
name: connection.name,
|
|
143
|
+
createdAt: connection.createdAt,
|
|
144
|
+
prismaConnectionString: secret(connection.connectionString),
|
|
145
|
+
connectionString: secret(
|
|
146
|
+
`postgres://${connection.user}:${connection.pass}@${connection.host}/${connection.database}`,
|
|
147
|
+
),
|
|
148
|
+
database: database,
|
|
149
|
+
host: connection.host,
|
|
150
|
+
password: connection.pass ? secret(connection.pass) : null,
|
|
151
|
+
user: connection.user,
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
);
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type { Context } from "../context.ts";
|
|
2
|
+
import { Resource } from "../resource.ts";
|
|
3
|
+
import type { Secret } from "../secret.ts";
|
|
4
|
+
import { createPrismaApi } from "./api.ts";
|
|
5
|
+
import type { CreateDatabaseData } from "./api/types.gen.ts";
|
|
6
|
+
import type { Project } from "./project.ts";
|
|
7
|
+
|
|
8
|
+
export interface DatabaseProps {
|
|
9
|
+
/**
|
|
10
|
+
* The name of the database
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
project: Project | string;
|
|
14
|
+
/**
|
|
15
|
+
* The region to create the database in
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
name?: string;
|
|
19
|
+
/**
|
|
20
|
+
* The project to create the database in
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
region?:
|
|
24
|
+
| "us-east-1"
|
|
25
|
+
| "us-west-1"
|
|
26
|
+
| "eu-west-3"
|
|
27
|
+
| "eu-central-1"
|
|
28
|
+
| "ap-northeast-1"
|
|
29
|
+
| "ap-southeast-1"
|
|
30
|
+
| (string & {});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Whether to delete the database if the resource is deleted
|
|
34
|
+
*
|
|
35
|
+
* @default false
|
|
36
|
+
*/
|
|
37
|
+
delete?: boolean;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The service token to use for the API
|
|
41
|
+
*/
|
|
42
|
+
serviceToken?: Secret<string>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface Database {
|
|
46
|
+
/**
|
|
47
|
+
* The prisma id of the database
|
|
48
|
+
*/
|
|
49
|
+
id: string;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The name of the database
|
|
53
|
+
*/
|
|
54
|
+
name: string;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The status of the database
|
|
58
|
+
*/
|
|
59
|
+
status: "failure" | "provisioning" | "ready" | "recovering";
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The region of the database
|
|
63
|
+
*/
|
|
64
|
+
region?: string;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The timestamp of the database creation
|
|
68
|
+
*/
|
|
69
|
+
createdAt: string;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The prisma id of the project the database belongs to
|
|
73
|
+
*/
|
|
74
|
+
project: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Creates and manages Prisma Postgres databases.
|
|
79
|
+
*
|
|
80
|
+
* Prisma Postgres databases are fully managed PostgreSQL instances
|
|
81
|
+
* that can be connected to applications. Databases belong to a
|
|
82
|
+
* Prisma Postgres project.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* // Create a database for a project
|
|
86
|
+
* import { Project, Database } from "alchemy/prisma-postgres";
|
|
87
|
+
* const project = await Project("my-app");
|
|
88
|
+
* const database = await Database("my-database", {
|
|
89
|
+
* project: project,
|
|
90
|
+
* });
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Create a database in the asia pacific region
|
|
94
|
+
* import { Project, Database } from "alchemy/prisma-postgres";
|
|
95
|
+
* const project = await Project("my-app");
|
|
96
|
+
* const database = await Database("my-database", {
|
|
97
|
+
* project: project,
|
|
98
|
+
* region: "ap-northeast-1",
|
|
99
|
+
* });
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* // Create a database and fully delete on destroy
|
|
103
|
+
* import { Project, Database } from "alchemy/prisma-postgres";
|
|
104
|
+
* const project = await Project("my-app");
|
|
105
|
+
* const database = await Database("my-database", {
|
|
106
|
+
* project: project,
|
|
107
|
+
* delete: true,
|
|
108
|
+
* });
|
|
109
|
+
*/
|
|
110
|
+
export const Database = Resource(
|
|
111
|
+
"prisma::Database",
|
|
112
|
+
async function (
|
|
113
|
+
this: Context<Database>,
|
|
114
|
+
id: string,
|
|
115
|
+
props: DatabaseProps,
|
|
116
|
+
): Promise<Database> {
|
|
117
|
+
const api = createPrismaApi({
|
|
118
|
+
serviceToken: props.serviceToken,
|
|
119
|
+
});
|
|
120
|
+
const name =
|
|
121
|
+
props.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
|
|
122
|
+
const shouldDelete = props.delete ?? false;
|
|
123
|
+
const project =
|
|
124
|
+
typeof props.project === "string" ? props.project : props.project.id;
|
|
125
|
+
|
|
126
|
+
if (this.phase === "delete") {
|
|
127
|
+
if (shouldDelete) {
|
|
128
|
+
await api.deleteDatabase({
|
|
129
|
+
path: { databaseId: this.output.id },
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return this.destroy();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (this.phase === "update") {
|
|
136
|
+
return this.replace();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const database = await api
|
|
140
|
+
.createDatabase({
|
|
141
|
+
path: {
|
|
142
|
+
projectId: project,
|
|
143
|
+
},
|
|
144
|
+
body: {
|
|
145
|
+
isDefault: false,
|
|
146
|
+
name,
|
|
147
|
+
region: props.region,
|
|
148
|
+
} as CreateDatabaseData["body"],
|
|
149
|
+
})
|
|
150
|
+
.then((response) => response.data.data);
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
id: database.id,
|
|
154
|
+
name: database.name,
|
|
155
|
+
region: database.region?.id,
|
|
156
|
+
status: database.status,
|
|
157
|
+
createdAt: database.createdAt,
|
|
158
|
+
project,
|
|
159
|
+
};
|
|
160
|
+
},
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
export async function findDatabaseByName(props: DatabaseProps) {
|
|
164
|
+
const api = createPrismaApi({
|
|
165
|
+
serviceToken: props.serviceToken,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const project =
|
|
169
|
+
typeof props.project === "string" ? props.project : props.project.id;
|
|
170
|
+
|
|
171
|
+
const databases = await api.listDatabases({
|
|
172
|
+
path: {
|
|
173
|
+
projectId: project,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
const database = databases.data.data.find((db) => db.name === props.name);
|
|
177
|
+
return database;
|
|
178
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { Context } from "../context.ts";
|
|
2
|
+
import { Resource } from "../resource.ts";
|
|
3
|
+
import type { Secret } from "../secret.ts";
|
|
4
|
+
import { createPrismaApi } from "./api.ts";
|
|
5
|
+
|
|
6
|
+
export interface ProjectProps {
|
|
7
|
+
/**
|
|
8
|
+
* The name of the project
|
|
9
|
+
*/
|
|
10
|
+
name?: string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Whether to delete the project if the resource is deleted
|
|
14
|
+
*
|
|
15
|
+
* @default false
|
|
16
|
+
*/
|
|
17
|
+
delete?: boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The service token to use for the API
|
|
21
|
+
*/
|
|
22
|
+
serviceToken?: Secret<string>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface Project {
|
|
26
|
+
/**
|
|
27
|
+
* The prisma id of the project
|
|
28
|
+
*/
|
|
29
|
+
id: string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The name of the project
|
|
33
|
+
*/
|
|
34
|
+
name: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The timestamp of the project creation
|
|
38
|
+
*/
|
|
39
|
+
createdAt: string;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The workspace the project belongs to
|
|
43
|
+
*/
|
|
44
|
+
workspace: {
|
|
45
|
+
/**
|
|
46
|
+
* The prisma id of the workspace
|
|
47
|
+
*/
|
|
48
|
+
id: string;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The name of the workspace
|
|
52
|
+
*/
|
|
53
|
+
name: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Creates and manages Prisma Postgres projects.
|
|
59
|
+
*
|
|
60
|
+
* Prisma Postgres projects are containers for your databases and
|
|
61
|
+
* their configurations. Projects belong to a workspace and can
|
|
62
|
+
* contain multiple databases.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* // Create a database for a project
|
|
66
|
+
* import { Project, Database } from "alchemy/prisma-postgres";
|
|
67
|
+
* const project = await Project("my-app");
|
|
68
|
+
*/
|
|
69
|
+
export const Project = Resource(
|
|
70
|
+
"prisma::Project",
|
|
71
|
+
async function (
|
|
72
|
+
this: Context<Project>,
|
|
73
|
+
id: string,
|
|
74
|
+
props?: ProjectProps,
|
|
75
|
+
): Promise<Project> {
|
|
76
|
+
const api = createPrismaApi({
|
|
77
|
+
serviceToken: props?.serviceToken,
|
|
78
|
+
});
|
|
79
|
+
const name =
|
|
80
|
+
props?.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
|
|
81
|
+
const shouldDelete = props?.delete ?? false;
|
|
82
|
+
|
|
83
|
+
if (this.phase === "delete") {
|
|
84
|
+
if (shouldDelete) {
|
|
85
|
+
await api.deleteProject({
|
|
86
|
+
path: { id: this.output.id },
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return this.destroy();
|
|
90
|
+
}
|
|
91
|
+
if (this.phase === "update") {
|
|
92
|
+
return this.replace();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const project = await api
|
|
96
|
+
.createProjectWithPostgresDatabase({
|
|
97
|
+
body: {
|
|
98
|
+
createDatabase: false,
|
|
99
|
+
name,
|
|
100
|
+
//! prisma seems to not support setting the workspace on project creation?
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
.then((response) => response.data.data!);
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
id: project.id,
|
|
107
|
+
name: project.name,
|
|
108
|
+
createdAt: project.createdAt,
|
|
109
|
+
workspace: project.workspace,
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
export async function findProjectByName(props: ProjectProps) {
|
|
115
|
+
const api = createPrismaApi(props);
|
|
116
|
+
let hasMore = true;
|
|
117
|
+
let project:
|
|
118
|
+
| NonNullable<
|
|
119
|
+
Awaited<ReturnType<typeof api.listProjects>>["data"]
|
|
120
|
+
>["data"][number]
|
|
121
|
+
| undefined;
|
|
122
|
+
while (hasMore) {
|
|
123
|
+
const response = await api.listProjects();
|
|
124
|
+
project = response.data.data.find((project) => project.name === props.name);
|
|
125
|
+
if (project != null) {
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
hasMore = response.data.pagination.hasMore;
|
|
129
|
+
}
|
|
130
|
+
return project;
|
|
131
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createPrismaApi, type PrismaApiOptions } from "./api.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get a prisma workspace by id or name.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const workspace = await WorkspaceRef("alchemy-test");
|
|
8
|
+
*
|
|
9
|
+
* @param identifier The id or name of the workspace to get.
|
|
10
|
+
* @param props The api credentials to use.
|
|
11
|
+
* @returns The workspace.
|
|
12
|
+
*/
|
|
13
|
+
export async function WorkspaceRef(
|
|
14
|
+
identifier: string,
|
|
15
|
+
props?: PrismaApiOptions,
|
|
16
|
+
) {
|
|
17
|
+
const api = createPrismaApi(props);
|
|
18
|
+
|
|
19
|
+
const workspaces = await api.listWorkspaces();
|
|
20
|
+
const workspace = workspaces.data.data.find(
|
|
21
|
+
(workspace) => workspace.id === identifier || workspace.name === identifier,
|
|
22
|
+
);
|
|
23
|
+
if (!workspace) {
|
|
24
|
+
throw new Error(`Workspace with identifier ${identifier} not found`);
|
|
25
|
+
}
|
|
26
|
+
return workspace;
|
|
27
|
+
}
|