alchemy 2.0.0-beta.75 → 2.0.0-beta.76

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 (69) hide show
  1. package/bin/exec.js +1 -1
  2. package/lib/AWS/Cognito/ManagedLoginBranding.d.ts +108 -0
  3. package/lib/AWS/Cognito/ManagedLoginBranding.d.ts.map +1 -0
  4. package/lib/AWS/Cognito/ManagedLoginBranding.js +200 -0
  5. package/lib/AWS/Cognito/ManagedLoginBranding.js.map +1 -0
  6. package/lib/AWS/Cognito/UserPool.d.ts +80 -0
  7. package/lib/AWS/Cognito/UserPool.d.ts.map +1 -1
  8. package/lib/AWS/Cognito/UserPool.js +72 -4
  9. package/lib/AWS/Cognito/UserPool.js.map +1 -1
  10. package/lib/AWS/Cognito/index.d.ts +1 -0
  11. package/lib/AWS/Cognito/index.d.ts.map +1 -1
  12. package/lib/AWS/Cognito/index.js +1 -0
  13. package/lib/AWS/Cognito/index.js.map +1 -1
  14. package/lib/AWS/Providers.d.ts.map +1 -1
  15. package/lib/AWS/Providers.js +2 -1
  16. package/lib/AWS/Providers.js.map +1 -1
  17. package/lib/AWS/Website/StaticSite.d.ts.map +1 -1
  18. package/lib/AWS/Website/StaticSite.js +8 -4
  19. package/lib/AWS/Website/StaticSite.js.map +1 -1
  20. package/lib/Cli/commands/dev.d.ts +13 -1
  21. package/lib/Cli/commands/dev.d.ts.map +1 -1
  22. package/lib/Cli/commands/dev.js +12 -5
  23. package/lib/Cli/commands/dev.js.map +1 -1
  24. package/lib/Cloudflare/Email/AllowPolicy.d.ts.map +1 -1
  25. package/lib/Cloudflare/Email/AllowPolicy.js +9 -3
  26. package/lib/Cloudflare/Email/AllowPolicy.js.map +1 -1
  27. package/lib/Cloudflare/Email/ImpersonationRegistryEntry.d.ts.map +1 -1
  28. package/lib/Cloudflare/Email/ImpersonationRegistryEntry.js +10 -1
  29. package/lib/Cloudflare/Email/ImpersonationRegistryEntry.js.map +1 -1
  30. package/lib/Cloudflare/Email/TrustedDomain.d.ts.map +1 -1
  31. package/lib/Cloudflare/Email/TrustedDomain.js +10 -1
  32. package/lib/Cloudflare/Email/TrustedDomain.js.map +1 -1
  33. package/lib/Cloudflare/Workers/Assets.d.ts +1 -1
  34. package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
  35. package/lib/Cloudflare/Workers/Assets.js +14 -7
  36. package/lib/Cloudflare/Workers/Assets.js.map +1 -1
  37. package/lib/Cloudflare/Workers/WorkerProvider.d.ts.map +1 -1
  38. package/lib/Cloudflare/Workers/WorkerProvider.js +1 -1
  39. package/lib/Cloudflare/Workers/WorkerProvider.js.map +1 -1
  40. package/lib/Command/Dev.d.ts.map +1 -1
  41. package/lib/Command/Dev.js +6 -1
  42. package/lib/Command/Dev.js.map +1 -1
  43. package/lib/Planetscale/Postgres/PostgresDefaultRole.d.ts +8 -0
  44. package/lib/Planetscale/Postgres/PostgresDefaultRole.d.ts.map +1 -1
  45. package/lib/Planetscale/Postgres/PostgresDefaultRole.js +17 -5
  46. package/lib/Planetscale/Postgres/PostgresDefaultRole.js.map +1 -1
  47. package/lib/Planetscale/Postgres/PostgresRole.d.ts +8 -0
  48. package/lib/Planetscale/Postgres/PostgresRole.d.ts.map +1 -1
  49. package/lib/Planetscale/Postgres/PostgresRole.js +2 -0
  50. package/lib/Planetscale/Postgres/PostgresRole.js.map +1 -1
  51. package/lib/Website/Server.d.ts.map +1 -1
  52. package/lib/Website/Server.js +11 -1
  53. package/lib/Website/Server.js.map +1 -1
  54. package/package.json +6 -6
  55. package/src/AWS/Cognito/ManagedLoginBranding.ts +339 -0
  56. package/src/AWS/Cognito/UserPool.ts +144 -6
  57. package/src/AWS/Cognito/index.ts +1 -0
  58. package/src/AWS/Providers.ts +4 -0
  59. package/src/AWS/Website/StaticSite.ts +8 -4
  60. package/src/Cli/commands/dev.ts +13 -6
  61. package/src/Cloudflare/Email/AllowPolicy.ts +9 -3
  62. package/src/Cloudflare/Email/ImpersonationRegistryEntry.ts +9 -1
  63. package/src/Cloudflare/Email/TrustedDomain.ts +9 -1
  64. package/src/Cloudflare/Workers/Assets.ts +14 -6
  65. package/src/Cloudflare/Workers/WorkerProvider.ts +1 -0
  66. package/src/Command/Dev.ts +9 -1
  67. package/src/Planetscale/Postgres/PostgresDefaultRole.ts +27 -5
  68. package/src/Planetscale/Postgres/PostgresRole.ts +12 -0
  69. package/src/Website/Server.ts +16 -1
