@supacloud/cli 0.111.0 → 0.112.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9346,7 +9346,7 @@ var ACTION_POLICY = {
9346
9346
  },
9347
9347
  secrets: { read: ["list"], write: ["upsert", "delete"] },
9348
9348
  frontend: {
9349
- read: ["list", "get", "build_logs", "list_frameworks", "list_records", "list_releases", "get_active_release", "get_release"],
9349
+ read: ["list", "get", "build_logs", "list_frameworks", "list_records", "list_releases", "get_active_release", "get_release", "verify_release"],
9350
9350
  write: ["create", "update", "delete", "deploy_git", "deploy_upload", "redeploy", "add_domain", "remove_domain", "set_env", "upload_release", "activate_release", "rollback"]
9351
9351
  },
9352
9352
  task_events: { read: ["inspect_webhook"], write: ["register_webhook", "unregister_webhook"] },
@@ -16919,6 +16919,8 @@ var TIMESTAMP_PATTERN2 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u;
16919
16919
  var ARCHIVE_MAX_BYTES = 100 * 1024 * 1024;
16920
16920
  var ARCHIVE_CHUNK_BYTES = 64 * 1024;
16921
16921
  var RESPONSE_MAX_BYTES = 1024 * 1024;
16922
+ var LIVE_RESPONSE_MAX_BYTES = 1024 * 1024;
16923
+ var LIVE_CHECK_TIMEOUT_MS = 1e4;
16922
16924
  var UPLOAD_REQUEST_TIMEOUT_MS = 10 * 60000;
16923
16925
  var MUTATION_RESPONSE_TIMEOUT_MS = 5000;
16924
16926
  var RELEASE_LIST_LIMIT_MAX = 100;
@@ -17276,6 +17278,129 @@ async function getActiveFrontendRelease(http, projectRef, deploymentId) {
17276
17278
  const snapshot = await readActiveFrontendRelease(http, projectRef, deploymentId);
17277
17279
  return "failure" in snapshot ? snapshot.failure : toolResponse(snapshot.inventory);
17278
17280
  }
