@alchemy.run/planetscale 0.0.0 → 2.0.0-beta.84
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/LICENSE +201 -0
- package/README.md +83 -4
- package/lib/AuthProvider.d.ts +64 -0
- package/lib/AuthProvider.d.ts.map +1 -0
- package/lib/AuthProvider.js +384 -0
- package/lib/AuthProvider.js.map +1 -0
- package/lib/Branch.d.ts +128 -0
- package/lib/Branch.d.ts.map +1 -0
- package/lib/Branch.js +420 -0
- package/lib/Branch.js.map +1 -0
- package/lib/Contributions.d.ts +7 -0
- package/lib/Contributions.d.ts.map +1 -0
- package/lib/Contributions.js +6 -0
- package/lib/Contributions.js.map +1 -0
- package/lib/Credentials.d.ts +33 -0
- package/lib/Credentials.d.ts.map +1 -0
- package/lib/Credentials.js +65 -0
- package/lib/Credentials.js.map +1 -0
- package/lib/Database.d.ts +138 -0
- package/lib/Database.d.ts.map +1 -0
- package/lib/Database.js +1 -0
- package/lib/Database.js.map +1 -0
- package/lib/MySQL/MySQLBranch.d.ts +87 -0
- package/lib/MySQL/MySQLBranch.d.ts.map +1 -0
- package/lib/MySQL/MySQLBranch.js +15 -0
- package/lib/MySQL/MySQLBranch.js.map +1 -0
- package/lib/MySQL/MySQLClusterSize.d.ts +32 -0
- package/lib/MySQL/MySQLClusterSize.d.ts.map +1 -0
- package/lib/MySQL/MySQLClusterSize.js +111 -0
- package/lib/MySQL/MySQLClusterSize.js.map +1 -0
- package/lib/MySQL/MySQLDatabase.d.ts +141 -0
- package/lib/MySQL/MySQLDatabase.d.ts.map +1 -0
- package/lib/MySQL/MySQLDatabase.js +294 -0
- package/lib/MySQL/MySQLDatabase.js.map +1 -0
- package/lib/MySQL/MySQLMigrations.d.ts +24 -0
- package/lib/MySQL/MySQLMigrations.d.ts.map +1 -0
- package/lib/MySQL/MySQLMigrations.js +106 -0
- package/lib/MySQL/MySQLMigrations.js.map +1 -0
- package/lib/MySQL/MySQLOrigin.d.ts +15 -0
- package/lib/MySQL/MySQLOrigin.d.ts.map +1 -0
- package/lib/MySQL/MySQLOrigin.js +2 -0
- package/lib/MySQL/MySQLOrigin.js.map +1 -0
- package/lib/MySQL/MySQLPassword.d.ts +116 -0
- package/lib/MySQL/MySQLPassword.d.ts.map +1 -0
- package/lib/MySQL/MySQLPassword.js +212 -0
- package/lib/MySQL/MySQLPassword.js.map +1 -0
- package/lib/MySQL/index.d.ts +6 -0
- package/lib/MySQL/index.d.ts.map +1 -0
- package/lib/MySQL/index.js +6 -0
- package/lib/MySQL/index.js.map +1 -0
- package/lib/OAuthClient.d.ts +32 -0
- package/lib/OAuthClient.d.ts.map +1 -0
- package/lib/OAuthClient.js +52 -0
- package/lib/OAuthClient.js.map +1 -0
- package/lib/Postgres/PostgresBranch.d.ts +75 -0
- package/lib/Postgres/PostgresBranch.d.ts.map +1 -0
- package/lib/Postgres/PostgresBranch.js +15 -0
- package/lib/Postgres/PostgresBranch.js.map +1 -0
- package/lib/Postgres/PostgresClusterSize.d.ts +77 -0
- package/lib/Postgres/PostgresClusterSize.d.ts.map +1 -0
- package/lib/Postgres/PostgresClusterSize.js +89 -0
- package/lib/Postgres/PostgresClusterSize.js.map +1 -0
- package/lib/Postgres/PostgresDatabase.d.ts +95 -0
- package/lib/Postgres/PostgresDatabase.d.ts.map +1 -0
- package/lib/Postgres/PostgresDatabase.js +294 -0
- package/lib/Postgres/PostgresDatabase.js.map +1 -0
- package/lib/Postgres/PostgresDefaultRole.d.ts +94 -0
- package/lib/Postgres/PostgresDefaultRole.d.ts.map +1 -0
- package/lib/Postgres/PostgresDefaultRole.js +187 -0
- package/lib/Postgres/PostgresDefaultRole.js.map +1 -0
- package/lib/Postgres/PostgresMigrations.d.ts +24 -0
- package/lib/Postgres/PostgresMigrations.d.ts.map +1 -0
- package/lib/Postgres/PostgresMigrations.js +116 -0
- package/lib/Postgres/PostgresMigrations.js.map +1 -0
- package/lib/Postgres/PostgresOrigin.d.ts +15 -0
- package/lib/Postgres/PostgresOrigin.d.ts.map +1 -0
- package/lib/Postgres/PostgresOrigin.js +2 -0
- package/lib/Postgres/PostgresOrigin.js.map +1 -0
- package/lib/Postgres/PostgresRole.d.ts +142 -0
- package/lib/Postgres/PostgresRole.d.ts.map +1 -0
- package/lib/Postgres/PostgresRole.js +268 -0
- package/lib/Postgres/PostgresRole.js.map +1 -0
- package/lib/Postgres/index.d.ts +7 -0
- package/lib/Postgres/index.d.ts.map +1 -0
- package/lib/Postgres/index.js +7 -0
- package/lib/Postgres/index.js.map +1 -0
- package/lib/Providers.d.ts +24 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +40 -0
- package/lib/Providers.js.map +1 -0
- package/lib/Util.d.ts +93 -0
- package/lib/Util.d.ts.map +1 -0
- package/lib/Util.js +135 -0
- package/lib/Util.js.map +1 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +9 -0
- package/lib/index.js.map +1 -0
- package/package.json +79 -3
- package/src/AuthProvider.ts +571 -0
- package/src/Branch.ts +657 -0
- package/src/Contributions.ts +9 -0
- package/src/Credentials.ts +116 -0
- package/src/Database.ts +152 -0
- package/src/MySQL/MySQLBranch.ts +109 -0
- package/src/MySQL/MySQLClusterSize.ts +185 -0
- package/src/MySQL/MySQLDatabase.ts +521 -0
- package/src/MySQL/MySQLMigrations.ts +182 -0
- package/src/MySQL/MySQLOrigin.ts +15 -0
- package/src/MySQL/MySQLPassword.ts +428 -0
- package/src/MySQL/index.ts +5 -0
- package/src/OAuthClient.ts +59 -0
- package/src/Postgres/PostgresBranch.ts +97 -0
- package/src/Postgres/PostgresClusterSize.ts +262 -0
- package/src/Postgres/PostgresDatabase.ts +469 -0
- package/src/Postgres/PostgresDefaultRole.ts +340 -0
- package/src/Postgres/PostgresMigrations.ts +193 -0
- package/src/Postgres/PostgresOrigin.ts +15 -0
- package/src/Postgres/PostgresRole.ts +547 -0
- package/src/Postgres/index.ts +6 -0
- package/src/Providers.ts +67 -0
- package/src/Util.ts +205 -0
- package/src/index.ts +14 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import * as planetscale from "@distilled.cloud/planetscale";
|
|
2
|
+
import { Credentials } from "@distilled.cloud/planetscale/Credentials";
|
|
3
|
+
import { isResolved } from "alchemy/Diff";
|
|
4
|
+
import * as Provider from "alchemy/Provider";
|
|
5
|
+
import { Resource } from "alchemy/Resource";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import * as Redacted from "effect/Redacted";
|
|
8
|
+
import * as Stream from "effect/Stream";
|
|
9
|
+
import { PlanetscaleConflict, waitForBranchReady } from "../Util.js";
|
|
10
|
+
/** @resource */
|
|
11
|
+
export const PostgresDefaultRole = Resource("Planetscale.PostgresDefaultRole");
|
|
12
|
+
export const PostgresDefaultRoleProvider = () => Provider.succeed(PostgresDefaultRole, {
|
|
13
|
+
stables: ["id"],
|
|
14
|
+
diff: Effect.fn(function* ({ news, olds = {} }) {
|
|
15
|
+
if (!isResolved(news))
|
|
16
|
+
return undefined;
|
|
17
|
+
const newDb = resolveDatabaseName(news.database);
|
|
18
|
+
const oldDb = olds.database ? resolveDatabaseName(olds.database) : undefined;
|
|
19
|
+
if (oldDb && newDb !== oldDb) {
|
|
20
|
+
return { action: "replace" };
|
|
21
|
+
}
|
|
22
|
+
const newBranch = resolveBranchName(news.branch);
|
|
23
|
+
const oldBranch = resolveBranchName(olds.branch);
|
|
24
|
+
if (newBranch !== oldBranch) {
|
|
25
|
+
return { action: "replace" };
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}),
|
|
29
|
+
read: Effect.fn(function* ({ output }) {
|
|
30
|
+
// Adoption (no cached output) is impossible without destroying
|
|
31
|
+
// existing credentials. The engine routes adoption through
|
|
32
|
+
// `read`, but here we always defer to reconcile so the
|
|
33
|
+
// `forceReset` props flag remains the user-facing switch for
|
|
34
|
+
// takeover. Returning undefined makes the engine treat the
|
|
35
|
+
// resource as greenfield; reconcile then observes live state
|
|
36
|
+
// and either fails (no forceReset) or resets (forceReset).
|
|
37
|
+
if (!output)
|
|
38
|
+
return undefined;
|
|
39
|
+
// Refresh — verify the default role still exists and re-emit
|
|
40
|
+
// the persisted output (with plaintext intact). If gone,
|
|
41
|
+
// return undefined so the engine routes through reconcile,
|
|
42
|
+
// which will recreate via reset.
|
|
43
|
+
return yield* planetscale
|
|
44
|
+
.getDefaultRole({
|
|
45
|
+
organization: output.organization,
|
|
46
|
+
database: output.database,
|
|
47
|
+
branch: output.branch,
|
|
48
|
+
})
|
|
49
|
+
.pipe(Effect.map((role) => ({
|
|
50
|
+
...output,
|
|
51
|
+
privateHost: role.private_access_host_url,
|
|
52
|
+
privateConnectionServiceName: role.private_connection_service_name,
|
|
53
|
+
})), Effect.catchTag("NotFound", () => Effect.succeed(undefined)));
|
|
54
|
+
}),
|
|
55
|
+
reconcile: Effect.fn(function* ({ news, output }) {
|
|
56
|
+
const { organization: envOrg } = yield* yield* Credentials;
|
|
57
|
+
const organization = resolveDatabaseOrg(news.database) ?? envOrg;
|
|
58
|
+
const databaseName = resolveDatabaseName(news.database);
|
|
59
|
+
const branchName = resolveBranchName(news.branch);
|
|
60
|
+
// 1. Observe — the default role is the singleton for this
|
|
61
|
+
// (database, branch); we key on those rather than an id.
|
|
62
|
+
// Observation runs unconditionally so the adoption guard
|
|
63
|
+
// below fires on greenfield deploys against branches that
|
|
64
|
+
// already have a default role (otherwise we would silently
|
|
65
|
+
// `resetDefault` and destroy their credentials).
|
|
66
|
+
const observed = yield* planetscale
|
|
67
|
+
.getDefaultRole({
|
|
68
|
+
organization,
|
|
69
|
+
database: databaseName,
|
|
70
|
+
branch: branchName,
|
|
71
|
+
})
|
|
72
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined)));
|
|
73
|
+
// 2. Sync (no-op) — we own the role and it still exists in the
|
|
74
|
+
// cloud. Default roles have nothing mutable in place: their
|
|
75
|
+
// plaintext password isn't retrievable, so we retain the cached
|
|
76
|
+
// credentials while refreshing the private connection details.
|
|
77
|
+
// diff() forces a replace when database/branch change.
|
|
78
|
+
if (output && observed) {
|
|
79
|
+
return {
|
|
80
|
+
...output,
|
|
81
|
+
privateHost: observed.private_access_host_url,
|
|
82
|
+
privateConnectionServiceName: observed.private_connection_service_name,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// 3. Adoption guard — observed exists but we have no prior
|
|
86
|
+
// output (greenfield against a pre-existing default role).
|
|
87
|
+
// Taking over requires a reset (which destroys the existing
|
|
88
|
+
// password), so gate on an explicit forceReset opt-in.
|
|
89
|
+
if (observed && !news.forceReset) {
|
|
90
|
+
return yield* new PlanetscaleConflict({
|
|
91
|
+
message: `Default role already exists for database "${databaseName}" branch "${branchName}". Use forceReset: true to reset.`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// 4. Ensure — (re)create the default role. This branch runs
|
|
95
|
+
// for greenfield (no output, no observed), drift recovery
|
|
96
|
+
// (output cached but cloud state gone), and authorised
|
|
97
|
+
// adoption (observed present + forceReset).
|
|
98
|
+
yield* waitForBranchReady(organization, databaseName, branchName);
|
|
99
|
+
const data = yield* planetscale.resetDefaultRole({
|
|
100
|
+
organization,
|
|
101
|
+
database: databaseName,
|
|
102
|
+
branch: branchName,
|
|
103
|
+
});
|
|
104
|
+
if (!data.password) {
|
|
105
|
+
return yield* Effect.die(`Planetscale did not return a password for Default Role.`);
|
|
106
|
+
}
|
|
107
|
+
const password = Redacted.isRedacted(data.password)
|
|
108
|
+
? Redacted.value(data.password)
|
|
109
|
+
: data.password;
|
|
110
|
+
const connectionUrl = `postgresql://${data.username}:${password}@${data.access_host_url}:5432/${data.database_name}?sslmode=verify-full`;
|
|
111
|
+
const connectionUrlPooled = `postgresql://${data.username}:${password}@${data.access_host_url}:6432/${data.database_name}?sslmode=verify-full`;
|
|
112
|
+
return {
|
|
113
|
+
id: data.id,
|
|
114
|
+
name: data.name,
|
|
115
|
+
expiresAt: data.expires_at,
|
|
116
|
+
host: data.access_host_url,
|
|
117
|
+
username: data.username,
|
|
118
|
+
password: Redacted.make(password),
|
|
119
|
+
ttl: data.ttl,
|
|
120
|
+
databaseName: data.database_name,
|
|
121
|
+
connectionUrl: Redacted.make(connectionUrl),
|
|
122
|
+
connectionUrlPooled: Redacted.make(connectionUrlPooled),
|
|
123
|
+
privateHost: data.private_access_host_url,
|
|
124
|
+
privateConnectionServiceName: data.private_connection_service_name,
|
|
125
|
+
inheritedRoles: data.inherited_roles,
|
|
126
|
+
organization,
|
|
127
|
+
database: databaseName,
|
|
128
|
+
branch: branchName,
|
|
129
|
+
};
|
|
130
|
+
}),
|
|
131
|
+
delete: Effect.fn(function* ({ output }) {
|
|
132
|
+
// No delete endpoint — reset to invalidate existing credentials.
|
|
133
|
+
yield* planetscale
|
|
134
|
+
.resetDefaultRole({
|
|
135
|
+
organization: output.organization,
|
|
136
|
+
database: output.database,
|
|
137
|
+
branch: output.branch,
|
|
138
|
+
})
|
|
139
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.void));
|
|
140
|
+
}),
|
|
141
|
+
list: Effect.fn(function* () {
|
|
142
|
+
const { organization } = yield* yield* Credentials;
|
|
143
|
+
const roles = yield* planetscale.listDatabases.pages({ organization }).pipe(Stream.map((page) => page.data.filter((db) => db.kind === "postgresql")), Stream.flattenIterable, Stream.flatMap((db) => planetscale.listBranches.pages({ organization, database: db.name }).pipe(Stream.map((page) => page.data.filter((branch) => branch.kind === "postgresql")), Stream.flattenIterable, Stream.catchTag("NotFound", () => Stream.succeed({ name: db.default_branch ?? "main" })), Stream.flatMap((branch) => planetscale.listRoles
|
|
144
|
+
.pages({
|
|
145
|
+
organization,
|
|
146
|
+
database: db.name,
|
|
147
|
+
branch: branch.name,
|
|
148
|
+
})
|
|
149
|
+
.pipe(Stream.map((page) => page.data
|
|
150
|
+
.filter((role) => role.default)
|
|
151
|
+
.map((role) => ({
|
|
152
|
+
id: role.id,
|
|
153
|
+
name: role.name,
|
|
154
|
+
expiresAt: role.expires_at,
|
|
155
|
+
host: role.access_host_url,
|
|
156
|
+
username: role.username,
|
|
157
|
+
password: Redacted.make(""),
|
|
158
|
+
ttl: role.ttl,
|
|
159
|
+
databaseName: role.database_name,
|
|
160
|
+
connectionUrl: Redacted.make(""),
|
|
161
|
+
connectionUrlPooled: Redacted.make(""),
|
|
162
|
+
privateHost: role.private_access_host_url,
|
|
163
|
+
privateConnectionServiceName: role.private_connection_service_name,
|
|
164
|
+
inheritedRoles: role.inherited_roles,
|
|
165
|
+
organization,
|
|
166
|
+
database: db.name,
|
|
167
|
+
branch: branch.name,
|
|
168
|
+
}))), Stream.flattenIterable, Stream.catchTags({
|
|
169
|
+
NotFound: () => Stream.empty,
|
|
170
|
+
Forbidden: () => Stream.empty,
|
|
171
|
+
})), { concurrency: 10 })), { concurrency: 10 }), Stream.runCollect);
|
|
172
|
+
return Array.from(roles);
|
|
173
|
+
}),
|
|
174
|
+
});
|
|
175
|
+
const resolveDatabaseName = (database) => {
|
|
176
|
+
const ref = database;
|
|
177
|
+
return typeof ref === "string" ? ref : ref.name;
|
|
178
|
+
};
|
|
179
|
+
const resolveDatabaseOrg = (database) => {
|
|
180
|
+
const ref = database;
|
|
181
|
+
return typeof ref === "string" ? undefined : ref.organization;
|
|
182
|
+
};
|
|
183
|
+
const resolveBranchName = (branch) => {
|
|
184
|
+
const ref = branch;
|
|
185
|
+
return !ref ? "main" : typeof ref === "string" ? ref : ref.name;
|
|
186
|
+
};
|
|
187
|
+
//# sourceMappingURL=PostgresDefaultRole.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresDefaultRole.js","sourceRoot":"","sources":["../../src/Postgres/PostgresDefaultRole.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type NormalizedMigrationsInput, type StampedMigrationsState } from "@alchemy.run/sql/Migrations";
|
|
2
|
+
import * as ps from "@distilled.cloud/planetscale";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
declare const PostgresMigrationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
5
|
+
readonly _tag: "Planetscale::PostgresMigrationError";
|
|
6
|
+
} & Readonly<A>;
|
|
7
|
+
export declare class PostgresMigrationError extends PostgresMigrationError_base<{
|
|
8
|
+
message: string;
|
|
9
|
+
cause?: unknown;
|
|
10
|
+
}> {
|
|
11
|
+
}
|
|
12
|
+
export interface PostgresMigrationTarget {
|
|
13
|
+
organization: string;
|
|
14
|
+
database: string;
|
|
15
|
+
branch: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* PlanetScale Postgres's migration adaptation is exactly this: the shared
|
|
19
|
+
* pipeline with a temp-role-scoped pg client as its executor.
|
|
20
|
+
*/
|
|
21
|
+
export declare const runPostgresMigrations: (target: PostgresMigrationTarget, input: NormalizedMigrationsInput, stamped: StampedMigrationsState) => Effect.Effect<import("@alchemy.run/sql/Migrations").MigrationRun, import("@alchemy.run/sql/Migrations").DrizzleV0LayoutError | PostgresMigrationError | ps.CreateRoleError | import("@alchemy.run/sql/Migrations").MigrationApplyError, import("effect/FileSystem").FileSystem | import("effect/Path").Path | ps.PlanetScaleOpContext>;
|
|
22
|
+
export declare const runPostgresImports: (target: PostgresMigrationTarget, importFiles: ReadonlyArray<string>, rootDir: string, previous: Record<string, string>) => Effect.Effect<Record<string, string>, import("effect/PlatformError").PlatformError | PostgresMigrationError | ps.CreateRoleError, import("effect/FileSystem").FileSystem | import("effect/Path").Path | ps.PlanetScaleOpContext>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=PostgresMigrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresMigrations.d.ts","sourceRoot":"","sources":["../../src/Postgres/PostgresMigrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC5B,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAEnD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;;;;AAiBxC,qBAAa,sBAAuB,SAAQ,4BAE1C;IACA,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;CAAG;AAEL,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,WACxB,uBAAuB,SACxB,yBAAyB,WACvB,sBAAsB,2UAO7B,CAAC;AAEL,eAAO,MAAM,kBAAkB,WACrB,uBAAuB,eAClB,aAAa,CAAC,MAAM,CAAC,WACzB,MAAM,YACL,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,qOAkB9B,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { makePgMigrationExecutor, runMigrations, } from "@alchemy.run/sql/Migrations";
|
|
2
|
+
import { readSqlFile } from "@alchemy.run/sql/SqlFile";
|
|
3
|
+
import * as ps from "@distilled.cloud/planetscale";
|
|
4
|
+
import * as Data from "effect/Data";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Redacted from "effect/Redacted";
|
|
7
|
+
import * as Schedule from "effect/Schedule";
|
|
8
|
+
// `pg` is an optional peer dependency — loaded lazily so importing the
|
|
9
|
+
// Planetscale provider never requires the driver unless migrations run.
|
|
10
|
+
const importPg = () => import("pg").catch((cause) => {
|
|
11
|
+
throw new Error("Failed to load the 'pg' driver. Install the optional peer dependency 'pg' to run Planetscale Postgres migrations.", { cause });
|
|
12
|
+
});
|
|
13
|
+
const MIGRATION_ROLE_TTL_SECONDS = 600;
|
|
14
|
+
export class PostgresMigrationError extends Data.TaggedError("Planetscale::PostgresMigrationError") {
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* PlanetScale Postgres's migration adaptation is exactly this: the shared
|
|
18
|
+
* pipeline with a temp-role-scoped pg client as its executor.
|
|
19
|
+
*/
|
|
20
|
+
export const runPostgresMigrations = (target, input, stamped) => runMigrations({
|
|
21
|
+
input,
|
|
22
|
+
stamped,
|
|
23
|
+
withExecutor: (apply) => withPostgresClient(target, (client) => apply(makePgMigrationExecutor(client))),
|
|
24
|
+
});
|
|
25
|
+
export const runPostgresImports = (target, importFiles, rootDir, previous) => Effect.gen(function* () {
|
|
26
|
+
const hashes = { ...previous };
|
|
27
|
+
for (const filePath of importFiles) {
|
|
28
|
+
const file = yield* readSqlFile(rootDir, filePath);
|
|
29
|
+
if (previous[filePath] === file.hash) {
|
|
30
|
+
hashes[filePath] = file.hash;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
yield* runPostgresSql(target, file.sql);
|
|
34
|
+
hashes[filePath] = file.hash;
|
|
35
|
+
}
|
|
36
|
+
const tracked = new Set(importFiles);
|
|
37
|
+
for (const key of Object.keys(hashes)) {
|
|
38
|
+
if (!tracked.has(key))
|
|
39
|
+
delete hashes[key];
|
|
40
|
+
}
|
|
41
|
+
return hashes;
|
|
42
|
+
});
|
|
43
|
+
const runPostgresSql = (target, sql) => withPostgresClient(target, (client) => pgExec(client, sql));
|
|
44
|
+
const withPostgresClient = (target, use) => withTemporaryPostgresRole(target, (role) => Effect.acquireUseRelease(Effect.gen(function* () {
|
|
45
|
+
const { Client } = yield* Effect.tryPromise({
|
|
46
|
+
try: importPg,
|
|
47
|
+
catch: toMigrationError,
|
|
48
|
+
});
|
|
49
|
+
const client = yield* Effect.sync(() => new Client({
|
|
50
|
+
connectionString: role.connectionUrl.pipe(Redacted.value, stripPgSslQueryParams),
|
|
51
|
+
ssl: { rejectUnauthorized: true },
|
|
52
|
+
}));
|
|
53
|
+
yield* Effect.tryPromise({
|
|
54
|
+
try: () => client.connect(),
|
|
55
|
+
catch: toMigrationError,
|
|
56
|
+
});
|
|
57
|
+
return client;
|
|
58
|
+
}), use, (client) => Effect.tryPromise({
|
|
59
|
+
try: () => client.end(),
|
|
60
|
+
catch: toMigrationError,
|
|
61
|
+
}).pipe(Effect.ignore)));
|
|
62
|
+
const withTemporaryPostgresRole = (target, use) => Effect.acquireUseRelease(Effect.gen(function* () {
|
|
63
|
+
const created = yield* ps.createRole({
|
|
64
|
+
organization: target.organization,
|
|
65
|
+
database: target.database,
|
|
66
|
+
branch: target.branch,
|
|
67
|
+
ttl: MIGRATION_ROLE_TTL_SECONDS,
|
|
68
|
+
inherited_roles: ["postgres"],
|
|
69
|
+
});
|
|
70
|
+
const password = created.password;
|
|
71
|
+
const value = Redacted.value(password);
|
|
72
|
+
const connectionUrl = yield* Effect.sync(() => `postgresql://${encodeURIComponent(created.username)}:${encodeURIComponent(value)}@${created.access_host_url}:5432/${created.database_name}?sslmode=verify-full`);
|
|
73
|
+
return {
|
|
74
|
+
id: created.id,
|
|
75
|
+
connectionUrl: Redacted.make(connectionUrl),
|
|
76
|
+
};
|
|
77
|
+
}), use, (role) => ps
|
|
78
|
+
.deleteRole({
|
|
79
|
+
organization: target.organization,
|
|
80
|
+
database: target.database,
|
|
81
|
+
branch: target.branch,
|
|
82
|
+
id: role.id,
|
|
83
|
+
successor: "postgres",
|
|
84
|
+
})
|
|
85
|
+
.pipe(
|
|
86
|
+
// Already-deleted roles are a success: nothing to clean up.
|
|
87
|
+
Effect.catchTag("NotFound", () => Effect.void), Effect.retry({
|
|
88
|
+
schedule: Schedule.max([Schedule.exponential("500 millis"), Schedule.recurs(5)]),
|
|
89
|
+
}),
|
|
90
|
+
// Migrations succeeded; don't fail the parent over a release-step
|
|
91
|
+
// hiccup. The role's TTL bounds the orphan window; log loudly so
|
|
92
|
+
// an operator can clean it up manually if needed.
|
|
93
|
+
Effect.catch((cause) => Effect.logWarning(`Failed to delete temporary Planetscale migration role after retries. ` +
|
|
94
|
+
`It will expire via TTL (~${MIGRATION_ROLE_TTL_SECONDS}s). ` +
|
|
95
|
+
`organization=${target.organization} database=${target.database} ` +
|
|
96
|
+
`branch=${target.branch} id=${role.id}`, cause))));
|
|
97
|
+
const pgExec = (client, sql, values) => Effect.tryPromise({
|
|
98
|
+
try: () => client.query(sql, values).then(() => undefined),
|
|
99
|
+
catch: toMigrationError,
|
|
100
|
+
});
|
|
101
|
+
const toMigrationError = (cause) => new PostgresMigrationError({
|
|
102
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
103
|
+
cause,
|
|
104
|
+
});
|
|
105
|
+
const stripPgSslQueryParams = (uri) => {
|
|
106
|
+
try {
|
|
107
|
+
const url = new URL(uri);
|
|
108
|
+
url.searchParams.delete("sslmode");
|
|
109
|
+
url.searchParams.delete("channel_binding");
|
|
110
|
+
return url.toString();
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return uri;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=PostgresMigrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresMigrations.js","sourceRoot":"","sources":["../../src/Postgres/PostgresMigrations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as Redacted from "effect/Redacted";
|
|
2
|
+
/**
|
|
3
|
+
* The shape `Cloudflare.Hyperdrive` and other Postgres consumers accept as an
|
|
4
|
+
* origin. Materialized on `Planetscale.PostgresRole` so callers can wire role
|
|
5
|
+
* credentials into Hyperdrive directly.
|
|
6
|
+
*/
|
|
7
|
+
export type PostgresOrigin = {
|
|
8
|
+
scheme: "postgres" | "postgresql";
|
|
9
|
+
host: string;
|
|
10
|
+
port: number;
|
|
11
|
+
database: string;
|
|
12
|
+
user: string;
|
|
13
|
+
password: Redacted.Redacted<string>;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=PostgresOrigin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresOrigin.d.ts","sourceRoot":"","sources":["../../src/Postgres/PostgresOrigin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAE5C;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,UAAU,GAAG,YAAY,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;CACrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresOrigin.js","sourceRoot":"","sources":["../../src/Postgres/PostgresOrigin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import * as planetscale from "@distilled.cloud/planetscale";
|
|
2
|
+
import * as Provider from "alchemy/Provider";
|
|
3
|
+
import { Resource } from "alchemy/Resource";
|
|
4
|
+
import * as Redacted from "effect/Redacted";
|
|
5
|
+
import type { Providers } from "../Providers.ts";
|
|
6
|
+
import type { PostgresBranch } from "./PostgresBranch.ts";
|
|
7
|
+
import type { PostgresDatabase } from "./PostgresDatabase.ts";
|
|
8
|
+
import type { PostgresOrigin } from "./PostgresOrigin.ts";
|
|
9
|
+
/**
|
|
10
|
+
* Built-in PostgreSQL roles that can be inherited from. Custom role names
|
|
11
|
+
* (referencing other Role resources) are also accepted.
|
|
12
|
+
*/
|
|
13
|
+
export type InheritedRole = "pscale_managed" | "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" | "postgres" | (string & {});
|
|
14
|
+
/**
|
|
15
|
+
* Properties for creating or updating a PlanetScale PostgreSQL role.
|
|
16
|
+
*
|
|
17
|
+
* Roles are only meant for PostgreSQL databases. For MySQL,
|
|
18
|
+
* use {@link MySQLPassword} instead.
|
|
19
|
+
*/
|
|
20
|
+
export interface PostgresRoleProps {
|
|
21
|
+
/**
|
|
22
|
+
* Role name. If not provided, a physical name will be generated.
|
|
23
|
+
*/
|
|
24
|
+
name?: string;
|
|
25
|
+
/**
|
|
26
|
+
* PostgreSQL database — string name or {@link PostgresDatabase} resource.
|
|
27
|
+
*/
|
|
28
|
+
database: string | PostgresDatabase;
|
|
29
|
+
/**
|
|
30
|
+
* Branch — string name or {@link PostgresBranch} resource.
|
|
31
|
+
* @default "main"
|
|
32
|
+
*/
|
|
33
|
+
branch?: string | PostgresBranch;
|
|
34
|
+
/**
|
|
35
|
+
* Time to live in seconds.
|
|
36
|
+
*/
|
|
37
|
+
ttl?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Roles to inherit from. Either a list of built-in role names, or
|
|
40
|
+
* another {@link PostgresRole} resource (whose `inheritedRoles` are reused).
|
|
41
|
+
*/
|
|
42
|
+
inheritedRoles: InheritedRole[] | PostgresRole;
|
|
43
|
+
/**
|
|
44
|
+
* Give the role the REPLICATION attribute, for a logical-replication
|
|
45
|
+
* consumer (Electric, Debezium, a CDC pipeline). PlanetScale only grants
|
|
46
|
+
* it alongside `inheritedRoles: ["postgres"]`. Create-only: changing it
|
|
47
|
+
* replaces the role.
|
|
48
|
+
* @default false
|
|
49
|
+
*/
|
|
50
|
+
withReplication?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Successor role to reassign ownership to before dropping. Used during
|
|
53
|
+
* delete.
|
|
54
|
+
* @default "postgres"
|
|
55
|
+
*/
|
|
56
|
+
successor?: string | PostgresRole;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Output attributes of a deployed PlanetScale role.
|
|
60
|
+
*/
|
|
61
|
+
export interface PostgresRoleAttributes {
|
|
62
|
+
/** Unique identifier for the role (stable). */
|
|
63
|
+
id: string;
|
|
64
|
+
/** The Postgres role name (assigned by PlanetScale). */
|
|
65
|
+
name: string;
|
|
66
|
+
/** ISO 8601 timestamp at which the role expires. */
|
|
67
|
+
expiresAt: string | null;
|
|
68
|
+
/** Hostname for the database connection. */
|
|
69
|
+
host: string;
|
|
70
|
+
/** Username for database authentication. */
|
|
71
|
+
username: string;
|
|
72
|
+
/** Password for database authentication (Redacted). */
|
|
73
|
+
password: Redacted.Redacted<string>;
|
|
74
|
+
/** The database name. */
|
|
75
|
+
database: string;
|
|
76
|
+
/** The Postgres database name inside the branch. */
|
|
77
|
+
databaseName: string;
|
|
78
|
+
/** Parsed direct (port 5432) connection components ready to feed into Cloudflare Hyperdrive. */
|
|
79
|
+
origin: PostgresOrigin;
|
|
80
|
+
/** Parsed pooled (PSBouncer, port 6432) connection components, e.g. for a Hyperdrive `dev` origin. */
|
|
81
|
+
pooledOrigin: PostgresOrigin;
|
|
82
|
+
/**
|
|
83
|
+
* Private connection host or DNS zone for this branch, supplied by
|
|
84
|
+
* PlanetScale. GCP Private Service Connect requires an endpoint name before
|
|
85
|
+
* this DNS zone.
|
|
86
|
+
*/
|
|
87
|
+
privateHost: string;
|
|
88
|
+
/** Service name for this branch supplied by PlanetScale to establish a private connection. */
|
|
89
|
+
privateConnectionServiceName: string;
|
|
90
|
+
/** Direct connection URL for the database (Redacted). */
|
|
91
|
+
connectionUrl: Redacted.Redacted<string>;
|
|
92
|
+
/** Pooled connection URL via PSBouncer (port 6432, Redacted). */
|
|
93
|
+
connectionUrlPooled: Redacted.Redacted<string>;
|
|
94
|
+
/** Inherited roles. */
|
|
95
|
+
inheritedRoles: InheritedRole[];
|
|
96
|
+
/** Whether the role carries the REPLICATION attribute. */
|
|
97
|
+
withReplication: boolean;
|
|
98
|
+
/** The successor role used during delete. */
|
|
99
|
+
successor: string;
|
|
100
|
+
/** Resolved organization slug. */
|
|
101
|
+
organization: string;
|
|
102
|
+
/** Resolved branch name. */
|
|
103
|
+
branch: string;
|
|
104
|
+
/** Time-to-live for the role in seconds. */
|
|
105
|
+
ttl: number | null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* A PlanetScale role for accessing a PostgreSQL database branch.
|
|
109
|
+
*
|
|
110
|
+
* For MySQL databases, use {@link MySQLPassword} instead.
|
|
111
|
+
*
|
|
112
|
+
* ### Creating a Role
|
|
113
|
+
* **Example:** Postgres admin role
|
|
114
|
+
* ```typescript
|
|
115
|
+
* const admin = yield* Planetscale.PostgresRole("Admin", {
|
|
116
|
+
* database: "my-db",
|
|
117
|
+
* inheritedRoles: ["postgres"],
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* **Example:** Read-only role
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const reader = yield* Planetscale.PostgresRole("Reader", {
|
|
124
|
+
* database: "my-db",
|
|
125
|
+
* inheritedRoles: ["pg_read_all_data", "pg_read_all_settings"],
|
|
126
|
+
* });
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* **Example:** Role with TTL
|
|
130
|
+
* ```typescript
|
|
131
|
+
* const tempReader = yield* Planetscale.PostgresRole("TempReader", {
|
|
132
|
+
* database: "my-db",
|
|
133
|
+
* inheritedRoles: ["pg_read_all_data"],
|
|
134
|
+
* ttl: 3600,
|
|
135
|
+
* });
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export type PostgresRole = Resource<"Planetscale.PostgresRole", PostgresRoleProps, PostgresRoleAttributes, never, Providers>;
|
|
139
|
+
/** @resource */
|
|
140
|
+
export declare const PostgresRole: import("alchemy/Resource").ResourceClass<PostgresRole>;
|
|
141
|
+
export declare const PostgresRoleProvider: () => import("effect/Layer").Layer<Provider.Provider<PostgresRole>, never, import("alchemy/Stack").Stack | import("alchemy/Stage").Stage | planetscale.PlanetScaleOpContext>;
|
|
142
|
+
//# sourceMappingURL=PostgresRole.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresRole.d.ts","sourceRoot":"","sources":["../../src/Postgres/PostgresRole.ts"],"names":[],"mappings":"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"}
|