@@ -142,7 +142,15 @@ export const ImpersonationRegistryEntryProvider = () =>
142
142
  ),
143
143
  ),
144
144
  ),
145
- Effect.catchTag("EmailSecurityNotEntitled", () =>
145
+ // Email Security is a paid add-on gated by both account
146
+ // entitlement and token scope: an unentitled account answers
147
+ // `EmailSecurityNotEntitled`, while a credential lacking the
148
+ // Email Security scope (e.g. Cloudflare OAuth) answers a bare
149
+ // `Forbidden`. Neither can enumerate, so both mean "none
150
+ // visible" — matching `Domain.list()`. Returning `[]` is the
151
+ // safe direction for the callers of `list` (orphan detection
152
+ // never deletes what it cannot see).
153
+ Effect.catchTag(["EmailSecurityNotEntitled", "Forbidden"], () =>
146
154
  Effect.succeed([] as ImpersonationRegistryEntryAttributes[]),
147
155
  ),
148
156
  );
@@ -138,7 +138,15 @@ export const TrustedDomainProvider = () =>
138
138
  ),
139
139
  ),
140
140
  ),
141
- Effect.catchTag("EmailSecurityNotEntitled", () =>
141
+ // Email Security is a paid add-on gated by both account
142
+ // entitlement and token scope: an unentitled account answers
143
+ // `EmailSecurityNotEntitled`, while a credential lacking the
144
+ // Email Security scope (e.g. Cloudflare OAuth) answers a bare
145
+ // `Forbidden`. Neither can enumerate, so both mean "none
146
+ // visible" — matching `Domain.list()`. Returning `[]` is the
147
+ // safe direction for the callers of `list` (orphan detection
148
+ // never deletes what it cannot see).
149
+ Effect.catchTag(["EmailSecurityNotEntitled", "Forbidden"], () =>
142
150
  Effect.succeed([] as TrustedDomainAttributes[]),
143
151
  ),
144
152
  );
@@ -1,4 +1,5 @@
1
1
  import * as workers from "@distilled.cloud/cloudflare/workers";
2
+ import * as wfp from "@distilled.cloud/cloudflare/workers-for-platforms";
2
3
  import * as Data from "effect/Data";
3
4
  import * as Effect from "effect/Effect";
4
5
  import * as FileSystem from "effect/FileSystem";
