@alchemy.run/planetscale 2.0.0-beta.84 → 2.0.0-beta.86
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/lib/AuthProvider.d.ts +1 -1
- package/lib/AuthProvider.d.ts.map +1 -1
- package/lib/AuthProvider.js +58 -47
- package/lib/AuthProvider.js.map +1 -1
- package/lib/Branch.d.ts +6 -1
- package/lib/Branch.d.ts.map +1 -1
- package/lib/Branch.js +23 -2
- package/lib/Branch.js.map +1 -1
- package/lib/Contributions.d.ts +1 -1
- package/lib/Contributions.d.ts.map +1 -1
- package/lib/Contributions.js.map +1 -1
- package/lib/Credentials.d.ts +1 -1
- package/lib/Credentials.d.ts.map +1 -1
- package/lib/Credentials.js +6 -12
- package/lib/Credentials.js.map +1 -1
- package/lib/Database.d.ts +7 -0
- package/lib/Database.d.ts.map +1 -1
- package/lib/Database.js.map +1 -1
- package/lib/MySQL/MySQLBranch.d.ts +26 -2
- package/lib/MySQL/MySQLBranch.d.ts.map +1 -1
- package/lib/MySQL/MySQLBranch.js +15 -1
- package/lib/MySQL/MySQLBranch.js.map +1 -1
- package/lib/MySQL/MySQLClusterSize.d.ts +1 -1
- package/lib/MySQL/MySQLClusterSize.d.ts.map +1 -1
- package/lib/MySQL/MySQLClusterSize.js +1 -1
- package/lib/MySQL/MySQLClusterSize.js.map +1 -1
- package/lib/MySQL/MySQLDatabase.d.ts +28 -2
- package/lib/MySQL/MySQLDatabase.d.ts.map +1 -1
- package/lib/MySQL/MySQLDatabase.js +72 -51
- package/lib/MySQL/MySQLDatabase.js.map +1 -1
- package/lib/MySQL/MySQLMigrations.d.ts +7 -11
- package/lib/MySQL/MySQLMigrations.d.ts.map +1 -1
- package/lib/MySQL/MySQLMigrations.js +24 -58
- package/lib/MySQL/MySQLMigrations.js.map +1 -1
- package/lib/MySQL/MySQLOrigin.d.ts.map +1 -1
- package/lib/MySQL/MySQLOrigin.js.map +1 -1
- package/lib/MySQL/MySQLPassword.d.ts.map +1 -1
- package/lib/MySQL/MySQLPassword.js +2 -2
- package/lib/MySQL/MySQLPassword.js.map +1 -1
- package/lib/MySQL/index.d.ts.map +1 -1
- package/lib/MySQL/index.js.map +1 -1
- package/lib/OAuthClient.d.ts.map +1 -1
- package/lib/OAuthClient.js.map +1 -1
- package/lib/Postgres/PostgresBranch.d.ts +26 -2
- package/lib/Postgres/PostgresBranch.d.ts.map +1 -1
- package/lib/Postgres/PostgresBranch.js +15 -1
- package/lib/Postgres/PostgresBranch.js.map +1 -1
- package/lib/Postgres/PostgresClusterSize.d.ts.map +1 -1
- package/lib/Postgres/PostgresClusterSize.js.map +1 -1
- package/lib/Postgres/PostgresDatabase.d.ts +28 -2
- package/lib/Postgres/PostgresDatabase.d.ts.map +1 -1
- package/lib/Postgres/PostgresDatabase.js +77 -56
- package/lib/Postgres/PostgresDatabase.js.map +1 -1
- package/lib/Postgres/PostgresDefaultRole.d.ts.map +1 -1
- package/lib/Postgres/PostgresDefaultRole.js +2 -2
- package/lib/Postgres/PostgresDefaultRole.js.map +1 -1
- package/lib/Postgres/PostgresMigrations.d.ts +3 -11
- package/lib/Postgres/PostgresMigrations.d.ts.map +1 -1
- package/lib/Postgres/PostgresMigrations.js +15 -66
- package/lib/Postgres/PostgresMigrations.js.map +1 -1
- package/lib/Postgres/PostgresOrigin.d.ts.map +1 -1
- package/lib/Postgres/PostgresOrigin.js.map +1 -1
- package/lib/Postgres/PostgresRole.d.ts.map +1 -1
- package/lib/Postgres/PostgresRole.js +3 -3
- package/lib/Postgres/PostgresRole.js.map +1 -1
- package/lib/Postgres/index.d.ts.map +1 -1
- package/lib/Postgres/index.js.map +1 -1
- package/lib/Providers.d.ts +1 -1
- package/lib/Providers.d.ts.map +1 -1
- package/lib/Providers.js +3 -1
- package/lib/Providers.js.map +1 -1
- package/lib/ServiceToken.d.ts +142 -0
- package/lib/ServiceToken.d.ts.map +1 -0
- package/lib/ServiceToken.js +268 -0
- package/lib/ServiceToken.js.map +1 -0
- package/lib/Util.d.ts +3 -3
- package/lib/Util.d.ts.map +1 -1
- package/lib/Util.js +1 -1
- package/lib/Util.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/package.json +9 -9
- package/src/AuthProvider.ts +91 -78
- package/src/Branch.ts +36 -3
- package/src/Credentials.ts +8 -32
- package/src/Database.ts +7 -0
- package/src/MySQL/MySQLBranch.ts +28 -2
- package/src/MySQL/MySQLClusterSize.ts +1 -1
- package/src/MySQL/MySQLDatabase.ts +103 -63
- package/src/MySQL/MySQLMigrations.ts +31 -80
- package/src/MySQL/MySQLPassword.ts +2 -2
- package/src/Postgres/PostgresBranch.ts +28 -2
- package/src/Postgres/PostgresDatabase.ts +104 -63
- package/src/Postgres/PostgresDefaultRole.ts +2 -2
- package/src/Postgres/PostgresMigrations.ts +20 -91
- package/src/Postgres/PostgresRole.ts +4 -4
- package/src/Providers.ts +3 -0
- package/src/ServiceToken.ts +431 -0
- package/src/Util.ts +1 -1
- package/src/index.ts +1 -0
package/lib/Util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Util.js","
|
|
1
|
+
{"version":3,"file":"Util.js","sources":["../src/Util.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC"}
|
package/lib/index.js
CHANGED
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAmD,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alchemy.run/planetscale",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.86",
|
|
4
4
|
"description": "PlanetScale MySQL and Postgres databases for Alchemy.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"alchemy",
|
|
@@ -58,22 +58,22 @@
|
|
|
58
58
|
"access": "public"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@alchemy.run/sql": "2.0.0-beta.
|
|
62
|
-
"@distilled.cloud/core": "1.0.0-rc.
|
|
63
|
-
"@distilled.cloud/planetscale": "1.0.0-rc.
|
|
61
|
+
"@alchemy.run/sql": "2.0.0-beta.86",
|
|
62
|
+
"@distilled.cloud/core": "1.0.0-rc.19",
|
|
63
|
+
"@distilled.cloud/planetscale": "1.0.0-rc.19"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@types/bun": "1.4.3",
|
|
67
67
|
"@types/pg": "^8.20.0",
|
|
68
|
-
"alchemy": "2.0.0-beta.
|
|
69
|
-
"effect": "^4.
|
|
68
|
+
"alchemy": "2.0.0-beta.86",
|
|
69
|
+
"effect": "^4.1.4",
|
|
70
70
|
"mysql2": "^3.24.2",
|
|
71
71
|
"pg": "^8.22.0",
|
|
72
|
-
"typescript": "^7.0.
|
|
72
|
+
"typescript": "^7.1.0-dev.20261105.1"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
|
-
"alchemy": "2.0.0-beta.
|
|
76
|
-
"effect": "^4.
|
|
75
|
+
"alchemy": "2.0.0-beta.86",
|
|
76
|
+
"effect": "^4.1.4",
|
|
77
77
|
"mysql2": "^3.24.2",
|
|
78
78
|
"pg": "^8.22.0"
|
|
79
79
|
},
|
package/src/AuthProvider.ts
CHANGED
|
@@ -67,7 +67,6 @@ const withOAuthCredentials = <A, E, R>(
|
|
|
67
67
|
*/
|
|
68
68
|
const selectOrganization = (accessToken: string) =>
|
|
69
69
|
Effect.gen(function* () {
|
|
70
|
-
const interaction = Interaction.accessors;
|
|
71
70
|
const list = yield* listOrganizations;
|
|
72
71
|
const response = yield* list({});
|
|
73
72
|
const orgs = response.data;
|
|
@@ -83,19 +82,17 @@ const selectOrganization = (accessToken: string) =>
|
|
|
83
82
|
message: "Planetscale: organization response was unexpectedly empty.",
|
|
84
83
|
});
|
|
85
84
|
}
|
|
86
|
-
yield*
|
|
85
|
+
yield* Interaction.info(`Planetscale: using organization: ${org.name} (${org.id})`);
|
|
87
86
|
return org.name;
|
|
88
87
|
}
|
|
89
|
-
return yield*
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
})
|
|
98
|
-
.pipe(mapPromptCancellation);
|
|
88
|
+
return yield* Interaction.select({
|
|
89
|
+
message: "Select a Planetscale organization",
|
|
90
|
+
options: orgs.map((o) => ({
|
|
91
|
+
value: o.name,
|
|
92
|
+
label: o.name,
|
|
93
|
+
description: o.id,
|
|
94
|
+
})),
|
|
95
|
+
}).pipe(mapPromptCancellation);
|
|
99
96
|
}).pipe((e) => withOAuthCredentials(accessToken, e));
|
|
100
97
|
|
|
101
98
|
const options: Array<{
|
|
@@ -182,7 +179,6 @@ export const PlanetscaleAuth = AuthProviderLayer<
|
|
|
182
179
|
>()(
|
|
183
180
|
PLANETSCALE_AUTH_PROVIDER_NAME,
|
|
184
181
|
Effect.gen(function* () {
|
|
185
|
-
const interaction = Interaction.accessors;
|
|
186
182
|
const oauthLogin = (_profileName: string) =>
|
|
187
183
|
Effect.gen(function* () {
|
|
188
184
|
const authorization = yield* OAuthClient.authorize();
|
|
@@ -193,7 +189,7 @@ export const PlanetscaleAuth = AuthProviderLayer<
|
|
|
193
189
|
callback: OAuthClient.callback(authorization),
|
|
194
190
|
exchange: (input) => OAuthClient.exchangeCallbackInput(input, authorization),
|
|
195
191
|
});
|
|
196
|
-
yield*
|
|
192
|
+
yield* Interaction.success("Planetscale: OAuth credentials saved.");
|
|
197
193
|
return credentials;
|
|
198
194
|
});
|
|
199
195
|
|
|
@@ -210,15 +206,13 @@ export const PlanetscaleAuth = AuthProviderLayer<
|
|
|
210
206
|
selectOrganization,
|
|
211
207
|
Effect.catch((e) =>
|
|
212
208
|
Effect.gen(function* () {
|
|
213
|
-
yield*
|
|
209
|
+
yield* Interaction.warning(
|
|
214
210
|
`Planetscale: could not auto-list organizations (${String(e)}). Falling back to manual entry.`,
|
|
215
211
|
);
|
|
216
|
-
return yield*
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
})
|
|
221
|
-
.pipe(mapPromptCancellation);
|
|
212
|
+
return yield* Interaction.text({
|
|
213
|
+
message: "Planetscale Organization (URL slug)",
|
|
214
|
+
validate: (v) => (v.length === 0 ? "Required" : undefined),
|
|
215
|
+
}).pipe(mapPromptCancellation);
|
|
222
216
|
}),
|
|
223
217
|
),
|
|
224
218
|
);
|
|
@@ -235,46 +229,38 @@ export const PlanetscaleAuth = AuthProviderLayer<
|
|
|
235
229
|
});
|
|
236
230
|
|
|
237
231
|
const loginStored = Effect.fn(function* (_profileName: string) {
|
|
238
|
-
const tokenId = yield*
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
})
|
|
243
|
-
.pipe(mapPromptCancellation);
|
|
232
|
+
const tokenId = yield* Interaction.text({
|
|
233
|
+
message: "Planetscale Service Token ID",
|
|
234
|
+
validate: (v) => (v.length === 0 ? "Required" : undefined),
|
|
235
|
+
}).pipe(mapPromptCancellation);
|
|
244
236
|
|
|
245
|
-
const token = yield*
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
})
|
|
250
|
-
.pipe(mapPromptCancellation);
|
|
237
|
+
const token = yield* Interaction.password({
|
|
238
|
+
message: "Planetscale Service Token",
|
|
239
|
+
validate: (v) => (v.length === 0 ? "Required" : undefined),
|
|
240
|
+
}).pipe(mapPromptCancellation);
|
|
251
241
|
|
|
252
|
-
const organization = yield*
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
})
|
|
257
|
-
.pipe(mapPromptCancellation);
|
|
242
|
+
const organization = yield* Interaction.text({
|
|
243
|
+
message: "Planetscale Organization (URL slug)",
|
|
244
|
+
validate: (v) => (v.length === 0 ? "Required" : undefined),
|
|
245
|
+
}).pipe(mapPromptCancellation);
|
|
258
246
|
|
|
259
|
-
yield*
|
|
247
|
+
yield* Interaction.success("Planetscale: credentials saved.");
|
|
260
248
|
return { method: "stored" as const, tokenId, token, organization };
|
|
261
249
|
});
|
|
262
250
|
|
|
263
251
|
const configureInteractive = (profileName: string) =>
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
Match.
|
|
272
|
-
|
|
273
|
-
Match.when("stored", () => loginStored(profileName)),
|
|
274
|
-
Match.exhaustive,
|
|
275
|
-
),
|
|
252
|
+
Interaction.select({
|
|
253
|
+
message: "Planetscale authentication method",
|
|
254
|
+
options,
|
|
255
|
+
}).pipe(
|
|
256
|
+
Effect.flatMap((method) =>
|
|
257
|
+
Match.value(method).pipe(
|
|
258
|
+
Match.when("oauth", () => configureOAuth(profileName)),
|
|
259
|
+
Match.when("stored", () => loginStored(profileName)),
|
|
260
|
+
Match.exhaustive,
|
|
276
261
|
),
|
|
277
|
-
)
|
|
262
|
+
),
|
|
263
|
+
);
|
|
278
264
|
|
|
279
265
|
const configureCredentials = (profileName: string) =>
|
|
280
266
|
configureInteractive(profileName).pipe(
|
|
@@ -321,7 +307,7 @@ export const PlanetscaleAuth = AuthProviderLayer<
|
|
|
321
307
|
token: Redacted.value(storedSecret(values.token) ?? Redacted.make("")),
|
|
322
308
|
organization: storedValueText(values.organization) ?? "",
|
|
323
309
|
})),
|
|
324
|
-
Effect.tap(() =>
|
|
310
|
+
Effect.tap(() => Interaction.success("Planetscale: credentials saved.")),
|
|
325
311
|
)
|
|
326
312
|
: Effect.fail(
|
|
327
313
|
AuthError.make({
|
|
@@ -420,6 +406,7 @@ export const PlanetscaleAuth = AuthProviderLayer<
|
|
|
420
406
|
profileName: string,
|
|
421
407
|
config: PlanetscaleAuthConfig,
|
|
422
408
|
updateConfig?: (config: PlanetscaleAuthConfig) => Effect.Effect<void, AuthError>,
|
|
409
|
+
reload?: Effect.Effect<PlanetscaleAuthConfig, AuthError>,
|
|
423
410
|
) =>
|
|
424
411
|
Match.value(config).pipe(
|
|
425
412
|
Match.when({ method: "stored" }, (stored) => Effect.succeed(stored)),
|
|
@@ -436,25 +423,50 @@ export const PlanetscaleAuth = AuthProviderLayer<
|
|
|
436
423
|
if (!OAuthClient.usesCurrentClient(credentials)) {
|
|
437
424
|
return yield* configureOAuth(profileName);
|
|
438
425
|
}
|
|
439
|
-
|
|
426
|
+
// Refresh tokens are single-use: refresh with the token stored
|
|
427
|
+
// now, read under the lock, not the one `config` was read with.
|
|
428
|
+
const outcome = yield* withProfileCredentialsLock(
|
|
440
429
|
profileName,
|
|
441
|
-
|
|
442
|
-
Effect.
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
430
|
+
Effect.gen(function* () {
|
|
431
|
+
const current = yield* reload ?? Effect.succeed(oauth);
|
|
432
|
+
if (current.method !== "oauth") return { type: "browser" as const };
|
|
433
|
+
const currentCredentials: OAuthClient.OAuthCredentials = {
|
|
434
|
+
type: "oauth",
|
|
435
|
+
clientId: current.clientId,
|
|
436
|
+
access: Redacted.make(current.access),
|
|
437
|
+
refresh: Redacted.make(current.refresh),
|
|
438
|
+
expires: current.expires,
|
|
439
|
+
scopes: current.scopes,
|
|
440
|
+
};
|
|
441
|
+
if (!OAuthClient.usesCurrentClient(currentCredentials)) {
|
|
442
|
+
return { type: "browser" as const };
|
|
443
|
+
}
|
|
444
|
+
return yield* Interaction.info("Planetscale: refreshing OAuth credentials...").pipe(
|
|
445
|
+
Effect.andThen(OAuthClient.refresh(currentCredentials)),
|
|
446
|
+
Effect.flatMap((credentials) => {
|
|
447
|
+
const config = {
|
|
448
|
+
...current,
|
|
449
|
+
clientId: credentials.clientId,
|
|
450
|
+
access: Redacted.value(credentials.access),
|
|
451
|
+
refresh: Redacted.value(credentials.refresh),
|
|
452
|
+
expires: credentials.expires,
|
|
453
|
+
scopes: credentials.scopes,
|
|
454
|
+
};
|
|
455
|
+
// Saved here, under the lock, when the caller can take it;
|
|
456
|
+
// otherwise handed back for the caller to save.
|
|
457
|
+
const unsaved: Effect.Effect<typeof config | undefined, AuthError> =
|
|
458
|
+
updateConfig === undefined
|
|
459
|
+
? Effect.succeed(config)
|
|
460
|
+
: Effect.as(updateConfig(config), undefined);
|
|
461
|
+
return unsaved.pipe(
|
|
462
|
+
Effect.map((config) => ({ type: "refreshed" as const, config })),
|
|
463
|
+
);
|
|
464
|
+
}),
|
|
465
|
+
Effect.tap(() =>
|
|
466
|
+
Interaction.success("Planetscale: OAuth credentials refreshed."),
|
|
467
|
+
),
|
|
468
|
+
);
|
|
469
|
+
}),
|
|
458
470
|
).pipe(
|
|
459
471
|
Effect.catchTag(
|
|
460
472
|
[
|
|
@@ -463,10 +475,13 @@ export const PlanetscaleAuth = AuthProviderLayer<
|
|
|
463
475
|
"OAuthServerUnavailable",
|
|
464
476
|
"OAuthInvalidResponse",
|
|
465
477
|
],
|
|
466
|
-
() =>
|
|
478
|
+
() => Effect.succeed({ type: "browser" as const }),
|
|
467
479
|
),
|
|
468
480
|
);
|
|
469
|
-
|
|
481
|
+
if (outcome.type === "browser") {
|
|
482
|
+
return yield* configureOAuth(profileName);
|
|
483
|
+
}
|
|
484
|
+
return outcome.config;
|
|
470
485
|
}),
|
|
471
486
|
),
|
|
472
487
|
Match.exhaustive,
|
|
@@ -483,10 +498,8 @@ export const PlanetscaleAuth = AuthProviderLayer<
|
|
|
483
498
|
Clock.currentTimeMillis,
|
|
484
499
|
]).pipe(
|
|
485
500
|
Effect.map(([creds, now]): ProviderDetails => {
|
|
486
|
-
const
|
|
487
|
-
|
|
488
|
-
? `${creds.source.type} - ${creds.source.details}`
|
|
489
|
-
: creds.source.type;
|
|
501
|
+
const source: PlanetscaleResolvedCredentials["source"] = creds.source;
|
|
502
|
+
const sourceStr = source.details ? `${source.type} - ${source.details}` : source.type;
|
|
490
503
|
return Match.value(creds).pipe(
|
|
491
504
|
Match.when({ type: "apiToken" }, (c) => ({
|
|
492
505
|
lines: [
|
package/src/Branch.ts
CHANGED
|
@@ -73,7 +73,12 @@ export interface BaseBranchProps {
|
|
|
73
73
|
* Adding a file is an in-place update. Editing or removing an
|
|
74
74
|
* already-applied file replaces a non-production branch (re-forked from
|
|
75
75
|
* its parent) and fails on a current or desired production branch — add
|
|
76
|
-
* a forward migration instead.
|
|
76
|
+
* a forward migration instead. Renaming an applied file without changing
|
|
77
|
+
* its contents keeps it applied and replaces nothing.
|
|
78
|
+
*
|
|
79
|
+
* History is linear: a new file must sort after every applied one, or
|
|
80
|
+
* the deploy fails with `NonLinearMigrationHistoryError`. See
|
|
81
|
+
* [Migrations](https://alchemy.run/sql/effect-sql/migrations#change-migration-history-safely).
|
|
77
82
|
*/
|
|
78
83
|
migrations?: MigrationsInput;
|
|
79
84
|
|
|
@@ -361,6 +366,34 @@ export const makeBranchProvider = <R extends ResourceLike>(opts: {
|
|
|
361
366
|
return stables ? ({ action: "noop", stables } as const) : undefined;
|
|
362
367
|
}),
|
|
363
368
|
|
|
369
|
+
lookup: Effect.fn(function* ({ database, name }: any) {
|
|
370
|
+
const { organization } = yield* yield* Credentials;
|
|
371
|
+
return yield* planetscale.getBranch({ organization, database, branch: name }).pipe(
|
|
372
|
+
Effect.map(
|
|
373
|
+
(data) =>
|
|
374
|
+
({
|
|
375
|
+
name: data.name,
|
|
376
|
+
organization,
|
|
377
|
+
database,
|
|
378
|
+
parentBranch: data.parent_branch ?? "main",
|
|
379
|
+
production: data.production,
|
|
380
|
+
createdAt: data.created_at,
|
|
381
|
+
updatedAt: data.updated_at,
|
|
382
|
+
htmlUrl: data.html_url,
|
|
383
|
+
region: { slug: data.region.slug },
|
|
384
|
+
migrationsDir: undefined,
|
|
385
|
+
migrationsTable: undefined,
|
|
386
|
+
migrationsHashes: {},
|
|
387
|
+
importHashes: {},
|
|
388
|
+
desiredReplicas: undefined,
|
|
389
|
+
hasReplicas: data.has_replicas,
|
|
390
|
+
hasReadOnlyReplicas: data.has_read_only_replicas,
|
|
391
|
+
}) satisfies BaseBranchAttributes,
|
|
392
|
+
),
|
|
393
|
+
Effect.catchTag("NotFound", () => Effect.undefined),
|
|
394
|
+
);
|
|
395
|
+
}),
|
|
396
|
+
|
|
364
397
|
read: Effect.fn(function* ({ id, olds, output }: any) {
|
|
365
398
|
// If we have neither a cached output nor a usable `olds.database`
|
|
366
399
|
// there's no way to identify which branch to refresh — most often
|
|
@@ -412,7 +445,7 @@ export const makeBranchProvider = <R extends ResourceLike>(opts: {
|
|
|
412
445
|
|
|
413
446
|
return output ? attrs : Unowned(attrs);
|
|
414
447
|
}),
|
|
415
|
-
Effect.catchTag("NotFound", () => Effect.
|
|
448
|
+
Effect.catchTag("NotFound", () => Effect.undefined),
|
|
416
449
|
);
|
|
417
450
|
}),
|
|
418
451
|
|
|
@@ -440,7 +473,7 @@ export const makeBranchProvider = <R extends ResourceLike>(opts: {
|
|
|
440
473
|
database: databaseName,
|
|
441
474
|
branch: observedBranchName,
|
|
442
475
|
})
|
|
443
|
-
.pipe(Effect.catchTag("NotFound", () => Effect.
|
|
476
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.undefined));
|
|
444
477
|
|
|
445
478
|
// Ensure — if missing, create. The parent must be ready before
|
|
446
479
|
// the child can fork from it. PostgreSQL short cluster sizes need
|
package/src/Credentials.ts
CHANGED
|
@@ -4,19 +4,13 @@ import {
|
|
|
4
4
|
Credentials,
|
|
5
5
|
DEFAULT_API_BASE_URL,
|
|
6
6
|
} from "@distilled.cloud/planetscale/Credentials";
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
deferUntilFirstUse,
|
|
10
|
-
orDieCredentialsUnavailable,
|
|
11
|
-
resolveProviderConfig,
|
|
12
|
-
} from "alchemy/Auth/Resolve";
|
|
7
|
+
import { lazyCredentials } from "alchemy/Auth/Resolve";
|
|
13
8
|
import * as Config from "effect/Config";
|
|
14
9
|
import * as Effect from "effect/Effect";
|
|
15
10
|
import * as Layer from "effect/Layer";
|
|
16
11
|
import * as Redacted from "effect/Redacted";
|
|
17
12
|
import {
|
|
18
13
|
PLANETSCALE_AUTH_PROVIDER_NAME,
|
|
19
|
-
type PlanetscaleAuthConfig,
|
|
20
14
|
type PlanetscaleResolvedCredentials,
|
|
21
15
|
} from "./AuthProvider.ts";
|
|
22
16
|
|
|
@@ -69,32 +63,13 @@ export const fromAuthProvider = () =>
|
|
|
69
63
|
const apiBaseUrl = yield* Config.String("PLANETSCALE_API_BASE_URL").pipe(
|
|
70
64
|
Config.withDefault(DEFAULT_API_BASE_URL),
|
|
71
65
|
);
|
|
72
|
-
// Defer profile lookup and credential resolution until first use, so
|
|
73
|
-
// building the provider layers never requires a configured profile.
|
|
74
|
-
const resolve = yield* resolveProviderConfig<
|
|
75
|
-
PlanetscaleAuthConfig,
|
|
76
|
-
PlanetscaleResolvedCredentials
|
|
77
|
-
>(PLANETSCALE_AUTH_PROVIDER_NAME).pipe(
|
|
78
|
-
Effect.flatMap(({ profileName, resolve }) =>
|
|
79
|
-
Effect.mapError(resolve, (e) =>
|
|
80
|
-
ConfigError.make({
|
|
81
|
-
message: `Failed to resolve Planetscale credentials from ${profileName === undefined ? "the CI environment" : `profile '${profileName}'`}: ${e.message}`,
|
|
82
|
-
}),
|
|
83
|
-
),
|
|
84
|
-
),
|
|
85
|
-
deferUntilFirstUse,
|
|
86
|
-
);
|
|
87
|
-
|
|
88
66
|
// Cache until shortly before the OAuth token expires (service tokens
|
|
89
67
|
// never expire) so a long `alchemy dev` session re-resolves — and
|
|
90
68
|
// thereby refreshes — the token instead of keeping the first, by then
|
|
91
|
-
// dead, resolution forever.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
creds
|
|
95
|
-
);
|
|
96
|
-
return cached.pipe(
|
|
97
|
-
Effect.map((creds): PlanetscaleClientConfig =>
|
|
69
|
+
// dead, resolution forever.
|
|
70
|
+
return yield* lazyCredentials<PlanetscaleResolvedCredentials, ConfigError>()(
|
|
71
|
+
PLANETSCALE_AUTH_PROVIDER_NAME,
|
|
72
|
+
(creds): PlanetscaleClientConfig =>
|
|
98
73
|
creds.type === "oauth"
|
|
99
74
|
? {
|
|
100
75
|
type: "oauth",
|
|
@@ -109,8 +84,9 @@ export const fromAuthProvider = () =>
|
|
|
109
84
|
organization: creds.organization,
|
|
110
85
|
apiBaseUrl,
|
|
111
86
|
},
|
|
112
|
-
|
|
113
|
-
|
|
87
|
+
{
|
|
88
|
+
expiresAt: (creds) => (creds.type === "oauth" ? creds.expires : undefined),
|
|
89
|
+
},
|
|
114
90
|
);
|
|
115
91
|
}),
|
|
116
92
|
);
|
package/src/Database.ts
CHANGED
|
@@ -84,6 +84,13 @@ export interface BaseDatabaseProps {
|
|
|
84
84
|
* one-way conversion on first deploy: the old tool's applied history is
|
|
85
85
|
* copied into Alchemy's table and the old table is left frozen. No
|
|
86
86
|
* baselining required.
|
|
87
|
+
*
|
|
88
|
+
* History is forward-only and linear. A new file must sort after every
|
|
89
|
+
* applied one, or the deploy fails with `NonLinearMigrationHistoryError`;
|
|
90
|
+
* an edited or deleted applied file fails with
|
|
91
|
+
* `RewrittenMigrationHistoryError`. Renaming an applied file without
|
|
92
|
+
* changing its contents keeps it applied. See
|
|
93
|
+
* [Migrations](https://alchemy.run/sql/effect-sql/migrations#change-migration-history-safely).
|
|
87
94
|
*/
|
|
88
95
|
migrations?: MigrationsInput;
|
|
89
96
|
|
package/src/MySQL/MySQLBranch.ts
CHANGED
|
@@ -91,10 +91,36 @@ export type MySQLBranch = Resource<
|
|
|
91
91
|
MySQLBranchProps,
|
|
92
92
|
MySQLBranchAttributes,
|
|
93
93
|
never,
|
|
94
|
-
Providers
|
|
94
|
+
Providers,
|
|
95
|
+
MySQLBranchLookup
|
|
95
96
|
>;
|
|
96
97
|
|
|
97
|
-
/**
|
|
98
|
+
/**
|
|
99
|
+
* Props for {@link MySQLBranch.lookup}: find a MySQL branch this
|
|
100
|
+
* stack doesn't manage by its database and name.
|
|
101
|
+
*/
|
|
102
|
+
export interface MySQLBranchLookup {
|
|
103
|
+
/** Database name. */
|
|
104
|
+
database: string;
|
|
105
|
+
/** Branch name. */
|
|
106
|
+
name: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* A branch of a PlanetScale MySQL database.
|
|
111
|
+
*
|
|
112
|
+
* ### Looking up an existing MySQL branch
|
|
113
|
+
* `MySQLBranch.lookup` references a MySQL branch Alchemy doesn't manage (created in
|
|
114
|
+
* the PlanetScale dashboard or by another stack). It is read during
|
|
115
|
+
* plan/deploy, never created, updated or deleted.
|
|
116
|
+
*
|
|
117
|
+
* **Example:** Reference an existing branch
|
|
118
|
+
* ```typescript
|
|
119
|
+
* const main = Planetscale.MySQLBranch.lookup({ database: "app", name: "main" });
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @resource
|
|
123
|
+
*/
|
|
98
124
|
export const MySQLBranch = Resource<MySQLBranch>("Planetscale.MySQLBranch");
|
|
99
125
|
|
|
100
126
|
export const MySQLBranchProvider = () =>
|
|
@@ -87,7 +87,7 @@ export const observeDefaultKeyspaceReplicas = Effect.fn(function* (
|
|
|
87
87
|
) {
|
|
88
88
|
return yield* observeDefaultKeyspace(organization, database, branch).pipe(
|
|
89
89
|
Effect.map((keyspace) => keyspace?.replicas),
|
|
90
|
-
Effect.catchTag("NotFound", () => Effect.
|
|
90
|
+
Effect.catchTag("NotFound", () => Effect.undefined),
|
|
91
91
|
);
|
|
92
92
|
});
|
|
93
93
|
|