@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
|
-
|
|
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.
|
|
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.
|
|
21975
|
+
version: "0.45.3",
|
|
21831
21976
|
peerDependencies: {
|
|
21832
|
-
"@supabase/supabase-js": "^2.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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;
|