@alchemy.run/planetscale 0.0.0 → 2.0.0-beta.85

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 (123) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +83 -4
  3. package/lib/AuthProvider.d.ts +64 -0
  4. package/lib/AuthProvider.d.ts.map +1 -0
  5. package/lib/AuthProvider.js +395 -0
  6. package/lib/AuthProvider.js.map +1 -0
  7. package/lib/Branch.d.ts +128 -0
  8. package/lib/Branch.d.ts.map +1 -0
  9. package/lib/Branch.js +420 -0
  10. package/lib/Branch.js.map +1 -0
  11. package/lib/Contributions.d.ts +7 -0
  12. package/lib/Contributions.d.ts.map +1 -0
  13. package/lib/Contributions.js +6 -0
  14. package/lib/Contributions.js.map +1 -0
  15. package/lib/Credentials.d.ts +33 -0
  16. package/lib/Credentials.d.ts.map +1 -0
  17. package/lib/Credentials.js +59 -0
  18. package/lib/Credentials.js.map +1 -0
  19. package/lib/Database.d.ts +138 -0
  20. package/lib/Database.d.ts.map +1 -0
  21. package/lib/Database.js +1 -0
  22. package/lib/Database.js.map +1 -0
  23. package/lib/MySQL/MySQLBranch.d.ts +87 -0
  24. package/lib/MySQL/MySQLBranch.d.ts.map +1 -0
  25. package/lib/MySQL/MySQLBranch.js +15 -0
  26. package/lib/MySQL/MySQLBranch.js.map +1 -0
  27. package/lib/MySQL/MySQLClusterSize.d.ts +32 -0
  28. package/lib/MySQL/MySQLClusterSize.d.ts.map +1 -0
  29. package/lib/MySQL/MySQLClusterSize.js +111 -0
  30. package/lib/MySQL/MySQLClusterSize.js.map +1 -0
  31. package/lib/MySQL/MySQLDatabase.d.ts +141 -0
  32. package/lib/MySQL/MySQLDatabase.d.ts.map +1 -0
  33. package/lib/MySQL/MySQLDatabase.js +294 -0
  34. package/lib/MySQL/MySQLDatabase.js.map +1 -0
  35. package/lib/MySQL/MySQLMigrations.d.ts +20 -0
  36. package/lib/MySQL/MySQLMigrations.d.ts.map +1 -0
  37. package/lib/MySQL/MySQLMigrations.js +72 -0
  38. package/lib/MySQL/MySQLMigrations.js.map +1 -0
  39. package/lib/MySQL/MySQLOrigin.d.ts +15 -0
  40. package/lib/MySQL/MySQLOrigin.d.ts.map +1 -0
  41. package/lib/MySQL/MySQLOrigin.js +2 -0
  42. package/lib/MySQL/MySQLOrigin.js.map +1 -0
  43. package/lib/MySQL/MySQLPassword.d.ts +116 -0
  44. package/lib/MySQL/MySQLPassword.d.ts.map +1 -0
  45. package/lib/MySQL/MySQLPassword.js +212 -0
  46. package/lib/MySQL/MySQLPassword.js.map +1 -0
  47. package/lib/MySQL/index.d.ts +6 -0
  48. package/lib/MySQL/index.d.ts.map +1 -0
  49. package/lib/MySQL/index.js +6 -0
  50. package/lib/MySQL/index.js.map +1 -0
  51. package/lib/OAuthClient.d.ts +32 -0
  52. package/lib/OAuthClient.d.ts.map +1 -0
  53. package/lib/OAuthClient.js +52 -0
  54. package/lib/OAuthClient.js.map +1 -0
  55. package/lib/Postgres/PostgresBranch.d.ts +75 -0
  56. package/lib/Postgres/PostgresBranch.d.ts.map +1 -0
  57. package/lib/Postgres/PostgresBranch.js +15 -0
  58. package/lib/Postgres/PostgresBranch.js.map +1 -0
  59. package/lib/Postgres/PostgresClusterSize.d.ts +77 -0
  60. package/lib/Postgres/PostgresClusterSize.d.ts.map +1 -0
  61. package/lib/Postgres/PostgresClusterSize.js +89 -0
  62. package/lib/Postgres/PostgresClusterSize.js.map +1 -0
  63. package/lib/Postgres/PostgresDatabase.d.ts +95 -0
  64. package/lib/Postgres/PostgresDatabase.d.ts.map +1 -0
  65. package/lib/Postgres/PostgresDatabase.js +294 -0
  66. package/lib/Postgres/PostgresDatabase.js.map +1 -0
  67. package/lib/Postgres/PostgresDefaultRole.d.ts +94 -0
  68. package/lib/Postgres/PostgresDefaultRole.d.ts.map +1 -0
  69. package/lib/Postgres/PostgresDefaultRole.js +187 -0
  70. package/lib/Postgres/PostgresDefaultRole.js.map +1 -0
  71. package/lib/Postgres/PostgresMigrations.d.ts +16 -0
  72. package/lib/Postgres/PostgresMigrations.d.ts.map +1 -0
  73. package/lib/Postgres/PostgresMigrations.js +65 -0
  74. package/lib/Postgres/PostgresMigrations.js.map +1 -0
  75. package/lib/Postgres/PostgresOrigin.d.ts +15 -0
  76. package/lib/Postgres/PostgresOrigin.d.ts.map +1 -0
  77. package/lib/Postgres/PostgresOrigin.js +2 -0
  78. package/lib/Postgres/PostgresOrigin.js.map +1 -0
  79. package/lib/Postgres/PostgresRole.d.ts +142 -0
  80. package/lib/Postgres/PostgresRole.d.ts.map +1 -0
  81. package/lib/Postgres/PostgresRole.js +268 -0
  82. package/lib/Postgres/PostgresRole.js.map +1 -0
  83. package/lib/Postgres/index.d.ts +7 -0
  84. package/lib/Postgres/index.d.ts.map +1 -0
  85. package/lib/Postgres/index.js +7 -0
  86. package/lib/Postgres/index.js.map +1 -0
  87. package/lib/Providers.d.ts +24 -0
  88. package/lib/Providers.d.ts.map +1 -0
  89. package/lib/Providers.js +40 -0
  90. package/lib/Providers.js.map +1 -0
  91. package/lib/Util.d.ts +93 -0
  92. package/lib/Util.d.ts.map +1 -0
  93. package/lib/Util.js +135 -0
  94. package/lib/Util.js.map +1 -0
  95. package/lib/index.d.ts +9 -0
  96. package/lib/index.d.ts.map +1 -0
  97. package/lib/index.js +9 -0
  98. package/lib/index.js.map +1 -0
  99. package/package.json +79 -3
  100. package/src/AuthProvider.ts +584 -0
  101. package/src/Branch.ts +657 -0
  102. package/src/Contributions.ts +9 -0
  103. package/src/Credentials.ts +92 -0
  104. package/src/Database.ts +152 -0
  105. package/src/MySQL/MySQLBranch.ts +109 -0
  106. package/src/MySQL/MySQLClusterSize.ts +185 -0
  107. package/src/MySQL/MySQLDatabase.ts +521 -0
  108. package/src/MySQL/MySQLMigrations.ts +133 -0
  109. package/src/MySQL/MySQLOrigin.ts +15 -0
  110. package/src/MySQL/MySQLPassword.ts +428 -0
  111. package/src/MySQL/index.ts +5 -0
  112. package/src/OAuthClient.ts +59 -0
  113. package/src/Postgres/PostgresBranch.ts +97 -0
  114. package/src/Postgres/PostgresClusterSize.ts +262 -0
  115. package/src/Postgres/PostgresDatabase.ts +469 -0
  116. package/src/Postgres/PostgresDefaultRole.ts +340 -0
  117. package/src/Postgres/PostgresMigrations.ts +122 -0
  118. package/src/Postgres/PostgresOrigin.ts +15 -0
  119. package/src/Postgres/PostgresRole.ts +547 -0
  120. package/src/Postgres/index.ts +6 -0
  121. package/src/Providers.ts +67 -0
  122. package/src/Util.ts +205 -0
  123. package/src/index.ts +14 -0