17281
+ function deploymentLiveUrl(candidate) {
17282
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate))
17283
+ return null;
17284
+ const value = candidate.deployment_url;
17285
+ if (typeof value !== "string" || !value.trim())
17286
+ return null;
17287
+ try {
17288
+ const url = new URL(value.trim());
17289
+ return url.protocol === "https:" || url.protocol === "http:" ? url.toString() : null;
17290
+ } catch {
17291
+ return null;
17292
+ }
17293
+ }
17294
+ async function verifyLiveDeployment(url) {
17295
+ try {
17296
+ const response = await fetch(url, {
17297
+ method: "GET",
17298
+ redirect: "follow",
17299
+ cache: "no-store",
17300
+ signal: AbortSignal.timeout(LIVE_CHECK_TIMEOUT_MS)
17301
+ });
17302
+ const contentLength = Number(response.headers.get("content-length") ?? "");
17303
+ if (Number.isFinite(contentLength) && contentLength > LIVE_RESPONSE_MAX_BYTES) {
17304
+ response.body?.cancel().catch(() => {
17305
+ return;
17306
+ });
17307
+ return {
17308
+ ok: false,
17309
+ status: response.status,
17310
+ content_type: response.headers.get("content-type"),
17311
+ bytes: contentLength,
17312
+ error_code: "LIVE_RESPONSE_TOO_LARGE"
17313
+ };
17314
+ }
17315
+ let bytes = 0;
17316
+ const reader = response.body?.getReader();
17317
+ if (reader) {
17318
+ try {
17319
+ while (true) {
17320
+ const { done, value } = await reader.read();
17321
+ if (done)
17322
+ break;
17323
+ bytes += value.byteLength;
17324
+ if (bytes > LIVE_RESPONSE_MAX_BYTES) {
17325
+ reader.cancel().catch(() => {
17326
+ return;
17327
+ });
17328
+ break;
17329
+ }
17330
+ }
17331
+ } finally {
17332
+ reader.releaseLock();
17333
+ }
17334
+ }
17335
+ const ok = response.status === 200 && bytes > 0 && bytes <= LIVE_RESPONSE_MAX_BYTES;
17336
+ return {
17337
+ ok,
17338
+ status: response.status,
17339
+ content_type: response.headers.get("content-type"),
17340
+ bytes,
17341
+ error_code: bytes > LIVE_RESPONSE_MAX_BYTES ? "LIVE_RESPONSE_TOO_LARGE" : ok ? null : bytes === 0 ? "LIVE_RESPONSE_EMPTY" : "LIVE_RESPONSE_INVALID"
17342
+ };
17343
+ } catch (error) {
17344
+ const timedOut = error instanceof Error && (error.name === "TimeoutError" || error.name === "AbortError");
17345
+ return {
17346
+ ok: false,
17347
+ status: 0,
17348
+ content_type: null,
17349
+ bytes: 0,
17350
+ error_code: timedOut ? "LIVE_CHECK_TIMEOUT" : "LIVE_CHECK_FAILED"
17351
+ };
17352
+ }
17353
+ }
17354
+ async function verifyFrontendRelease(http, projectRef, deploymentId) {
17355
+ const snapshot = await readActiveFrontendRelease(http, projectRef, deploymentId);
17356
+ if ("failure" in snapshot)
17357
+ return snapshot.failure;
17358
+ const inventory = snapshot.inventory;
17359
+ const release = inventory.releases[0];
17360
+ if (!release)
17361
+ return releaseFailure("frontend.verify_release", "NO_ACTIVE_RELEASE", 200);
17362
+ const deployment = await http.get(deploymentEndpoint(projectRef, deploymentId), {
17363
+ maxJsonBytes: RESPONSE_MAX_BYTES
17364
+ });
17365
+ const liveUrl = deployment.ok && deployment.status === 200 ? deploymentLiveUrl(deployment.data) : null;
17366
+ const live = liveUrl ? await verifyLiveDeployment(liveUrl) : { ok: false, status: 0, content_type: null, bytes: 0, error_code: "LIVE_URL_UNAVAILABLE" };
17367
+ let errorCode = live.error_code;
17368
+ if (live.ok) {
17369
+ try {
17370
+ const readback = await readActiveFrontendRelease(http, projectRef, deploymentId);
17371
+ if ("failure" in readback)
17372
+ errorCode = "ACTIVE_RELEASE_READBACK_FAILED";
17373
+ else if (readback.inventory.active_release_id !== inventory.active_release_id || readback.inventory.active_activation_id !== inventory.active_activation_id) {
17374
+ errorCode = "STALE_AUTHORITY";
17375
+ }
17376
+ } catch {
17377
+ errorCode = "ACTIVE_RELEASE_READBACK_FAILED";
17378
+ }
17379
+ }
17380
+ const ok = errorCode === null;
17381
+ const receipt = {
17382
+ schema: "supacloud.frontend-release-verification.v1",
17383
+ ok,
17384
+ error_code: errorCode,
17385
+ project_ref: projectRef,
17386
+ deployment_id: deploymentId,
17387
+ active_release_id: inventory.active_release_id,
17388
+ active_activation_id: inventory.active_activation_id,
17389
+ release,
17390
+ live: {
17391
+ url: liveUrl,
17392
+ status: live.status,
17393
+ content_type: live.content_type,
17394
+ bytes: live.bytes,
17395
+ error_code: live.error_code
17396
+ },
17397
+ checked_at: new Date().toISOString()
17398
+ };
17399
+ return {
17400
+ content: [{ type: "text", text: JSON.stringify(receipt, null, 2) }],
17401
+ ...ok ? {} : { isError: true }
17402
+ };
17403
+ }
17279
17404
  async function publishFrontendRelease(http, projectRef, deploymentId, archiveSource, expectedTreeSha256) {
17280
17405
  const authority = await readActiveFrontendRelease(http, projectRef, deploymentId);
17281
17406
  if ("failure" in authority)
@@ -17565,7 +17690,7 @@ async function activationReadback(http, input, mutationId, activationStatus) {
17565
17690
  // src/shared/tools/frontend-tools.ts
17566
17691
  function registerFrontendTools(server, http) {
17567
17692
  registerTool(server, "frontend", `Frontend hosting and immutable prebuilt releases. Supports: static, react, vue, svelte, sveltekit, sveltekit-static, nextjs, nuxt, astro.
17568
- Actions: list, get, create, update, delete, build_logs, add_domain, remove_domain, set_env, list_frameworks, list_records, list_releases, get_active_release, get_release, rollback. Publish with supacloud deploy.`, {
17693
+ Actions: list, get, create, update, delete, build_logs, add_domain, remove_domain, set_env, list_frameworks, list_records, list_releases, get_active_release, get_release, verify_release, rollback. Publish with supacloud deploy.`, {
17569
17694
  action: withDescription(stringEnum2([
17570
17695
  "list",
17571
17696
  "get",
@@ -17581,6 +17706,7 @@ Actions: list, get, create, update, delete, build_logs, add_domain, remove_domai
17581
17706
  "list_releases",
17582
17707
  "get_active_release",
17583
17708
  "get_release",
17709
+ "verify_release",
17584
17710
  "rollback"
17585
17711
  ]), "Action"),
17586
17712
  ref: optional(String2(), "Project ref"),
@@ -17711,6 +17837,10 @@ Actions: list, get, create, update, delete, build_logs, add_domain, remove_domai
17711
17837
  need("ref", ref);
17712
17838
  need("id", id);
17713
17839
  return getActiveFrontendRelease(http, ref, id);
17840
+ case "verify_release":
17841
+ need("ref", ref);
17842
+ need("id", id);
17843
+ return verifyFrontendRelease(http, ref, id);
17714
17844
  case "rollback":
17715
17845
  need("ref", ref);
17716
17846
  need("id", id);
@@ -20671,8 +20801,23 @@ var VALID_VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
20671
20801
  var VALID_MIGRATION_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]{0,100}$/;
20672
20802
  var VALID_SCHEMA = /^[A-Za-z_][A-Za-z0-9_$]*$/;
20673
20803
  var VALID_PROJECT_REF = /^[A-Za-z0-9_-]{1,64}$/;
20804
+ var OFFICIAL_CLI_PG_TLS_ENV = new Set([
20805
+ "PGSSLMODE",
20806
+ "PGSSLROOTCERT",
20807
+ "PGSSLCERT",
20808
+ "PGSSLKEY",
20809
+ "PGSSLCRL",
20810
+ "PGSSLCRLDIR",
20811
+ "PGSSLSNI",
20812
+ "PGSSLNEGOTIATION",
20813
+ "PGSSLCOMPRESSION",
20814
+ "PGREQUIRESSL"
20815
+ ]);
20674
20816
  function isSensitiveEnvironmentKey(key) {
20675
- return key.toUpperCase().startsWith("PG") || SENSITIVE_ENV_KEY.test(key);
20817
+ const upper = key.toUpperCase();
20818
+ if (OFFICIAL_CLI_PG_TLS_ENV.has(upper))
20819
+ return false;
20820
+ return upper.startsWith("PG") || SENSITIVE_ENV_KEY.test(upper);
20676
20821
  }
20677
20822
  function requireMigrationName(name) {
20678
20823
  if (!name || !VALID_MIGRATION_NAME.test(name)) {
@@ -20959,7 +21104,7 @@ function resolveOfficialSupabaseCommand(workdir, environment = process.env) {
20959
21104
  const version = environment.SUPABASE_CLI_VERSION?.trim();
20960
21105
  if (version) {
20961
21106
  if (!VALID_VERSION.test(version))
20962
- throw new Error("Invalid SUPABASE_CLI_VERSION; use an exact version such as 2.120.0");
21107
+ throw new Error("Invalid SUPABASE_CLI_VERSION; use an exact version such as 2.122.0");
20963
21108
  if (process.versions.bun)
20964
21109
  return [process.execPath, "x", `supabase@${version}`];
20965
21110
  if (process.platform === "win32") {
@@ -21827,9 +21972,9 @@ var starter_metadata_default = {
21827
21972
  }
21828
21973
  },
21829
21974
  sdk: {
21830
- version: "0.45.2",
21975
+ version: "0.45.3",
21831
21976
  peerDependencies: {
21832
- "@supabase/supabase-js": "^2.117.3"
21977
+ "@supabase/supabase-js": "^2.118.0"
21833
21978
  }
21834
21979
  }
21835
21980
  }
@@ -29688,8 +29833,23 @@ var VALID_VERSION2 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
29688
29833
  var VALID_MIGRATION_NAME2 = /^[A-Za-z0-9][A-Za-z0-9_-]{0,100}$/;
29689
29834
  var VALID_SCHEMA2 = /^[A-Za-z_][A-Za-z0-9_$]*$/;
29690
29835
  var VALID_PROJECT_REF2 = /^[A-Za-z0-9_-]{1,64}$/;
29836
+ var OFFICIAL_CLI_PG_TLS_ENV2 = new Set([
29837
+ "PGSSLMODE",
29838
+ "PGSSLROOTCERT",
29839
+ "PGSSLCERT",
29840
+ "PGSSLKEY",
29841
+ "PGSSLCRL",
29842
+ "PGSSLCRLDIR",
29843
+ "PGSSLSNI",
29844
+ "PGSSLNEGOTIATION",
29845
+ "PGSSLCOMPRESSION",
29846
+ "PGREQUIRESSL"
29847
+ ]);
29691
29848
  function isSensitiveEnvironmentKey2(key) {
29692
- return key.toUpperCase().startsWith("PG") || SENSITIVE_ENV_KEY2.test(key);
29849
+ const upper = key.toUpperCase();
29850
+ if (OFFICIAL_CLI_PG_TLS_ENV2.has(upper))
29851
+ return false;
29852
+ return upper.startsWith("PG") || SENSITIVE_ENV_KEY2.test(upper);
29693
29853
  }
29694
29854
  function requireMigrationName2(name) {
29695
29855
  if (!name || !VALID_MIGRATION_NAME2.test(name)) {
@@ -29941,7 +30101,7 @@ function resolveOfficialSupabaseCommand2(workdir, environment = process.env) {
29941
30101
  const version = environment.SUPABASE_CLI_VERSION?.trim();
29942
30102
  if (version) {
29943
30103
  if (!VALID_VERSION2.test(version))
29944
- throw new Error("Invalid SUPABASE_CLI_VERSION; use an exact version such as 2.120.0");
30104
+ throw new Error("Invalid SUPABASE_CLI_VERSION; use an exact version such as 2.122.0");
29945
30105
  if (process.versions.bun)
29946
30106
  return [process.execPath, "x", `supabase@${version}`];
29947
30107
  if (process.platform === "win32") {
@@ -33421,7 +33581,7 @@ async function runProjectDeployment(http, args) {
33421
33581
  // package.json
33422
33582
  var package_default = {
33423
33583
  name: "@supacloud/cli",
33424
- version: "0.111.0",
33584
+ version: "0.112.0",
33425
33585
  description: "Project-scoped CLI for SupaCloud users",
33426
33586
  type: "module",
33427
33587
  main: "./dist/index.js",
@@ -45,6 +45,7 @@ export declare function uploadFrontendRelease(http: FrontendReleaseHttp, project
45
45
  export declare function uploadProjectWebRelease(http: FrontendReleaseHttp, projectRef: string, environmentId: string, deploymentId: string, archivePath: string): Promise<ToolResponse>;
46
46
  export declare function uploadFrontendSource(http: FrontendReleaseHttp, projectRef: string, deploymentId: string, archivePath: string): Promise<ToolResponse>;
47
47
  export declare function getActiveFrontendRelease(http: FrontendReleaseHttp, projectRef: string, deploymentId: string): Promise<ToolResponse>;
48
+ export declare function verifyFrontendRelease(http: FrontendReleaseHttp, projectRef: string, deploymentId: string): Promise<ToolResponse>;
48
49
  export declare function readFrontendReleaseAuthority(http: FrontendReleaseHttp, projectRef: string, deploymentId: string): Promise<ToolResponse>;
49
50
  export declare function publishFrontendRelease(http: FrontendReleaseHttp, projectRef: string, deploymentId: string, archiveSource: string | (() => Promise<{
50
51
  archivePath: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/cli",
3
- "version": "0.111.0",
3
+ "version": "0.112.0",
4
4
  "description": "Project-scoped CLI for SupaCloud users",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",