@@ -428,10 +429,10 @@ export const uploadAssets = Effect.fn(function* (
428
429
  workerName: string,
429
430
  assets: AssetReadResult,
430
431
  { note }: ScopedPlanStatusSession,
432
+ dispatchNamespace?: string,
431
433
  ) {
432
434
  const fs = yield* FileSystem.FileSystem;
433
435
  const path = yield* Path.Path;
434
- const createScriptAssetUpload = yield* workers.createScriptAssetUpload;
435
436
  const createAssetUpload = yield* workers.createAssetUpload;
436
437
 
437
438
  // Manifest keys are the paths Cloudflare *serves*, so they carry the
@@ -463,11 +464,18 @@ export const uploadAssets = Effect.fn(function* (
463
464
  // the completion JWT directly.
464
465
  const runSession = Effect.fn(function* () {
465
466
  yield* note("Checking assets...");
466
- const session = yield* createScriptAssetUpload({
467
- accountId,
468
- scriptName: workerName,
469
- manifest: assets.manifest,
470
- });
467
+ const session = dispatchNamespace
468
+ ? yield* wfp.createDispatchNamespaceScriptAssetUpload({
469
+ accountId,
470
+ dispatchNamespace,
471
+ scriptName: workerName,
472
+ manifest: assets.manifest,
473
+ })
474
+ : yield* workers.createScriptAssetUpload({
475
+ accountId,
476
+ scriptName: workerName,
477
+ manifest: assets.manifest,
478
+ });
471
479
  if (!session.buckets?.length) {
472
480
  if (!session.jwt) {
473
481
  return yield* new AssetUploadSessionError({
@@ -3234,6 +3234,7 @@ export const LiveWorkerProvider = () =>
3234
3234
  name,
3235
3235
  assets,
3236
3236
  session,
3237
+ dispatchNamespace,
3237
3238
  );
3238
3239
  metadataAssets = {
3239
3240
  jwt,
@@ -218,7 +218,15 @@ const ANSI_REGEX = /\x1b\[[0-9;]*m/g;
218
218
  */
219
219
  export const extractUrl = (text: string) => {
220
220
  const clean = text.replaceAll(ANSI_REGEX, "");
221
- return clean.match(LOCAL_URL_REGEX)?.[0] ?? clean.match(URL_REGEX)?.[0];
221
+ const url = clean.match(LOCAL_URL_REGEX)?.[0] ?? clean.match(URL_REGEX)?.[0];
222
+ // Some dev servers print their *bind* address (Nuxt: `http://0.0.0.0:3000`),
223
+ // which is not a connectable host. Normalize the unspecified address to
224
+ // `localhost` so consumers of `url` — browser links, Router dev routing,
225
+ // the emulated CloudFront edge dialing the origin — can actually reach it.
226
+ return url?.replace(
227
+ /^(https?:\/\/)(?:0\.0\.0\.0|\[::\]|\[0+:0+:0+:0+:0+:0+:0+:0+\])(?=[:/]|$)/,
228
+ "$1localhost",
229
+ );
222
230
  };
223
231
 
224
232
  const isLocalUrl = (url: string) => LOCAL_URL_REGEX.test(url);
@@ -64,6 +64,14 @@ export interface PostgresDefaultRoleAttributes {
64
64
  connectionUrl: Redacted.Redacted<string>;
65
65
  /** Pooled connection URL via PSBouncer (Redacted). */
66
66
  connectionUrlPooled: Redacted.Redacted<string>;
67
+ /**
68
+ * Private connection host or DNS zone for this branch, supplied by
69
+ * PlanetScale. GCP Private Service Connect requires an endpoint name before
70
+ * this DNS zone.
71
+ */
72
+ privateHost: string;
73
+ /** Service name for this branch supplied by PlanetScale to establish a private connection. */
74
+ privateConnectionServiceName: string;
67
75
  /** Inherited roles. */
68
76
  inheritedRoles: InheritedRole[];
69
77
  /** Resolved organization slug. */
@@ -144,7 +152,11 @@ export const PostgresDefaultRoleProvider = () =>
144
152
  branch: output.branch,
145
153
  })
146
154
  .pipe(
147
- Effect.map(() => output),
155
+ Effect.map((role) => ({
156
+ ...output,
157
+ privateHost: role.private_access_host_url,
158
+ privateConnectionServiceName: role.private_connection_service_name,
159
+ })),
148
160
  Effect.catchTag("NotFound", () => Effect.succeed(undefined)),
149
161
  );
150
162
  }),
@@ -171,11 +183,16 @@ export const PostgresDefaultRoleProvider = () =>
171
183
 
172
184
  // 2. Sync (no-op) — we own the role and it still exists in the
173
185
  // cloud. Default roles have nothing mutable in place: their
174
- // plaintext password isn't retrievable, so we re-emit the
175
- // persisted attributes unchanged. diff() forces a replace
176
- // when database/branch change.
186
+ // plaintext password isn't retrievable, so we retain the cached
187
+ // credentials while refreshing the private connection details.
188
+ // diff() forces a replace when database/branch change.
177
189
  if (output && observed) {
178
- return output;
190
+ return {
191
+ ...output,
192
+ privateHost: observed.private_access_host_url,
193
+ privateConnectionServiceName:
194
+ observed.private_connection_service_name,
195
+ };
179
196
  }
180
197
 
181
198
  // 3. Adoption guard — observed exists but we have no prior
@@ -225,6 +242,8 @@ export const PostgresDefaultRoleProvider = () =>
225
242
  databaseName: data.database_name,
226
243
  connectionUrl: Redacted.make(connectionUrl),
227
244
  connectionUrlPooled: Redacted.make(connectionUrlPooled),
245
+ privateHost: data.private_access_host_url,
246
+ privateConnectionServiceName: data.private_connection_service_name,
228
247
  inheritedRoles: data.inherited_roles as InheritedRole[],
229
248
  organization,
230
249
  database: databaseName,
@@ -290,6 +309,9 @@ export const PostgresDefaultRoleProvider = () =>
290
309
  databaseName: role.database_name,
291
310
  connectionUrl: Redacted.make(""),
292
311
  connectionUrlPooled: Redacted.make(""),
312
+ privateHost: role.private_access_host_url,
313
+ privateConnectionServiceName:
314
+ role.private_connection_service_name,
293
315
  inheritedRoles:
294
316
  role.inherited_roles as InheritedRole[],
295
317
  organization,
@@ -117,6 +117,14 @@ export interface PostgresRoleAttributes {
117
117
  origin: PostgresOrigin;
118
118
  /** Parsed pooled (PSBouncer, port 6432) connection components, e.g. for a Hyperdrive `dev` origin. */
119
119
  pooledOrigin: PostgresOrigin;
120
+ /**
121
+ * Private connection host or DNS zone for this branch, supplied by
122
+ * PlanetScale. GCP Private Service Connect requires an endpoint name before
123
+ * this DNS zone.
124
+ */
125
+ privateHost: string;
126
+ /** Service name for this branch supplied by PlanetScale to establish a private connection. */
127
+ privateConnectionServiceName: string;
120
128
  /** Direct connection URL for the database (Redacted). */
121
129
  connectionUrl: Redacted.Redacted<string>;
122
130
  /** Pooled connection URL via PSBouncer (port 6432, Redacted). */
@@ -495,6 +503,8 @@ const buildAttributes = (
495
503
  name: string;
496
504
  expires_at: string | null;
497
505
  access_host_url: string;
506
+ private_access_host_url: string;
507
+ private_connection_service_name: string;
498
508
  username: string;
499
509
  database_name: string;
500
510
  ttl: number | null;
@@ -521,6 +531,8 @@ const buildAttributes = (
521
531
  password,
522
532
  connectionUrl: Redacted.make(connectionUrl),
523
533
  connectionUrlPooled: Redacted.make(connectionUrlPooled),
534
+ privateHost: role.private_access_host_url,
535
+ privateConnectionServiceName: role.private_connection_service_name,
524
536
  inheritedRoles: context.inheritedRoles,
525
537
  successor: context.successor,
526
538
  organization: context.organization,
@@ -456,6 +456,21 @@ const resolveDevPort = Effect.fn(function* (options: {
456
456
  );
457
457
  });
458
458
 
459
+ /**
460
+ * A framework dev server may advertise its *bind* address — nuxt echoes the
461
+ * host it was told to listen on, so a Router-attached site (which binds
462
+ * `0.0.0.0` to be reachable from the emulator container) reports
463
+ * `http://0.0.0.0:{port}/`. The unspecified address is not a connectable
464
+ * host: normalize it to `localhost` for the `url` attribute (browser links,
465
+ * Router dev routing, the emulated CloudFront edge dialing the origin). The
466
+ * server itself still listens on every interface.
467
+ */
468
+ const normalizeAdvertisedUrl = (url: string) =>
469
+ url.replace(
470
+ /^(https?:\/\/)(?:0\.0\.0\.0|\[::\]|\[0+(?::0+){7}\])(?=[:/]|$)/,
471
+ "$1localhost",
472
+ );
473
+
459
474
  /**
460
475
  * The `alchemy dev` variant: runs the framework's own dev server (native
461
476
  * HMR through the framework's kit — nuxt, astro, ...) inside the dev
@@ -536,7 +551,7 @@ export const ServerProviderLocal = () =>
536
551
  distDir: undefined,
537
552
  clientDir: undefined,
538
553
  serverEntry: undefined,
539
- url,
554
+ url: normalizeAdvertisedUrl(url),
540
555
  hash: { input: undefined, output: undefined },
541
556
  };
542
557
  }),