@@ -0,0 +1,395 @@
1
+ import { listOrganizations } from "@distilled.cloud/planetscale";
2
+ import * as PsCredentialsModule from "@distilled.cloud/planetscale/Credentials";
3
+ import { AuthError, AuthProviderLayer, refreshHint, NeedsReauth, } from "alchemy/Auth/AuthProvider";
4
+ import { browserOAuth } from "alchemy/Auth/BrowserOAuth";
5
+ import { displayRedacted } from "alchemy/Auth/Credentials";
6
+ import { getEnvRedactedRequired, getEnvRequired, mapPromptCancellation } from "alchemy/Auth/Env";
7
+ import { withProfileCredentialsLock } from "alchemy/Auth/Lock";
8
+ import { storedSecret, storedValueText, validateFieldValues, } from "alchemy/Auth/StoredAuthProvider";
9
+ import * as Interaction from "alchemy/Interaction";
10
+ import * as Clock from "effect/Clock";
11
+ import * as Duration from "effect/Duration";
12
+ import * as Effect from "effect/Effect";
13
+ import * as FetchHttpClient from "effect/http/FetchHttpClient";
14
+ import * as HttpClient from "effect/http/HttpClient";
15
+ import * as Layer from "effect/Layer";
16
+ import * as Match from "effect/Match";
17
+ import * as Redacted from "effect/Redacted";
18
+ import * as Schema from "effect/Schema";
19
+ import * as OAuthClient from "./OAuthClient.js";
20
+ /**
21
+ * Canonical name registered in {@link AuthProviders}. Use this key to look
22
+ * up the PlanetScale {@link AuthProvider} from inside provider Layers.
23
+ */
24
+ export const PLANETSCALE_AUTH_PROVIDER_NAME = "Planetscale";
25
+ /**
26
+ * Provide PlanetScale `Credentials` + `HttpClient` to an Effect using a
27
+ * just-obtained OAuth access token. Used during configure to call
28
+ * org-discovery endpoints before the user has chosen an org.
29
+ *
30
+ * `organization` is required by the credential type but isn't consulted by
31
+ * `listOrganizations` (it's a user-scoped endpoint), so an empty string is
32
+ * fine here.
33
+ */
34
+ const withOAuthCredentials = (accessToken, effect) => Effect.provide(effect, Layer.mergeAll(PsCredentialsModule.fromOAuth({
35
+ accessToken: Redacted.make(accessToken),
36
+ organization: "",
37
+ }), FetchHttpClient.layer));
38
+ /**
39
+ * List the organizations the OAuth user belongs to and either auto-pick
40
+ * (one org) or prompt the user to choose. Returns the org's URL slug
41
+ * (`name` field, used as `{organization}` in API paths).
42
+ */
43
+ const selectOrganization = (accessToken) => Effect.gen(function* () {
44
+ const list = yield* listOrganizations;
45
+ const response = yield* list({});
46
+ const orgs = response.data;
47
+ if (orgs.length === 0) {
48
+ return yield* AuthError.make({
49
+ message: "Planetscale: no organizations found for this credential.",
50
+ });
51
+ }
52
+ if (orgs.length === 1) {
53
+ const org = orgs[0];
54
+ if (org === undefined) {
55
+ return yield* AuthError.make({
56
+ message: "Planetscale: organization response was unexpectedly empty.",
57
+ });
58
+ }
59
+ yield* Interaction.info(`Planetscale: using organization: ${org.name} (${org.id})`);
60
+ return org.name;
61
+ }
62
+ return yield* Interaction.select({
63
+ message: "Select a Planetscale organization",
64
+ options: orgs.map((o) => ({
65
+ value: o.name,
66
+ label: o.name,
67
+ description: o.id,
68
+ })),
69
+ }).pipe(mapPromptCancellation);
70
+ }).pipe((e) => withOAuthCredentials(accessToken, e));
71
+ const options = [
72
+ {
73
+ value: "oauth",
74
+ label: "OAuth",
75
+ description: "recommended — browser-based login with automatic token refresh",
76
+ },
77
+ {
78
+ value: "stored",
79
+ label: "Service Token",
80
+ description: "enter a service token and store it inline in the provider file",
81
+ },
82
+ ];
83
+ /**
84
+ * Typed values stored in a PlanetScale provider profile document. Both
85
+ * service-token and OAuth values are inline. PlanetScale has no PKCE flow,
86
+ * so the OAuth application's
87
+ * `client_secret` ships in the CLI — see {@link OAuthClient}.
88
+ */
89
+ export const PlanetscaleAuthConfigSchema = Schema.Union([
90
+ Schema.Struct({
91
+ method: Schema.Literal("stored"),
92
+ tokenId: Schema.String,
93
+ token: Schema.String,
94
+ organization: Schema.String,
95
+ }),
96
+ Schema.Struct({
97
+ method: Schema.Literal("oauth"),
98
+ organization: Schema.String,
99
+ clientId: Schema.optional(Schema.String),
100
+ access: Schema.String,
101
+ refresh: Schema.String,
102
+ expires: Schema.Number,
103
+ scopes: Schema.String.pipe(Schema.Array, Schema.mutable),
104
+ }),
105
+ ]);
106
+ /**
107
+ * Layer that registers the PlanetScale {@link AuthProvider} into the
108
+ * {@link AuthProviders} registry when built. Include this in the
109
+ * PlanetScale `providers()` layer so the alchemy CLI can discover it.
110
+ *
111
+ * Supported methods:
112
+ * - `stored`: prompts for a service token and stores it inline.
113
+ * - `oauth`: browser-based login storing access/refresh values inline.
114
+ */
115
+ export const PlanetscaleAuth = AuthProviderLayer()(PLANETSCALE_AUTH_PROVIDER_NAME, Effect.gen(function* () {
116
+ const oauthLogin = (_profileName) => Effect.gen(function* () {
117
+ const authorization = yield* OAuthClient.authorize();
118
+ const credentials = yield* browserOAuth({
119
+ provider: "Planetscale",
120
+ url: authorization.url,
121
+ callback: OAuthClient.callback(authorization),
122
+ exchange: (input) => OAuthClient.exchangeCallbackInput(input, authorization),
123
+ });
124
+ yield* Interaction.success("Planetscale: OAuth credentials saved.");
125
+ return credentials;
126
+ });
127
+ const configureOAuth = Effect.fn(function* (profileName) {
128
+ const oauthCreds = yield* oauthLogin(profileName);
129
+ // Use the just-issued access token to list the user's orgs and let
130
+ // them pick (mirrors Cloudflare's selectAccount). Requires the
131
+ // `user:read_organizations` scope. If the call fails for any
132
+ // reason — missing scope, network, off-spec response — fall back
133
+ // to a manual prompt so login still completes.
134
+ const organization = yield* oauthCreds.access.pipe(Redacted.value, selectOrganization, Effect.catch((e) => Effect.gen(function* () {
135
+ yield* Interaction.warning(`Planetscale: could not auto-list organizations (${String(e)}). Falling back to manual entry.`);
136
+ return yield* Interaction.text({
137
+ message: "Planetscale Organization (URL slug)",
138
+ validate: (v) => (v.length === 0 ? "Required" : undefined),
139
+ }).pipe(mapPromptCancellation);
140
+ })));
141
+ return {
142
+ method: "oauth",
143
+ organization,
144
+ clientId: oauthCreds.clientId,
145
+ access: Redacted.value(oauthCreds.access),
146
+ refresh: Redacted.value(oauthCreds.refresh),
147
+ expires: oauthCreds.expires,
148
+ scopes: oauthCreds.scopes,
149
+ };
150
+ });
151
+ const loginStored = Effect.fn(function* (_profileName) {
152
+ const tokenId = yield* Interaction.text({
153
+ message: "Planetscale Service Token ID",
154
+ validate: (v) => (v.length === 0 ? "Required" : undefined),
155
+ }).pipe(mapPromptCancellation);
156
+ const token = yield* Interaction.password({
157
+ message: "Planetscale Service Token",
158
+ validate: (v) => (v.length === 0 ? "Required" : undefined),
159
+ }).pipe(mapPromptCancellation);
160
+ const organization = yield* Interaction.text({
161
+ message: "Planetscale Organization (URL slug)",
162
+ validate: (v) => (v.length === 0 ? "Required" : undefined),
163
+ }).pipe(mapPromptCancellation);
164
+ yield* Interaction.success("Planetscale: credentials saved.");
165
+ return { method: "stored", tokenId, token, organization };
166
+ });
167
+ const configureInteractive = (profileName) => Interaction.select({
168
+ message: "Planetscale authentication method",
169
+ options,
170
+ }).pipe(Effect.flatMap((method) => Match.value(method).pipe(Match.when("oauth", () => configureOAuth(profileName)), Match.when("stored", () => loginStored(profileName)), Match.exhaustive)));
171
+ const configureCredentials = (profileName) => configureInteractive(profileName).pipe(Effect.mapError((e) => AuthError.make({
172
+ message: "failed to configure credentials",
173
+ cause: e,
174
+ })));
175
+ /**
176
+ * Flag-driven (`--method stored --set ...`) fields, mirroring the
177
+ * interactive service-token prompts. OAuth requires a browser and stays
178
+ * interactive-only, so it is deliberately absent from
179
+ * {@link configureMethods}.
180
+ */
181
+ const serviceTokenFields = [
182
+ { name: "tokenId", label: "Planetscale Service Token ID" },
183
+ { name: "token", label: "Planetscale Service Token", secret: true },
184
+ { name: "organization", label: "Planetscale Organization (URL slug)" },
185
+ ];
186
+ const configureMethods = [
187
+ { method: "stored", fields: serviceTokenFields },
188
+ ];
189
+ const configureWith = (_profileName, input) => input.method === "stored"
190
+ ? validateFieldValues(PLANETSCALE_AUTH_PROVIDER_NAME, serviceTokenFields, input.values).pipe(Effect.map((values) => ({
191
+ method: "stored",
192
+ tokenId: Redacted.value(storedSecret(values.tokenId) ?? Redacted.make("")),
193
+ token: Redacted.value(storedSecret(values.token) ?? Redacted.make("")),
194
+ organization: storedValueText(values.organization) ?? "",
195
+ })), Effect.tap(() => Interaction.success("Planetscale: credentials saved.")))
196
+ : Effect.fail(AuthError.make({
197
+ message: `Planetscale: unknown method '${input.method}'. Valid methods: stored. (OAuth is interactive-only.)`,
198
+ }));
199
+ const resolveCredentials = (profileName, config, updateConfig) => Effect.gen(function* () {
200
+ const reauth = refreshHint(PLANETSCALE_AUTH_PROVIDER_NAME, profileName);
201
+ return yield* Match.value(config).pipe(Match.when({ method: "stored" }, (stored) => Effect.succeed({
202
+ type: "apiToken",
203
+ tokenId: Redacted.make(stored.tokenId),
204
+ token: Redacted.make(stored.token),
205
+ organization: stored.organization,
206
+ source: { type: "stored", details: undefined },
207
+ })), Match.when({ method: "oauth" }, (cfg) => Effect.gen(function* () {
208
+ const creds = {
209
+ type: "oauth",
210
+ clientId: cfg.clientId,
211
+ access: Redacted.make(cfg.access),
212
+ refresh: Redacted.make(cfg.refresh),
213
+ expires: cfg.expires,
214
+ scopes: cfg.scopes,
215
+ };
216
+ if (!OAuthClient.usesCurrentClient(creds)) {
217
+ return yield* NeedsReauth.make({
218
+ provider: PLANETSCALE_AUTH_PROVIDER_NAME,
219
+ profile: profileName,
220
+ message: `Planetscale OAuth credentials for profile '${profileName}' were issued to an incompatible OAuth client and have been removed. ${reauth}`,
221
+ });
222
+ }
223
+ // Refresh proactively if the token has expired (or is within
224
+ // 10s of expiring). Persist the refreshed creds so subsequent
225
+ // resolves don't repeat the round-trip.
226
+ const now = yield* Clock.currentTimeMillis;
227
+ const fresh = creds.expires > now + 10_000
228
+ ? creds
229
+ : yield* OAuthClient.refresh(creds).pipe(
230
+ // Only the refresh round-trip maps to NeedsReauth — a
231
+ // failed persist afterwards is a local I/O AuthError and
232
+ // passes through untouched.
233
+ Effect.mapError((e) => NeedsReauth.make({
234
+ provider: PLANETSCALE_AUTH_PROVIDER_NAME,
235
+ profile: profileName,
236
+ message: `Planetscale OAuth refresh failed. ${reauth}`,
237
+ cause: e,
238
+ })));
239
+ if (fresh !== creds) {
240
+ yield* (updateConfig?.({
241
+ method: "oauth",
242
+ organization: cfg.organization,
243
+ clientId: fresh.clientId,
244
+ access: Redacted.value(fresh.access),
245
+ refresh: Redacted.value(fresh.refresh),
246
+ expires: fresh.expires,
247
+ scopes: fresh.scopes,
248
+ }) ?? Effect.void);
249
+ }
250
+ return {
251
+ type: "oauth",
252
+ accessToken: fresh.access,
253
+ expires: fresh.expires,
254
+ organization: cfg.organization,
255
+ source: { type: "oauth" },
256
+ };
257
+ })), Match.exhaustive);
258
+ });
259
+ const logout = (_profileName, config) => Match.value(config).pipe(Match.when({ method: "stored" }, () => Effect.void), Match.when({ method: "oauth" }, () => Effect.void), Match.exhaustive);
260
+ const login = (profileName, config, updateConfig, reload) => Match.value(config).pipe(Match.when({ method: "stored" }, (stored) => Effect.succeed(stored)), Match.when({ method: "oauth" }, (oauth) => Effect.gen(function* () {
261
+ const credentials = {
262
+ type: "oauth",
263
+ clientId: oauth.clientId,
264
+ access: Redacted.make(oauth.access),
265
+ refresh: Redacted.make(oauth.refresh),
266
+ expires: oauth.expires,
267
+ scopes: oauth.scopes,
268
+ };
269
+ if (!OAuthClient.usesCurrentClient(credentials)) {
270
+ return yield* configureOAuth(profileName);
271
+ }
272
+ // Refresh tokens are single-use: refresh with the token stored
273
+ // now, read under the lock, not the one `config` was read with.
274
+ const outcome = yield* withProfileCredentialsLock(profileName, Effect.gen(function* () {
275
+ const current = yield* reload ?? Effect.succeed(oauth);
276
+ if (current.method !== "oauth")
277
+ return { type: "browser" };
278
+ const currentCredentials = {
279
+ type: "oauth",
280
+ clientId: current.clientId,
281
+ access: Redacted.make(current.access),
282
+ refresh: Redacted.make(current.refresh),
283
+ expires: current.expires,
284
+ scopes: current.scopes,
285
+ };
286
+ if (!OAuthClient.usesCurrentClient(currentCredentials)) {
287
+ return { type: "browser" };
288
+ }
289
+ return yield* Interaction.info("Planetscale: refreshing OAuth credentials...").pipe(Effect.andThen(OAuthClient.refresh(currentCredentials)), Effect.flatMap((credentials) => {
290
+ const config = {
291
+ ...current,
292
+ clientId: credentials.clientId,
293
+ access: Redacted.value(credentials.access),
294
+ refresh: Redacted.value(credentials.refresh),
295
+ expires: credentials.expires,
296
+ scopes: credentials.scopes,
297
+ };
298
+ // Saved here, under the lock, when the caller can take it;
299
+ // otherwise handed back for the caller to save.
300
+ const unsaved = updateConfig === undefined
301
+ ? Effect.succeed(config)
302
+ : Effect.as(updateConfig(config), undefined);
303
+ return unsaved.pipe(Effect.map((config) => ({ type: "refreshed", config })));
304
+ }), Effect.tap(() => Interaction.success("Planetscale: OAuth credentials refreshed.")));
305
+ })).pipe(Effect.catchTag([
306
+ "OAuthError",
307
+ "OAuthNetworkError",
308
+ "OAuthServerUnavailable",
309
+ "OAuthInvalidResponse",
310
+ ], () => Effect.succeed({ type: "browser" })));
311
+ if (outcome.type === "browser") {
312
+ return yield* configureOAuth(profileName);
313
+ }
314
+ return outcome.config;
315
+ })), Match.exhaustive, Effect.mapError((e) => AuthError.make({ message: "login failed", cause: e })));
316
+ const details = (profileName, config, updateConfig) => Effect.all([
317
+ resolveCredentials(profileName, config, updateConfig),
318
+ Clock.currentTimeMillis,
319
+ ]).pipe(Effect.map(([creds, now]) => {
320
+ const source = creds.source;
321
+ const sourceStr = source.details ? `${source.type} - ${source.details}` : source.type;
322
+ return Match.value(creds).pipe(Match.when({ type: "apiToken" }, (c) => ({
323
+ lines: [
324
+ { key: "tokenId", value: displayRedacted(c.tokenId, 3) },
325
+ { key: "token", value: displayRedacted(c.token, 6) },
326
+ { key: "organization", value: c.organization },
327
+ { key: "source", value: sourceStr },
328
+ ],
329
+ })), Match.when({ type: "oauth" }, (c) => {
330
+ const remainingMs = c.expires - now;
331
+ const expiresAt = new Date(c.expires).toISOString();
332
+ const expiresStr = remainingMs <= 0
333
+ ? `expired (${expiresAt})`
334
+ : `in ${Duration.format(Duration.millis(remainingMs))} (${expiresAt})`;
335
+ return {
336
+ lines: [
337
+ { key: "accessToken", value: displayRedacted(c.accessToken) },
338
+ { key: "expires", value: expiresStr },
339
+ { key: "organization", value: c.organization },
340
+ { key: "source", value: sourceStr },
341
+ ],
342
+ };
343
+ }), Match.exhaustive);
344
+ }));
345
+ const readEnvironment = Effect.gen(function* () {
346
+ const tokenId = yield* getEnvRedactedRequired("PLANETSCALE_API_TOKEN_ID");
347
+ const token = yield* getEnvRedactedRequired("PLANETSCALE_API_TOKEN");
348
+ const organization = yield* getEnvRequired("PLANETSCALE_ORGANIZATION");
349
+ return {
350
+ type: "apiToken",
351
+ tokenId,
352
+ token,
353
+ organization,
354
+ source: {
355
+ type: "env",
356
+ details: "PLANETSCALE_API_TOKEN_ID/PLANETSCALE_API_TOKEN",
357
+ },
358
+ };
359
+ });
360
+ return {
361
+ configSchema: PlanetscaleAuthConfigSchema,
362
+ configure: configureCredentials,
363
+ configureWith,
364
+ configureMethods,
365
+ logout,
366
+ login,
367
+ details,
368
+ read: resolveCredentials,
369
+ readEnvironment,
370
+ environment: [
371
+ {
372
+ name: "PLANETSCALE_API_TOKEN_ID",
373
+ required: true,
374
+ description: "Service token id.",
375
+ },
376
+ {
377
+ name: "PLANETSCALE_API_TOKEN",
378
+ required: true,
379
+ secret: true,
380
+ description: "Service token secret.",
381
+ },
382
+ {
383
+ name: "PLANETSCALE_ORGANIZATION",
384
+ required: true,
385
+ description: "Organization URL slug.",
386
+ },
387
+ {
388
+ name: "PLANETSCALE_API_BASE_URL",
389
+ required: false,
390
+ description: "API base URL override.",
391
+ },
392
+ ],
393
+ };
394
+ }));
395
+ //# sourceMappingURL=AuthProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthProvider.js","sourceRoot":"","sources":["../src/AuthProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ import { type MigrationRun, type MigrationsInput, type NormalizedMigrationsInput, type StampedMigrationsState } from "@alchemy.run/sql/Migrations";
2
+ import * as Provider from "alchemy/Provider";
3
+ import type { ResourceClass, ResourceLike } from "alchemy/Resource";
4
+ import * as Effect from "effect/Effect";
5
+ /**
6
+ * Props shared between {@link MySQLBranch} and {@link PostgresBranch}. The
7
+ * `database` and `parentBranch` fields are typed by each engine's resource.
8
+ */
9
+ export interface BaseBranchProps {
10
+ /**
11
+ * Branch name. If omitted, a name is generated from the stack/stage/id.
12
+ */
13
+ name?: string;
14
+ /**
15
+ * If provided, restores the backup's schema and data to the new branch.
16
+ * Ignored if the branch already exists.
17
+ */
18
+ backupId?: string;
19
+ /**
20
+ * If provided, restores the last successful backup's schema and data.
21
+ * Ignored if the branch already exists.
22
+ */
23
+ seedData?: "last_successful_backup";
24
+ /**
25
+ * Whether safe migrations are enabled on the branch.
26
+ */
27
+ safeMigrations?: boolean;
28
+ /**
29
+ * Region in which to create the branch. Defaults to the database's
30
+ * region. The actual region is validated on adopt/update.
31
+ */
32
+ region?: {
33
+ slug: string;
34
+ };
35
+ /**
36
+ * SQL migrations to apply against this branch. Accepts a directory path,
37
+ * a `Drizzle.Schema` resource, or `{ dir, table? }`. Bookkeeping lives
38
+ * in Alchemy's `__alchemy_migrations` table; drizzle/prisma history is
39
+ * converted one-way on first deploy.
40
+ *
41
+ * Adding a file is an in-place update. Editing or removing an
42
+ * already-applied file replaces a non-production branch (re-forked from
43
+ * its parent) and fails on a current or desired production branch — add
44
+ * a forward migration instead.
45
+ */
46
+ migrations?: MigrationsInput;
47
+ /**
48
+ * Paths to additional `.sql` files to apply after migrations. Each file is
49
+ * hashed; only files whose contents change are re-applied on later deploys.
50
+ */
51
+ importFiles?: string[];
52
+ }
53
+ /**
54
+ * Attributes shared between {@link MySQLBranch} and {@link PostgresBranch}.
55
+ */
56
+ export interface BaseBranchAttributes {
57
+ /** The branch name. */
58
+ name: string;
59
+ /** The PlanetScale organization slug. */
60
+ organization: string;
61
+ /** The database name. */
62
+ database: string;
63
+ /** The parent branch name. */
64
+ parentBranch: string;
65
+ /** Whether this is a production branch. */
66
+ production: boolean;
67
+ /** Time at which the branch was created (ISO 8601). */
68
+ createdAt: string;
69
+ /**
70
+ * Time at which the branch was last updated (ISO 8601), as observed by the
71
+ * last deploy. PlanetScale bumps this timestamp on its own, so it is not
72
+ * refreshed by drift detection.
73
+ */
74
+ updatedAt: string;
75
+ /** HTML URL for accessing the branch in the dashboard. */
76
+ htmlUrl: string;
77
+ /** The region of the branch as reported by PlanetScale. */
78
+ region: {
79
+ slug: string;
80
+ };
81
+ /** Directory containing migration files, if configured. */
82
+ migrationsDir: string | undefined;
83
+ /** Table used to track applied migrations, if configured. */
84
+ migrationsTable: string | undefined;
85
+ /** Content hashes for the last applied migration files. */
86
+ migrationsHashes: Record<string, string>;
87
+ /** Content hashes for the last applied import files. */
88
+ importHashes: Record<string, string>;
89
+ /**
90
+ * Desired total replica count requested by the resource input, when known.
91
+ * PlanetScale's branch read API exposes only boolean HA state, so this is
92
+ * persisted from Alchemy state rather than observed from live provider data.
93
+ */
94
+ desiredReplicas: number | undefined;
95
+ /** Whether the branch currently has HA replicas. */
96
+ hasReplicas: boolean | undefined;
97
+ /** Whether the branch currently has read-only replicas. */
98
+ hasReadOnlyReplicas: boolean | undefined;
99
+ }
100
+ /**
101
+ * Shape of the engine-specific migration runners used by
102
+ * {@link makeBranchProvider}. MySQL and Postgres each supply their own
103
+ * implementations in their respective `*Migrations.ts` modules.
104
+ */
105
+ export interface BranchMigrationRunners {
106
+ runMigrations: (target: {
107
+ organization: string;
108
+ database: string;
109
+ branch: string;
110
+ }, input: NormalizedMigrationsInput, stamped: StampedMigrationsState) => Effect.Effect<MigrationRun, any, any>;
111
+ runImports: (target: {
112
+ organization: string;
113
+ database: string;
114
+ branch: string;
115
+ }, importFiles: string[], rootDir: string, previousHashes: Record<string, string>) => Effect.Effect<Record<string, string>, any, any>;
116
+ }
117
+ /**
118
+ * Build a branch provider for a specific PlanetScale engine. The
119
+ * caller supplies the typed `Resource` token and the engine's migration
120
+ * runners; everything else (observe / ensure / sync / delete) is shared.
121
+ */
122
+ export declare const makeBranchProvider: <R extends ResourceLike>(opts: {
123
+ resource: ResourceClass<R>;
124
+ expectedKind: "mysql" | "postgresql";
125
+ engineLabel: string;
126
+ runners: BranchMigrationRunners;
127
+ }) => import("effect/Layer").Layer<Provider.Provider<R>, never, never>;
128
+ //# sourceMappingURL=Branch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Branch.d.ts","sourceRoot":"","sources":["../src/Branch.ts"],"names":[],"mappings":"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"}