@supacloud/admin 0.28.0 → 0.28.3
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 +323 -88
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -24588,23 +24588,22 @@ function InstanceKeys(value) {
|
|
|
24588
24588
|
function IsIEEE754(value) {
|
|
24589
24589
|
return typeof value === "number";
|
|
24590
24590
|
}
|
|
24591
|
-
var ByteMarker
|
|
24592
|
-
|
|
24593
|
-
|
|
24594
|
-
|
|
24595
|
-
|
|
24596
|
-
|
|
24597
|
-
|
|
24598
|
-
|
|
24599
|
-
|
|
24600
|
-
|
|
24601
|
-
|
|
24602
|
-
|
|
24603
|
-
|
|
24604
|
-
|
|
24605
|
-
|
|
24606
|
-
|
|
24607
|
-
})(ByteMarker || (ByteMarker = {}));
|
|
24591
|
+
var ByteMarker = {
|
|
24592
|
+
Array: 0,
|
|
24593
|
+
BigInt: 1,
|
|
24594
|
+
Boolean: 2,
|
|
24595
|
+
Date: 3,
|
|
24596
|
+
Constructor: 4,
|
|
24597
|
+
Function: 5,
|
|
24598
|
+
Null: 6,
|
|
24599
|
+
Number: 7,
|
|
24600
|
+
Object: 8,
|
|
24601
|
+
RegExp: 9,
|
|
24602
|
+
String: 10,
|
|
24603
|
+
Symbol: 11,
|
|
24604
|
+
TypeArray: 12,
|
|
24605
|
+
Undefined: 13
|
|
24606
|
+
};
|
|
24608
24607
|
var Accumulator = BigInt("14695981039346656037");
|
|
24609
24608
|
var [Prime, Size] = [BigInt("1099511628211"), BigInt("18446744073709551616")];
|
|
24610
24609
|
var Bytes = Array.from({ length: 256 }).map((_, i) => BigInt(i));
|
|
@@ -30151,7 +30150,7 @@ function schemaProperties(schema) {
|
|
|
30151
30150
|
}
|
|
30152
30151
|
return schema;
|
|
30153
30152
|
}
|
|
30154
|
-
var DEPLOYMENT_UPGRADE = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment
|
|
30153
|
+
var DEPLOYMENT_UPGRADE = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment commands are no longer supported. Upgrade with `npm install -g @supacloud/cli@latest`, configure frontend in supacloud.json for static assets, or application.id and application.environmentId for executable application delivery, then run `supacloud deploy`. With a frontend configured, deploy publishes only Web assets; use `supacloud deploy --backend` for the application backend. `supacloud deploy --assets_only` remains an explicit Web-only option. SupaCloud owns activation; do not retry with legacy commands.";
|
|
30155
30154
|
var removedFrontendActions = new Set([
|
|
30156
30155
|
"deploy_git",
|
|
30157
30156
|
"deploy_upload",
|
|
@@ -37771,23 +37770,22 @@ function InstanceKeys2(value) {
|
|
|
37771
37770
|
function IsIEEE7542(value) {
|
|
37772
37771
|
return typeof value === "number";
|
|
37773
37772
|
}
|
|
37774
|
-
var ByteMarker2
|
|
37775
|
-
|
|
37776
|
-
|
|
37777
|
-
|
|
37778
|
-
|
|
37779
|
-
|
|
37780
|
-
|
|
37781
|
-
|
|
37782
|
-
|
|
37783
|
-
|
|
37784
|
-
|
|
37785
|
-
|
|
37786
|
-
|
|
37787
|
-
|
|
37788
|
-
|
|
37789
|
-
|
|
37790
|
-
})(ByteMarker2 || (ByteMarker2 = {}));
|
|
37773
|
+
var ByteMarker2 = {
|
|
37774
|
+
Array: 0,
|
|
37775
|
+
BigInt: 1,
|
|
37776
|
+
Boolean: 2,
|
|
37777
|
+
Date: 3,
|
|
37778
|
+
Constructor: 4,
|
|
37779
|
+
Function: 5,
|
|
37780
|
+
Null: 6,
|
|
37781
|
+
Number: 7,
|
|
37782
|
+
Object: 8,
|
|
37783
|
+
RegExp: 9,
|
|
37784
|
+
String: 10,
|
|
37785
|
+
Symbol: 11,
|
|
37786
|
+
TypeArray: 12,
|
|
37787
|
+
Undefined: 13
|
|
37788
|
+
};
|
|
37791
37789
|
var Accumulator2 = BigInt("14695981039346656037");
|
|
37792
37790
|
var [Prime2, Size2] = [BigInt("1099511628211"), BigInt("18446744073709551616")];
|
|
37793
37791
|
var Bytes2 = Array.from({ length: 256 }).map((_, i) => BigInt(i));
|
|
@@ -43306,7 +43304,7 @@ function decodedSchema2(inputSchema, outputSchema, decode, options) {
|
|
|
43306
43304
|
}
|
|
43307
43305
|
|
|
43308
43306
|
// ../cli/src/shared/deployment-upgrade.ts
|
|
43309
|
-
var DEPLOYMENT_UPGRADE2 = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment
|
|
43307
|
+
var DEPLOYMENT_UPGRADE2 = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment commands are no longer supported. Upgrade with `npm install -g @supacloud/cli@latest`, configure frontend in supacloud.json for static assets, or application.id and application.environmentId for executable application delivery, then run `supacloud deploy`. With a frontend configured, deploy publishes only Web assets; use `supacloud deploy --backend` for the application backend. `supacloud deploy --assets_only` remains an explicit Web-only option. SupaCloud owns activation; do not retry with legacy commands.";
|
|
43310
43308
|
var removedFrontendActions2 = new Set([
|
|
43311
43309
|
"deploy_git",
|
|
43312
43310
|
"deploy_upload",
|
|
@@ -43702,12 +43700,188 @@ var FRONTEND_ARCHIVE_MAX_FILES2 = 1e4;
|
|
|
43702
43700
|
var FRONTEND_ARCHIVE_MAX_SOURCE_BYTES2 = 300 * 1024 * 1024;
|
|
43703
43701
|
var FRONTEND_ARCHIVE_MAX_TAR_BYTES2 = FRONTEND_ARCHIVE_MAX_SOURCE_BYTES2 + FRONTEND_ARCHIVE_MAX_FILES2 * 2048 + 1024;
|
|
43704
43702
|
|
|
43703
|
+
// ../cli/src/shared/mutation-protocol.ts
|
|
43704
|
+
var MUTATION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
43705
|
+
var FINGERPRINT_PATTERN = /^[0-9a-f]{64}$/;
|
|
43706
|
+
var OPERATION_PATTERN = /^[a-z0-9][a-z0-9._:-]{0,127}$/;
|
|
43707
|
+
var RESOURCE_KEY_PATTERN = /^v1\/(?:[a-z0-9][a-z0-9._-]{0,63})\/([A-Za-z0-9_-]{2,171})$/;
|
|
43708
|
+
var RESOURCE_ID_CONTROL_PATTERN = /[\u0000-\u001f\u007f-\u009f]/u;
|
|
43709
|
+
var FAILURE_CODE_PATTERN = /^[A-Z][A-Z0-9_]{0,63}$/;
|
|
43710
|
+
var LEASE_OWNER_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,254}$/;
|
|
43711
|
+
var TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
43712
|
+
var MAX_RESOURCE_ID_BYTES = 128;
|
|
43713
|
+
var FATAL_UTF8_DECODER = new TextDecoder("utf-8", { fatal: true });
|
|
43714
|
+
var MUTATION_STATUSES = new Set([
|
|
43715
|
+
"pending",
|
|
43716
|
+
"running",
|
|
43717
|
+
"succeeded",
|
|
43718
|
+
"failed_retryable",
|
|
43719
|
+
"failed_terminal",
|
|
43720
|
+
"outcome_unknown"
|
|
43721
|
+
]);
|
|
43722
|
+
var MUTATION_KEYS = [
|
|
43723
|
+
"project_ref",
|
|
43724
|
+
"mutation_id",
|
|
43725
|
+
"operation",
|
|
43726
|
+
"resource_key",
|
|
43727
|
+
"request_fingerprint",
|
|
43728
|
+
"principal",
|
|
43729
|
+
"status",
|
|
43730
|
+
"checkpoint",
|
|
43731
|
+
"receipt",
|
|
43732
|
+
"response_status",
|
|
43733
|
+
"failure_code",
|
|
43734
|
+
"lease",
|
|
43735
|
+
"completed_at",
|
|
43736
|
+
"created_at",
|
|
43737
|
+
"updated_at"
|
|
43738
|
+
];
|
|
43739
|
+
var PRINCIPAL_KEYS = ["type", "id"];
|
|
43740
|
+
var LEASE_KEYS = ["owner", "expires_at", "fencing_epoch"];
|
|
43741
|
+
function isMutationId(candidate) {
|
|
43742
|
+
return typeof candidate === "string" && MUTATION_ID_PATTERN.test(candidate);
|
|
43743
|
+
}
|
|
43744
|
+
function objectRecord(candidate) {
|
|
43745
|
+
return candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : null;
|
|
43746
|
+
}
|
|
43747
|
+
function exactRecord(candidate, keys) {
|
|
43748
|
+
const record = objectRecord(candidate);
|
|
43749
|
+
if (!record || Object.keys(record).length !== keys.length)
|
|
43750
|
+
return null;
|
|
43751
|
+
return keys.every((key) => Object.hasOwn(record, key)) ? record : null;
|
|
43752
|
+
}
|
|
43753
|
+
function emptyProjection(candidate) {
|
|
43754
|
+
const record = objectRecord(candidate);
|
|
43755
|
+
return record && Object.keys(record).length === 0 ? record : null;
|
|
43756
|
+
}
|
|
43757
|
+
function canonicalTimestamp4(candidate) {
|
|
43758
|
+
if (typeof candidate !== "string" || !TIMESTAMP_PATTERN.test(candidate))
|
|
43759
|
+
return false;
|
|
43760
|
+
const milliseconds = Date.parse(candidate);
|
|
43761
|
+
return Number.isFinite(milliseconds) && new Date(milliseconds).toISOString() === candidate;
|
|
43762
|
+
}
|
|
43763
|
+
function nullableTimestamp(candidate) {
|
|
43764
|
+
return candidate === null || canonicalTimestamp4(candidate);
|
|
43765
|
+
}
|
|
43766
|
+
function safePrincipal(candidate) {
|
|
43767
|
+
const principal = exactRecord(candidate, PRINCIPAL_KEYS);
|
|
43768
|
+
if (!principal || !["master", "admin", "project"].includes(String(principal["type"])))
|
|
43769
|
+
return null;
|
|
43770
|
+
if (typeof principal["id"] !== "string" || !principal["id"] || principal["id"].length > 320 || principal["id"].trim() !== principal["id"] || /[\u0000-\u001f\u007f]/u.test(principal["id"]))
|
|
43771
|
+
return null;
|
|
43772
|
+
return { type: principal["type"], id: principal["id"] };
|
|
43773
|
+
}
|
|
43774
|
+
function safeLease(candidate) {
|
|
43775
|
+
const lease = exactRecord(candidate, LEASE_KEYS);
|
|
43776
|
+
if (!lease || lease["owner"] !== null && (typeof lease["owner"] !== "string" || !LEASE_OWNER_PATTERN.test(lease["owner"])))
|
|
43777
|
+
return null;
|
|
43778
|
+
if (!nullableTimestamp(lease["expires_at"]) || !Number.isSafeInteger(lease["fencing_epoch"]) || Number(lease["fencing_epoch"]) < 0)
|
|
43779
|
+
return null;
|
|
43780
|
+
return {
|
|
43781
|
+
owner: lease["owner"],
|
|
43782
|
+
expires_at: lease["expires_at"],
|
|
43783
|
+
fencing_epoch: Number(lease["fencing_epoch"])
|
|
43784
|
+
};
|
|
43785
|
+
}
|
|
43786
|
+
function safeResponseStatus(candidate) {
|
|
43787
|
+
if (candidate === null)
|
|
43788
|
+
return null;
|
|
43789
|
+
return Number.isInteger(candidate) && Number(candidate) >= 100 && Number(candidate) <= 599 ? Number(candidate) : undefined;
|
|
43790
|
+
}
|
|
43791
|
+
function validLeaseState(status, lease) {
|
|
43792
|
+
const running = status === "running";
|
|
43793
|
+
return running ? lease.owner !== null && lease.expires_at !== null && lease.fencing_epoch > 0 : lease.owner === null && lease.expires_at === null;
|
|
43794
|
+
}
|
|
43795
|
+
function validMutationLifecycle(mutation, receipt, responseStatus) {
|
|
43796
|
+
const terminal = ["succeeded", "failed_terminal", "outcome_unknown"].includes(String(mutation["status"]));
|
|
43797
|
+
if (mutation["completed_at"] !== null !== terminal)
|
|
43798
|
+
return false;
|
|
43799
|
+
if (mutation["status"] === "succeeded") {
|
|
43800
|
+
return receipt !== null && responseStatus !== null && responseStatus >= 200 && responseStatus < 300 && mutation["failure_code"] === null;
|
|
43801
|
+
}
|
|
43802
|
+
if (mutation["status"] === "failed_terminal") {
|
|
43803
|
+
return receipt !== null && typeof mutation["failure_code"] === "string";
|
|
43804
|
+
}
|
|
43805
|
+
if (mutation["status"] === "failed_retryable" || mutation["status"] === "outcome_unknown") {
|
|
43806
|
+
return receipt !== null && typeof mutation["failure_code"] === "string";
|
|
43807
|
+
}
|
|
43808
|
+
if (mutation["status"] === "pending") {
|
|
43809
|
+
return receipt === null && responseStatus === null && mutation["failure_code"] === null;
|
|
43810
|
+
}
|
|
43811
|
+
return true;
|
|
43812
|
+
}
|
|
43813
|
+
function canonicalMutationResourceKey(candidate) {
|
|
43814
|
+
if (typeof candidate !== "string")
|
|
43815
|
+
return false;
|
|
43816
|
+
const match = RESOURCE_KEY_PATTERN.exec(candidate);
|
|
43817
|
+
if (!match)
|
|
43818
|
+
return false;
|
|
43819
|
+
const encodedResourceId = match[1];
|
|
43820
|
+
const resourceIdBytes = Buffer.from(encodedResourceId, "base64url");
|
|
43821
|
+
if (resourceIdBytes.byteLength < 1 || resourceIdBytes.byteLength > MAX_RESOURCE_ID_BYTES || resourceIdBytes.toString("base64url") !== encodedResourceId)
|
|
43822
|
+
return false;
|
|
43823
|
+
let resourceId;
|
|
43824
|
+
try {
|
|
43825
|
+
resourceId = FATAL_UTF8_DECODER.decode(resourceIdBytes);
|
|
43826
|
+
} catch (decodeError) {
|
|
43827
|
+
if (decodeError instanceof TypeError)
|
|
43828
|
+
return false;
|
|
43829
|
+
throw decodeError;
|
|
43830
|
+
}
|
|
43831
|
+
return resourceId.trim() === resourceId && !RESOURCE_ID_CONTROL_PATTERN.test(resourceId) && Buffer.from(resourceId, "utf8").equals(resourceIdBytes);
|
|
43832
|
+
}
|
|
43833
|
+
function validMutationIdentity(mutation) {
|
|
43834
|
+
if (!isMutationId(mutation["mutation_id"]) || typeof mutation["project_ref"] !== "string")
|
|
43835
|
+
return false;
|
|
43836
|
+
if (typeof mutation["operation"] !== "string" || !OPERATION_PATTERN.test(mutation["operation"]))
|
|
43837
|
+
return false;
|
|
43838
|
+
if (mutation["resource_key"] !== null && !canonicalMutationResourceKey(mutation["resource_key"]))
|
|
43839
|
+
return false;
|
|
43840
|
+
return typeof mutation["request_fingerprint"] === "string" && FINGERPRINT_PATTERN.test(mutation["request_fingerprint"]);
|
|
43841
|
+
}
|
|
43842
|
+
function validMutationTerminalFields(mutation) {
|
|
43843
|
+
if (typeof mutation["status"] !== "string" || !MUTATION_STATUSES.has(mutation["status"]))
|
|
43844
|
+
return false;
|
|
43845
|
+
if (mutation["failure_code"] !== null && (typeof mutation["failure_code"] !== "string" || !FAILURE_CODE_PATTERN.test(mutation["failure_code"])))
|
|
43846
|
+
return false;
|
|
43847
|
+
return nullableTimestamp(mutation["completed_at"]) && canonicalTimestamp4(mutation["created_at"]) && canonicalTimestamp4(mutation["updated_at"]);
|
|
43848
|
+
}
|
|
43849
|
+
function safeMutationStatus(candidate) {
|
|
43850
|
+
const mutation = exactRecord(candidate, MUTATION_KEYS);
|
|
43851
|
+
if (!mutation || !validMutationIdentity(mutation) || !validMutationTerminalFields(mutation))
|
|
43852
|
+
return null;
|
|
43853
|
+
const principal = safePrincipal(mutation["principal"]);
|
|
43854
|
+
const checkpoint = emptyProjection(mutation["checkpoint"]);
|
|
43855
|
+
const receipt = mutation["receipt"] === null ? null : emptyProjection(mutation["receipt"]);
|
|
43856
|
+
const responseStatus = safeResponseStatus(mutation["response_status"]);
|
|
43857
|
+
const lease = safeLease(mutation["lease"]);
|
|
43858
|
+
if (!principal || !checkpoint || mutation["receipt"] !== null && !receipt || responseStatus === undefined || !lease || !validLeaseState(String(mutation["status"]), lease) || !validMutationLifecycle(mutation, receipt, responseStatus))
|
|
43859
|
+
return null;
|
|
43860
|
+
return {
|
|
43861
|
+
project_ref: mutation["project_ref"],
|
|
43862
|
+
mutation_id: mutation["mutation_id"],
|
|
43863
|
+
operation: mutation["operation"],
|
|
43864
|
+
resource_key: mutation["resource_key"],
|
|
43865
|
+
request_fingerprint: mutation["request_fingerprint"],
|
|
43866
|
+
principal,
|
|
43867
|
+
status: mutation["status"],
|
|
43868
|
+
checkpoint,
|
|
43869
|
+
receipt,
|
|
43870
|
+
response_status: responseStatus,
|
|
43871
|
+
failure_code: mutation["failure_code"],
|
|
43872
|
+
lease,
|
|
43873
|
+
completed_at: mutation["completed_at"],
|
|
43874
|
+
created_at: mutation["created_at"],
|
|
43875
|
+
updated_at: mutation["updated_at"]
|
|
43876
|
+
};
|
|
43877
|
+
}
|
|
43878
|
+
|
|
43705
43879
|
// ../cli/src/shared/tools/frontend-release-control.ts
|
|
43706
43880
|
var PROJECT_REF_PATTERN3 = /^[A-Za-z0-9_-]{1,20}$/u;
|
|
43707
43881
|
var DEPLOYMENT_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/u;
|
|
43708
43882
|
var RELEASE_ID_PATTERN = /^[0-9a-f]{64}$/u;
|
|
43709
|
-
var
|
|
43710
|
-
var
|
|
43883
|
+
var MUTATION_ID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
|
|
43884
|
+
var TIMESTAMP_PATTERN2 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u;
|
|
43711
43885
|
var ARCHIVE_MAX_BYTES = 100 * 1024 * 1024;
|
|
43712
43886
|
var ARCHIVE_CHUNK_BYTES = 64 * 1024;
|
|
43713
43887
|
var RESPONSE_MAX_BYTES = 1024 * 1024;
|
|
@@ -43748,7 +43922,7 @@ function releaseRecord(candidate) {
|
|
|
43748
43922
|
"kind",
|
|
43749
43923
|
"archive_format"
|
|
43750
43924
|
];
|
|
43751
|
-
if (!exactKeys(record, keys) || record.schema !== FRONTEND_ARCHIVE_RELEASE_SCHEMA || record.archive_format !== FRONTEND_ARCHIVE_FORMAT || typeof record.project_ref !== "string" || !PROJECT_REF_PATTERN3.test(record.project_ref) || typeof record.deployment_id !== "string" || !DEPLOYMENT_ID_PATTERN.test(record.deployment_id) || typeof record.release_id !== "string" || !RELEASE_ID_PATTERN.test(record.release_id) || record.sha256 !== record.release_id || typeof record.tree_sha256 !== "string" || !RELEASE_ID_PATTERN.test(record.tree_sha256) || !Number.isSafeInteger(record.size_bytes) || Number(record.size_bytes) < 1 || !Number.isSafeInteger(record.file_count) || Number(record.file_count) < 1 || !
|
|
43925
|
+
if (!exactKeys(record, keys) || record.schema !== FRONTEND_ARCHIVE_RELEASE_SCHEMA || record.archive_format !== FRONTEND_ARCHIVE_FORMAT || typeof record.project_ref !== "string" || !PROJECT_REF_PATTERN3.test(record.project_ref) || typeof record.deployment_id !== "string" || !DEPLOYMENT_ID_PATTERN.test(record.deployment_id) || typeof record.release_id !== "string" || !RELEASE_ID_PATTERN.test(record.release_id) || record.sha256 !== record.release_id || typeof record.tree_sha256 !== "string" || !RELEASE_ID_PATTERN.test(record.tree_sha256) || !Number.isSafeInteger(record.size_bytes) || Number(record.size_bytes) < 1 || !Number.isSafeInteger(record.file_count) || Number(record.file_count) < 1 || !canonicalTimestamp5(record.created_at) || record.kind !== "prebuilt_static")
|
|
43752
43926
|
return null;
|
|
43753
43927
|
return {
|
|
43754
43928
|
project_ref: record.project_ref,
|
|
@@ -43772,8 +43946,8 @@ function releaseEnvelope(candidate, expected) {
|
|
|
43772
43946
|
return null;
|
|
43773
43947
|
return release;
|
|
43774
43948
|
}
|
|
43775
|
-
function
|
|
43776
|
-
if (typeof candidate !== "string" || !
|
|
43949
|
+
function canonicalTimestamp5(candidate) {
|
|
43950
|
+
if (typeof candidate !== "string" || !TIMESTAMP_PATTERN2.test(candidate))
|
|
43777
43951
|
return false;
|
|
43778
43952
|
const milliseconds = Date.parse(candidate);
|
|
43779
43953
|
return Number.isFinite(milliseconds) && new Date(milliseconds).toISOString() === candidate;
|
|
@@ -43798,7 +43972,7 @@ function releaseInventory(candidate, expected) {
|
|
|
43798
43972
|
if (!exactKeys(record, keys) || typeof record.project_ref !== "string" || !PROJECT_REF_PATTERN3.test(record.project_ref) || typeof record.deployment_id !== "string" || !DEPLOYMENT_ID_PATTERN.test(record.deployment_id) || !Array.isArray(record.releases))
|
|
43799
43973
|
return null;
|
|
43800
43974
|
const activeReleaseId = nullableIdentity(record.active_release_id, RELEASE_ID_PATTERN);
|
|
43801
|
-
const activeActivationId = nullableIdentity(record.active_activation_id,
|
|
43975
|
+
const activeActivationId = nullableIdentity(record.active_activation_id, MUTATION_ID_PATTERN2);
|
|
43802
43976
|
const nextCursor = nullableIdentity(record.next_cursor, RELEASE_ID_PATTERN);
|
|
43803
43977
|
const releases = record.releases.map(releaseRecord);
|
|
43804
43978
|
if (activeReleaseId === undefined || activeActivationId === undefined || nextCursor === undefined || activeReleaseId === null !== (activeActivationId === null) || releases.some((release) => release === null))
|
|
@@ -43909,13 +44083,16 @@ async function getFrontendRelease(http, projectRef, deploymentId, releaseId) {
|
|
|
43909
44083
|
const response = await http.get(releasePath(projectRef, deploymentId, releaseId), {
|
|
43910
44084
|
maxJsonBytes: RESPONSE_MAX_BYTES
|
|
43911
44085
|
});
|
|
43912
|
-
const release = response.ok ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId }) : null;
|
|
44086
|
+
const release = response.ok && response.status === 200 ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId }) : null;
|
|
43913
44087
|
if (!release) {
|
|
43914
44088
|
return releaseReadFailure("frontend.get_release", response);
|
|
43915
44089
|
}
|
|
43916
44090
|
return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release });
|
|
43917
44091
|
}
|
|
43918
44092
|
async function uploadFrontendRelease(http, projectRef, deploymentId, archivePath) {
|
|
44093
|
+
return uploadFrontendReleaseWithReadback(http, projectRef, deploymentId, archivePath, true);
|
|
44094
|
+
}
|
|
44095
|
+
async function uploadFrontendReleaseWithReadback(http, projectRef, deploymentId, archivePath, verifyReadback) {
|
|
43919
44096
|
const endpoint = releaseEndpoint(projectRef, deploymentId);
|
|
43920
44097
|
const archive = await verifiedArchive(archivePath);
|
|
43921
44098
|
let response;
|
|
@@ -43934,13 +44111,15 @@ async function uploadFrontendRelease(http, projectRef, deploymentId, archivePath
|
|
|
43934
44111
|
} finally {
|
|
43935
44112
|
await archive.handle.close();
|
|
43936
44113
|
}
|
|
43937
|
-
const release = response.ok ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId: archive.sha256 }) : null;
|
|
44114
|
+
const release = response.ok && (response.status === 200 || response.status === 201) ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId: archive.sha256 }) : null;
|
|
43938
44115
|
if (!release) {
|
|
43939
44116
|
if (response.status >= 400 && response.status < 500 && response.status !== 408 && !response.transportError) {
|
|
43940
44117
|
return releaseFailure("frontend.upload_release", "HTTP_ERROR", response.status);
|
|
43941
44118
|
}
|
|
43942
44119
|
return uploadReadback(http, projectRef, deploymentId, archive.sha256, response.status);
|
|
43943
44120
|
}
|
|
44121
|
+
if (!verifyReadback)
|
|
44122
|
+
return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release });
|
|
43944
44123
|
const readback = await http.get(`${endpoint}/${release.release_id}`, { maxJsonBytes: RESPONSE_MAX_BYTES });
|
|
43945
44124
|
const verified = readback.ok ? releaseEnvelope(readback.data, { projectRef, deploymentId, releaseId: release.release_id }) : null;
|
|
43946
44125
|
if (!verified || verified.tree_sha256 !== release.tree_sha256) {
|
|
@@ -43952,7 +44131,7 @@ async function uploadReadback(http, projectRef, deploymentId, releaseId, uploadS
|
|
|
43952
44131
|
const response = await http.get(releasePath(projectRef, deploymentId, releaseId), {
|
|
43953
44132
|
maxJsonBytes: RESPONSE_MAX_BYTES
|
|
43954
44133
|
});
|
|
43955
|
-
const release = response.ok ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId }) : null;
|
|
44134
|
+
const release = response.ok && response.status === 200 ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId }) : null;
|
|
43956
44135
|
if (!release) {
|
|
43957
44136
|
return releaseFailure("frontend.upload_release", "OUTCOME_UNKNOWN", uploadStatus);
|
|
43958
44137
|
}
|
|
@@ -43983,25 +44162,8 @@ function publicMutationReceipt(candidate, expected) {
|
|
|
43983
44162
|
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate))
|
|
43984
44163
|
return null;
|
|
43985
44164
|
const envelope = candidate;
|
|
43986
|
-
const mutation = envelope.mutation;
|
|
43987
|
-
|
|
43988
|
-
"project_ref",
|
|
43989
|
-
"mutation_id",
|
|
43990
|
-
"operation",
|
|
43991
|
-
"resource_key",
|
|
43992
|
-
"request_fingerprint",
|
|
43993
|
-
"principal",
|
|
43994
|
-
"status",
|
|
43995
|
-
"checkpoint",
|
|
43996
|
-
"receipt",
|
|
43997
|
-
"response_status",
|
|
43998
|
-
"failure_code",
|
|
43999
|
-
"lease",
|
|
44000
|
-
"completed_at",
|
|
44001
|
-
"created_at",
|
|
44002
|
-
"updated_at"
|
|
44003
|
-
];
|
|
44004
|
-
if (!mutation || !exactKeys(envelope, ["project_ref", "mutation"]) || !exactKeys(mutation, expectedKeys) || envelope.project_ref !== expected.projectRef || mutation.project_ref !== expected.projectRef || mutation.mutation_id !== expected.mutationId || mutation.resource_key !== expected.resourceKey || mutation.request_fingerprint !== expected.requestFingerprint || typeof mutation.operation !== "string" || typeof mutation.status !== "string" || !(mutation.response_status === null || Number.isSafeInteger(mutation.response_status)) || !(mutation.failure_code === null || typeof mutation.failure_code === "string"))
|
|
44165
|
+
const mutation = safeMutationStatus(envelope.mutation);
|
|
44166
|
+
if (!mutation || !exactKeys(envelope, ["project_ref", "mutation"]) || envelope.project_ref !== expected.projectRef || mutation.project_ref !== expected.projectRef || mutation.mutation_id !== expected.mutationId || mutation.resource_key !== expected.resourceKey || mutation.request_fingerprint !== expected.requestFingerprint)
|
|
44005
44167
|
return null;
|
|
44006
44168
|
return {
|
|
44007
44169
|
operation: mutation.operation,
|
|
@@ -44028,6 +44190,18 @@ function activationReceipt(candidate, input) {
|
|
|
44028
44190
|
return release;
|
|
44029
44191
|
}
|
|
44030
44192
|
async function activeReleaseReadback(http, identity) {
|
|
44193
|
+
const snapshot = await activeReleaseSnapshotReadback(http, identity);
|
|
44194
|
+
if (!snapshot.release)
|
|
44195
|
+
return snapshot;
|
|
44196
|
+
const releaseRead = await http.get(releasePath(identity.projectRef, identity.deploymentId, identity.releaseId), { maxJsonBytes: RESPONSE_MAX_BYTES });
|
|
44197
|
+
const release = releaseRead.ok && releaseRead.status === 200 ? releaseEnvelope(releaseRead.data, {
|
|
44198
|
+
projectRef: identity.projectRef,
|
|
44199
|
+
deploymentId: identity.deploymentId,
|
|
44200
|
+
releaseId: identity.releaseId
|
|
44201
|
+
}) : null;
|
|
44202
|
+
return { release, status: releaseRead.status };
|
|
44203
|
+
}
|
|
44204
|
+
async function activeReleaseSnapshotReadback(http, identity) {
|
|
44031
44205
|
const snapshot = await readActiveFrontendRelease(http, identity.projectRef, identity.deploymentId);
|
|
44032
44206
|
if ("failure" in snapshot)
|
|
44033
44207
|
return { release: null, status: snapshot.status };
|
|
@@ -44035,13 +44209,7 @@ async function activeReleaseReadback(http, identity) {
|
|
|
44035
44209
|
if (inventory.active_release_id !== identity.releaseId || inventory.active_activation_id !== identity.mutationId) {
|
|
44036
44210
|
return { release: null, status: 200 };
|
|
44037
44211
|
}
|
|
44038
|
-
|
|
44039
|
-
const release = releaseRead.ok ? releaseEnvelope(releaseRead.data, {
|
|
44040
|
-
projectRef: identity.projectRef,
|
|
44041
|
-
deploymentId: identity.deploymentId,
|
|
44042
|
-
releaseId: identity.releaseId
|
|
44043
|
-
}) : null;
|
|
44044
|
-
return { release, status: releaseRead.status };
|
|
44212
|
+
return { release: inventory.releases[0] ?? null, status: 200 };
|
|
44045
44213
|
}
|
|
44046
44214
|
async function readActiveFrontendRelease(http, projectRef, deploymentId) {
|
|
44047
44215
|
const response = await http.get(`${deploymentEndpoint(projectRef, deploymentId)}/active-release`, {
|
|
@@ -44077,10 +44245,74 @@ async function getActiveFrontendRelease(http, projectRef, deploymentId) {
|
|
|
44077
44245
|
const snapshot = await readActiveFrontendRelease(http, projectRef, deploymentId);
|
|
44078
44246
|
return "failure" in snapshot ? snapshot.failure : toolResponse(snapshot.inventory);
|
|
44079
44247
|
}
|
|
44080
|
-
|
|
44248
|
+
function boundRollbackResponse(result, input) {
|
|
44249
|
+
const payload = JSON.parse(result.content[0].text);
|
|
44250
|
+
return {
|
|
44251
|
+
...toolResponse({
|
|
44252
|
+
...payload,
|
|
44253
|
+
operation: "frontend.rollback",
|
|
44254
|
+
project_ref: input.projectRef,
|
|
44255
|
+
deployment_id: input.deploymentId,
|
|
44256
|
+
target_release_id: input.releaseId,
|
|
44257
|
+
mutation_id: input.mutationId,
|
|
44258
|
+
expected_active_release_id: input.expectedActiveReleaseId,
|
|
44259
|
+
expected_activation_id: input.expectedActivationId,
|
|
44260
|
+
...!result.isError ? {
|
|
44261
|
+
rollback: true,
|
|
44262
|
+
previous_release_id: input.expectedActiveReleaseId,
|
|
44263
|
+
previous_activation_id: input.expectedActivationId
|
|
44264
|
+
} : {}
|
|
44265
|
+
}),
|
|
44266
|
+
...result.isError ? { isError: true } : {}
|
|
44267
|
+
};
|
|
44268
|
+
}
|
|
44269
|
+
async function rollbackBoundFrontendRelease(http, input) {
|
|
44270
|
+
const authority = await readActiveFrontendRelease(http, input.projectRef, input.deploymentId);
|
|
44271
|
+
if ("failure" in authority)
|
|
44272
|
+
return boundRollbackResponse(authority.failure, input);
|
|
44273
|
+
const current = authority.inventory;
|
|
44274
|
+
if (current.active_release_id === input.releaseId && current.active_activation_id === input.mutationId) {
|
|
44275
|
+
return boundRollbackResponse(await activationReadback(http, input, input.mutationId, 200), input);
|
|
44276
|
+
}
|
|
44277
|
+
if (current.active_release_id !== input.expectedActiveReleaseId || current.active_activation_id !== input.expectedActivationId) {
|
|
44278
|
+
return boundRollbackResponse(releaseFailure("frontend.rollback", "STALE_AUTHORITY", 409), input);
|
|
44279
|
+
}
|
|
44280
|
+
const target = await getFrontendRelease(http, input.projectRef, input.deploymentId, input.releaseId);
|
|
44281
|
+
if (target.isError)
|
|
44282
|
+
return boundRollbackResponse(target, input);
|
|
44283
|
+
return boundRollbackResponse(await activateFrontendRelease(http, input), input);
|
|
44284
|
+
}
|
|
44285
|
+
async function rollbackFrontendRelease(http, projectRef, deploymentId, releaseId, options = {}) {
|
|
44081
44286
|
if (releaseId !== undefined && !RELEASE_ID_PATTERN.test(releaseId)) {
|
|
44082
44287
|
throw new Error("'release_id' must be a SHA-256 digest");
|
|
44083
44288
|
}
|
|
44289
|
+
const bound = options.expectedActiveReleaseId !== undefined || options.expectedActivationId !== undefined || options.mutationId !== undefined;
|
|
44290
|
+
if (bound) {
|
|
44291
|
+
const { expectedActiveReleaseId, expectedActivationId, mutationId } = options;
|
|
44292
|
+
if (releaseId === undefined || expectedActiveReleaseId === undefined || expectedActivationId === undefined || mutationId === undefined) {
|
|
44293
|
+
throw new Error("'release_id', 'expected_active_release_id', 'expected_activation_id', and 'mutation_id' are required together for a bound rollback");
|
|
44294
|
+
}
|
|
44295
|
+
if (!RELEASE_ID_PATTERN.test(expectedActiveReleaseId)) {
|
|
44296
|
+
throw new Error("'expected_active_release_id' must be a SHA-256 digest");
|
|
44297
|
+
}
|
|
44298
|
+
if (!MUTATION_ID_PATTERN2.test(expectedActivationId)) {
|
|
44299
|
+
throw new Error("'expected_activation_id' must be a UUIDv4");
|
|
44300
|
+
}
|
|
44301
|
+
if (!MUTATION_ID_PATTERN2.test(mutationId)) {
|
|
44302
|
+
throw new Error("'mutation_id' must be a UUIDv4");
|
|
44303
|
+
}
|
|
44304
|
+
if (releaseId === expectedActiveReleaseId || mutationId === expectedActivationId) {
|
|
44305
|
+
throw new Error("Bound rollback requires a different target release and a distinct mutation UUID");
|
|
44306
|
+
}
|
|
44307
|
+
return rollbackBoundFrontendRelease(http, {
|
|
44308
|
+
projectRef,
|
|
44309
|
+
deploymentId,
|
|
44310
|
+
releaseId,
|
|
44311
|
+
expectedActiveReleaseId,
|
|
44312
|
+
expectedActivationId,
|
|
44313
|
+
mutationId
|
|
44314
|
+
});
|
|
44315
|
+
}
|
|
44084
44316
|
const authority = releaseId === undefined ? await readPreviousFrontendRelease(http, projectRef, deploymentId) : await readActiveFrontendRelease(http, projectRef, deploymentId);
|
|
44085
44317
|
if ("failure" in authority)
|
|
44086
44318
|
return authority.failure;
|
|
@@ -44149,8 +44381,8 @@ async function readPreviousFrontendRelease(http, projectRef, deploymentId) {
|
|
|
44149
44381
|
const data = response.data;
|
|
44150
44382
|
const value = data && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
44151
44383
|
const activeReleaseId = value ? nullableIdentity(value.active_release_id, RELEASE_ID_PATTERN) : undefined;
|
|
44152
|
-
const activeActivationId = value ? nullableIdentity(value.active_activation_id,
|
|
44153
|
-
const previousActivationId = value ? nullableIdentity(value.previous_activation_id,
|
|
44384
|
+
const activeActivationId = value ? nullableIdentity(value.active_activation_id, MUTATION_ID_PATTERN2) : undefined;
|
|
44385
|
+
const previousActivationId = value ? nullableIdentity(value.previous_activation_id, MUTATION_ID_PATTERN2) : undefined;
|
|
44154
44386
|
const previous = value?.previous_release === null ? null : releaseRecord(value?.previous_release);
|
|
44155
44387
|
if (!response.ok || response.status !== 200 || !value || !exactKeys(value, [
|
|
44156
44388
|
"schema",
|
|
@@ -44176,13 +44408,16 @@ async function readPreviousFrontendRelease(http, projectRef, deploymentId) {
|
|
|
44176
44408
|
};
|
|
44177
44409
|
}
|
|
44178
44410
|
async function activateFrontendRelease(http, input) {
|
|
44411
|
+
return activateFrontendReleaseWithReadback(http, input, activeReleaseReadback);
|
|
44412
|
+
}
|
|
44413
|
+
async function activateFrontendReleaseWithReadback(http, input, readActive) {
|
|
44179
44414
|
const mutationId = input.mutationId;
|
|
44180
|
-
if (!
|
|
44415
|
+
if (!MUTATION_ID_PATTERN2.test(mutationId))
|
|
44181
44416
|
throw new Error("'mutation_id' must be a UUIDv4");
|
|
44182
44417
|
if (input.expectedActiveReleaseId !== "absent" && !RELEASE_ID_PATTERN.test(input.expectedActiveReleaseId)) {
|
|
44183
44418
|
throw new Error("'expected_active_release_id' is invalid");
|
|
44184
44419
|
}
|
|
44185
|
-
if (input.expectedActivationId !== "absent" && !
|
|
44420
|
+
if (input.expectedActivationId !== "absent" && !MUTATION_ID_PATTERN2.test(input.expectedActivationId)) {
|
|
44186
44421
|
throw new Error("'expected_activation_id' is invalid");
|
|
44187
44422
|
}
|
|
44188
44423
|
const endpoint = `${releasePath(input.projectRef, input.deploymentId, input.releaseId)}/activate`;
|
|
@@ -44195,13 +44430,13 @@ async function activateFrontendRelease(http, input) {
|
|
|
44195
44430
|
responseTimeoutMs: MUTATION_RESPONSE_TIMEOUT_MS
|
|
44196
44431
|
});
|
|
44197
44432
|
const release = activationReceipt(response.data, { ...input, mutationId });
|
|
44198
|
-
if (!response.ok || !release) {
|
|
44433
|
+
if (!response.ok || response.status !== 200 || !release) {
|
|
44199
44434
|
if (response.status >= 400 && response.status < 500 && response.status !== 408 && !response.transportError) {
|
|
44200
44435
|
return releaseFailure("frontend.activate_release", "HTTP_ERROR", response.status);
|
|
44201
44436
|
}
|
|
44202
44437
|
return activationReadback(http, input, mutationId, response.status);
|
|
44203
44438
|
}
|
|
44204
|
-
const readback = await
|
|
44439
|
+
const readback = await readActive(http, { ...input, mutationId });
|
|
44205
44440
|
if (!readback.release || readback.release.tree_sha256 !== release.tree_sha256) {
|
|
44206
44441
|
return releaseFailure("frontend.activate_release", "OUTCOME_UNKNOWN", readback.status);
|
|
44207
44442
|
}
|
|
@@ -44216,7 +44451,7 @@ async function activateFrontendRelease(http, input) {
|
|
|
44216
44451
|
async function activationReadback(http, input, mutationId, activationStatus) {
|
|
44217
44452
|
const mutationRead = await http.get(`/v1/projects/${encodeURIComponent(input.projectRef)}/mutations/${mutationId}`, { maxJsonBytes: RESPONSE_MAX_BYTES });
|
|
44218
44453
|
const mutationEnvelope = mutationRead.data;
|
|
44219
|
-
const mutation = mutationRead.ok ? publicMutationReceipt(mutationRead.data, {
|
|
44454
|
+
const mutation = mutationRead.ok && mutationRead.status === 200 ? publicMutationReceipt(mutationRead.data, {
|
|
44220
44455
|
projectRef: input.projectRef,
|
|
44221
44456
|
mutationId,
|
|
44222
44457
|
resourceKey: activationResourceKey(input.deploymentId),
|
|
@@ -44321,7 +44556,7 @@ Actions: list_releases, get_active_release, get_release, upload_release, activat
|
|
|
44321
44556
|
// package.json
|
|
44322
44557
|
var package_default = {
|
|
44323
44558
|
name: "@supacloud/admin",
|
|
44324
|
-
version: "0.28.
|
|
44559
|
+
version: "0.28.3",
|
|
44325
44560
|
description: "Platform administration CLI for SupaCloud operators",
|
|
44326
44561
|
type: "module",
|
|
44327
44562
|
main: "./dist/index.js",
|
|
@@ -44356,21 +44591,21 @@ var package_default = {
|
|
|
44356
44591
|
directory: "packages/admin"
|
|
44357
44592
|
},
|
|
44358
44593
|
dependencies: {
|
|
44359
|
-
"@supacloud/delivery": "0.
|
|
44360
|
-
typebox: "1.3.
|
|
44361
|
-
"@supacloud/cli": "0.
|
|
44594
|
+
"@supacloud/delivery": "0.19.3",
|
|
44595
|
+
typebox: "1.3.37",
|
|
44596
|
+
"@supacloud/cli": "0.103.6",
|
|
44362
44597
|
ssh2: "^1.17.0"
|
|
44363
44598
|
},
|
|
44364
44599
|
devDependencies: {
|
|
44365
|
-
"@types/bun": "^1.4.
|
|
44600
|
+
"@types/bun": "^1.4.3",
|
|
44366
44601
|
"@types/ssh2": "^1.15.6",
|
|
44367
44602
|
typescript: "^7.0.2"
|
|
44368
44603
|
},
|
|
44369
44604
|
overrides: {
|
|
44370
|
-
"@supacloud/contracts": "0.
|
|
44371
|
-
"@supacloud/db": "0.
|
|
44372
|
-
"@supacloud/delivery": "0.
|
|
44373
|
-
"@graphql-tools/utils": "^12.0.
|
|
44605
|
+
"@supacloud/contracts": "0.11.4",
|
|
44606
|
+
"@supacloud/db": "0.18.3",
|
|
44607
|
+
"@supacloud/delivery": "0.19.3",
|
|
44608
|
+
"@graphql-tools/utils": "^12.0.4"
|
|
44374
44609
|
}
|
|
44375
44610
|
};
|
|
44376
44611
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supacloud/admin",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.3",
|
|
4
4
|
"description": "Platform administration CLI for SupaCloud operators",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -35,20 +35,20 @@
|
|
|
35
35
|
"directory": "packages/admin"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@supacloud/delivery": "0.
|
|
39
|
-
"typebox": "1.3.
|
|
40
|
-
"@supacloud/cli": "0.
|
|
38
|
+
"@supacloud/delivery": "0.19.3",
|
|
39
|
+
"typebox": "1.3.37",
|
|
40
|
+
"@supacloud/cli": "0.103.6",
|
|
41
41
|
"ssh2": "^1.17.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@types/bun": "^1.4.
|
|
44
|
+
"@types/bun": "^1.4.3",
|
|
45
45
|
"@types/ssh2": "^1.15.6",
|
|
46
46
|
"typescript": "^7.0.2"
|
|
47
47
|
},
|
|
48
48
|
"overrides": {
|
|
49
|
-
"@supacloud/contracts": "0.
|
|
50
|
-
"@supacloud/db": "0.
|
|
51
|
-
"@supacloud/delivery": "0.
|
|
52
|
-
"@graphql-tools/utils": "^12.0.
|
|
49
|
+
"@supacloud/contracts": "0.11.4",
|
|
50
|
+
"@supacloud/db": "0.18.3",
|
|
51
|
+
"@supacloud/delivery": "0.19.3",
|
|
52
|
+
"@graphql-tools/utils": "^12.0.4"
|
|
53
53
|
}
|
|
54
54
|
}
|