@supacloud/cli 0.87.1 → 0.90.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/README.md +45 -15
- package/dist/index.js +584 -93
- package/dist/shared/tools/app-tools.d.ts +2 -0
- package/dist/shared/tools/application-schemas.d.ts +42 -5
- package/dist/shared/tools/application-tools.d.ts +8 -1
- package/dist/shared/tools/developer-experience-tools.d.ts +26 -0
- package/dist/shared/tools/developer-experience-tools.test.d.ts +1 -0
- package/package.json +7 -7
- package/skills/supacloud/references/command-map.md +4 -4
package/dist/index.js
CHANGED
|
@@ -7797,7 +7797,7 @@ function FromObject10(context, type, value) {
|
|
|
7797
7797
|
return value;
|
|
7798
7798
|
const additionalProperties = GetAdditionalProperties(type);
|
|
7799
7799
|
for (const key of Keys(value)) {
|
|
7800
|
-
if (HasPropertyKey(type.properties, key)) {
|
|
7800
|
+
if (HasPropertyKey(type.properties, key) && IsSchema(type.properties[key])) {
|
|
7801
7801
|
value[key] = FromType19(context, type.properties[key], value[key]);
|
|
7802
7802
|
continue;
|
|
7803
7803
|
}
|
|
@@ -7882,6 +7882,9 @@ function FromProperties4(properties) {
|
|
|
7882
7882
|
result[key] = FromType20(properties[key]);
|
|
7883
7883
|
return result;
|
|
7884
7884
|
}
|
|
7885
|
+
function FromRecordKey(type) {
|
|
7886
|
+
return String2({ pattern: RecordPattern(type) });
|
|
7887
|
+
}
|
|
7885
7888
|
function FromPriorityTypes(types) {
|
|
7886
7889
|
return FromTypes6(Priority(types));
|
|
7887
7890
|
}
|
|
@@ -7889,7 +7892,7 @@ function FromTypes6(types) {
|
|
|
7889
7892
|
return types.map((type) => FromType20(type));
|
|
7890
7893
|
}
|
|
7891
7894
|
function FromType20(type) {
|
|
7892
|
-
const next = IsArray2(type) ? _Array_(FromType20(type.items), ArrayOptions(type)) : IsIntersect(type) ? Intersect(FromTypes6(type.allOf)) : IsUnion(type) ? Union(FromPriorityTypes(type.anyOf)) : IsObject2(type) ? _Object_(FromProperties4(type.properties)) : IsRecord(type) ? Record(
|
|
7895
|
+
const next = IsArray2(type) ? _Array_(FromType20(type.items), ArrayOptions(type)) : IsIntersect(type) ? Intersect(FromTypes6(type.allOf)) : IsUnion(type) ? Union(FromPriorityTypes(type.anyOf)) : IsObject2(type) ? _Object_(FromProperties4(type.properties)) : IsRecord(type) ? Record(FromRecordKey(type), FromType20(RecordValue(type))) : IsTuple(type) ? Tuple(FromTypes6(type.items)) : type;
|
|
7893
7896
|
return Modifiers(type, next);
|
|
7894
7897
|
}
|
|
7895
7898
|
function UnionPrioritySort(type) {
|
|
@@ -9164,7 +9167,7 @@ var ACTION_POLICY = {
|
|
|
9164
9167
|
deploy: { write: ["deploy"] },
|
|
9165
9168
|
applications: {
|
|
9166
9169
|
read: ["list_releases", "get_release", "get_runtime", "get_deployment_evidence", "get_configuration", "get_release_transfer_plan", "get_promotion_plan", "get_promotion_status", "get_rollback_snapshot", "get_history", "get_deploy_plan", "logs", "get_preview_plan", "list_previews", "get_preview"],
|
|
9167
|
-
write: ["upload_release", "put_configuration", "
|
|
9170
|
+
write: ["upload_release", "put_configuration", "deploy_application", "transfer_release", "promote_application", "reconcile_promotion", "create_preview", "reconcile_preview", "cleanup_preview", "activate_release", "deploy_release", "rollback_release", "reconcile_activation", "retire_activation"]
|
|
9168
9171
|
},
|
|
9169
9172
|
project: {
|
|
9170
9173
|
read: ["get", "endpoints", "health", "logs", "api_keys", "settings", "tasks", "task_detail", "task_stats", "dlq", "background_settings"],
|
|
@@ -9257,6 +9260,8 @@ var ACTION_POLICY = {
|
|
|
9257
9260
|
write: ["send", "receive", "ack", "release", "fail", "retry", "delete_message", "update_settings"]
|
|
9258
9261
|
},
|
|
9259
9262
|
ai: { local: ["show_skill", "install_skill"] },
|
|
9263
|
+
init: { local: ["init"] },
|
|
9264
|
+
env: { local: ["list", "check"] },
|
|
9260
9265
|
app: {
|
|
9261
9266
|
local: ["init", "generate", "dev", "watch", "verify-plan", "compile", "check", "graph", "explain", "export-tools", "context", "doctor", "fix", "plan", "build"],
|
|
9262
9267
|
read: ["status", "logs", "transfer-plan", "promote-plan", "rollback-plan", "history", "deploy-plan", "diff", "promote-status", "preview-plan", "previews", "preview-list", "preview-status"],
|
|
@@ -10488,34 +10493,67 @@ function parseApplicationDeployPlan(value) {
|
|
|
10488
10493
|
throw new Error("Invalid application deploy plan action");
|
|
10489
10494
|
return value;
|
|
10490
10495
|
}
|
|
10491
|
-
// node_modules/@supacloud/delivery/src/application-
|
|
10496
|
+
// node_modules/@supacloud/delivery/src/application-deploy-operation.ts
|
|
10492
10497
|
var closed3 = { additionalProperties: false };
|
|
10498
|
+
var sha256 = ApplicationReleaseIdSchema;
|
|
10493
10499
|
var nullableActivation = Union([ApplicationActivationIdSchema, Null()]);
|
|
10494
|
-
var
|
|
10495
|
-
|
|
10500
|
+
var ApplicationDeployWebRequestSchema = _Object_({
|
|
10501
|
+
deployment_id: String2({ pattern: "^[A-Za-z0-9_-]{1,128}$" }),
|
|
10502
|
+
release_id: sha256,
|
|
10503
|
+
expected_active_release_id: String2({ minLength: 1 }),
|
|
10504
|
+
expected_activation_id: String2({ minLength: 1 }),
|
|
10505
|
+
mutation_id: ApplicationActivationIdSchema
|
|
10506
|
+
}, closed3);
|
|
10507
|
+
var ApplicationDeployRequestSchema = _Object_({
|
|
10508
|
+
mutation_id: ApplicationActivationIdSchema,
|
|
10509
|
+
release_id: sha256,
|
|
10496
10510
|
configuration_id: Optional(ApplicationConfigurationIdSchema),
|
|
10497
10511
|
configuration_write: Optional(ApplicationConfigurationWriteSchema),
|
|
10498
|
-
|
|
10499
|
-
|
|
10500
|
-
|
|
10512
|
+
expected_plan_sha256: Optional(sha256),
|
|
10513
|
+
approved_migration_digest: Optional(sha256),
|
|
10514
|
+
web: Optional(ApplicationDeployWebRequestSchema)
|
|
10501
10515
|
}, closed3);
|
|
10502
|
-
var
|
|
10503
|
-
schema: Literal("supacloud.application-
|
|
10516
|
+
var ApplicationBackendReceiptSchema = _Object_({
|
|
10517
|
+
schema: Literal("supacloud.application-backend-receipt.v1"),
|
|
10504
10518
|
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
10505
10519
|
application_id: ApplicationIdSchema,
|
|
10506
10520
|
environment_id: ApplicationIdSchema,
|
|
10507
|
-
release_id:
|
|
10521
|
+
release_id: sha256,
|
|
10522
|
+
manifest_sha256: sha256,
|
|
10523
|
+
mutation_id: ApplicationActivationIdSchema,
|
|
10524
|
+
plan_sha256: sha256,
|
|
10525
|
+
backup_id: Union([String2(), Null()]),
|
|
10526
|
+
before_ledger_digest: sha256,
|
|
10527
|
+
after_ledger_digest: sha256,
|
|
10528
|
+
applied_versions: _Array_(String2({ pattern: "^\\d{1,20}$" }), { uniqueItems: true }),
|
|
10529
|
+
schema_reloaded: Boolean2(),
|
|
10530
|
+
postgrest_healthy: Boolean2()
|
|
10531
|
+
}, closed3);
|
|
10532
|
+
var ApplicationDeployResultSchema = _Object_({
|
|
10533
|
+
schema: Literal("supacloud.application-deploy.v1"),
|
|
10534
|
+
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
10535
|
+
application_id: ApplicationIdSchema,
|
|
10536
|
+
environment_id: ApplicationIdSchema,
|
|
10537
|
+
mutation_id: ApplicationActivationIdSchema,
|
|
10538
|
+
release_id: sha256,
|
|
10508
10539
|
configuration_id: ApplicationConfigurationIdSchema,
|
|
10509
10540
|
activation_id: ApplicationActivationIdSchema,
|
|
10510
10541
|
expected_activation_id: nullableActivation,
|
|
10511
|
-
plan_sha256:
|
|
10542
|
+
plan_sha256: sha256,
|
|
10512
10543
|
action: Union([Literal("activate"), Literal("no-op")]),
|
|
10513
10544
|
replayed: Boolean2(),
|
|
10514
|
-
execution_performed: Boolean2()
|
|
10545
|
+
execution_performed: Boolean2(),
|
|
10546
|
+
backend_receipt: ApplicationBackendReceiptSchema,
|
|
10547
|
+
web: Optional(_Object_({
|
|
10548
|
+
deployment_id: String2({ pattern: "^[A-Za-z0-9_-]{1,128}$" }),
|
|
10549
|
+
release_id: sha256,
|
|
10550
|
+
activation_id: ApplicationActivationIdSchema,
|
|
10551
|
+
replayed: Boolean2()
|
|
10552
|
+
}, closed3))
|
|
10515
10553
|
}, closed3);
|
|
10516
|
-
function
|
|
10517
|
-
if (!Check2(
|
|
10518
|
-
throw new Error("Invalid application
|
|
10554
|
+
function parseApplicationDeployResult(value) {
|
|
10555
|
+
if (!Check2(ApplicationDeployResultSchema, value)) {
|
|
10556
|
+
throw new Error("Invalid application deploy result");
|
|
10519
10557
|
}
|
|
10520
10558
|
return structuredClone(value);
|
|
10521
10559
|
}
|
|
@@ -10716,7 +10754,7 @@ function parseApplicationReleaseTransferResult(candidate) {
|
|
|
10716
10754
|
}
|
|
10717
10755
|
// node_modules/@supacloud/delivery/src/deployment-evidence.ts
|
|
10718
10756
|
var closed5 = { additionalProperties: false };
|
|
10719
|
-
var
|
|
10757
|
+
var sha2562 = String2({ pattern: "^[a-f0-9]{64}$" });
|
|
10720
10758
|
var isoDate = String2({ minLength: 20, maxLength: 40 });
|
|
10721
10759
|
var status = Union([
|
|
10722
10760
|
Literal("confirmed"),
|
|
@@ -10736,7 +10774,7 @@ var DatabaseProviderSchema = _Object_({
|
|
|
10736
10774
|
topology: Union([Literal("single-node"), Literal("distributed")]),
|
|
10737
10775
|
migration: _Object_({
|
|
10738
10776
|
status,
|
|
10739
|
-
inventory_sha256: Union([
|
|
10777
|
+
inventory_sha256: Union([sha2562, Null()]),
|
|
10740
10778
|
compatibility: Union([
|
|
10741
10779
|
Literal("verified"),
|
|
10742
10780
|
Literal("not-proven"),
|
|
@@ -10784,9 +10822,9 @@ var DeploymentEvidenceSchema = _Object_({
|
|
|
10784
10822
|
}, closed5),
|
|
10785
10823
|
source: _Object_({
|
|
10786
10824
|
commit_sha: Union([String2({ pattern: "^[0-9a-f]{7,64}$" }), Null()]),
|
|
10787
|
-
manifest_sha256:
|
|
10825
|
+
manifest_sha256: sha2562,
|
|
10788
10826
|
contract_schema: Union([String2({ minLength: 1, maxLength: 128 }), Null()]),
|
|
10789
|
-
environment_binding_version: Union([
|
|
10827
|
+
environment_binding_version: Union([sha2562, Null()])
|
|
10790
10828
|
}, closed5),
|
|
10791
10829
|
database: DatabaseProviderSchema,
|
|
10792
10830
|
components: _Array_(DeploymentComponentEvidenceSchema, { minItems: 1, maxItems: 32 }),
|
|
@@ -10842,9 +10880,9 @@ function parseDeploymentEvidence(value) {
|
|
|
10842
10880
|
// node_modules/@supacloud/delivery/src/application-promotion.ts
|
|
10843
10881
|
var closed6 = { additionalProperties: false };
|
|
10844
10882
|
var projectRef2 = String2({ pattern: "^[a-z0-9-]{1,20}$" });
|
|
10845
|
-
var
|
|
10883
|
+
var sha2563 = ApplicationReleaseIdSchema;
|
|
10846
10884
|
var nullableActivation2 = Union([ApplicationActivationIdSchema, Null()]);
|
|
10847
|
-
var nullableDigest = Union([
|
|
10885
|
+
var nullableDigest = Union([sha2563, Null()]);
|
|
10848
10886
|
var observation = {
|
|
10849
10887
|
activation_id: nullableActivation2,
|
|
10850
10888
|
receipt_confirmed: Boolean2(),
|
|
@@ -10870,24 +10908,24 @@ var ApplicationPromotionPlanSchema = _Object_({
|
|
|
10870
10908
|
project_ref: projectRef2,
|
|
10871
10909
|
application_id: ApplicationIdSchema,
|
|
10872
10910
|
environment_id: ApplicationIdSchema,
|
|
10873
|
-
manifest_sha256:
|
|
10874
|
-
plan_sha256:
|
|
10911
|
+
manifest_sha256: sha2563,
|
|
10912
|
+
plan_sha256: sha2563,
|
|
10875
10913
|
source: _Object_({
|
|
10876
10914
|
project_ref: projectRef2,
|
|
10877
10915
|
environment_id: ApplicationIdSchema,
|
|
10878
|
-
release_id:
|
|
10916
|
+
release_id: sha2563,
|
|
10879
10917
|
...observation
|
|
10880
10918
|
}, closed6),
|
|
10881
10919
|
target: _Object_({
|
|
10882
|
-
candidate_release_id:
|
|
10883
|
-
current_release_id: Union([
|
|
10920
|
+
candidate_release_id: sha2563,
|
|
10921
|
+
current_release_id: Union([sha2563, Null()]),
|
|
10884
10922
|
artifact_action: Union([Literal("materialize"), Literal("reuse")]),
|
|
10885
10923
|
configuration_id: Union([ApplicationConfigurationIdSchema, Null()]),
|
|
10886
10924
|
configuration: Union([ApplicationConfigurationViewSchema, Null()]),
|
|
10887
10925
|
...observation
|
|
10888
10926
|
}, closed6),
|
|
10889
10927
|
migrations: _Object_({
|
|
10890
|
-
ledger_digest:
|
|
10928
|
+
ledger_digest: sha2563,
|
|
10891
10929
|
ledger_compatible: Boolean2(),
|
|
10892
10930
|
project_migrations_applied: Boolean2(),
|
|
10893
10931
|
pending_versions: _Array_(String2({ pattern: "^\\d{1,20}$" }), { maxItems: 4096, uniqueItems: true }),
|
|
@@ -16852,7 +16890,8 @@ var ApplicationActivationRetirementResultSchema2 = ApplicationActivationRetireme
|
|
|
16852
16890
|
var ApplicationRollbackSnapshotSchema2 = ApplicationRollbackSnapshotSchema;
|
|
16853
16891
|
var ApplicationActivationHistoryCursorSchema2 = ApplicationActivationHistoryCursorSchema;
|
|
16854
16892
|
var ApplicationPromotionPlanSchema2 = ApplicationPromotionPlanSchema;
|
|
16855
|
-
var
|
|
16893
|
+
var ApplicationDeployRequestSchema2 = ApplicationDeployRequestSchema;
|
|
16894
|
+
var ApplicationDeployWebRequestSchema2 = ApplicationDeployWebRequestSchema;
|
|
16856
16895
|
|
|
16857
16896
|
// src/shared/mutation-protocol.ts
|
|
16858
16897
|
import { createHash as createHash6 } from "node:crypto";
|
|
@@ -17640,7 +17679,7 @@ var APPLICATION_TOOL_SCHEMA = {
|
|
|
17640
17679
|
"put_configuration",
|
|
17641
17680
|
"get_deploy_plan",
|
|
17642
17681
|
"deploy_release",
|
|
17643
|
-
"
|
|
17682
|
+
"deploy_application",
|
|
17644
17683
|
"get_release_transfer_plan",
|
|
17645
17684
|
"transfer_release",
|
|
17646
17685
|
"get_promotion_plan",
|
|
@@ -17668,14 +17707,15 @@ var APPLICATION_TOOL_SCHEMA = {
|
|
|
17668
17707
|
activation_id: optional(ApplicationActivationIdSchema2, "[deploy_release/activate_release/reconcile_activation/retire_activation/rollback_release/get_history] Stable activation ID; generated for automatic deployment/rollback if omitted"),
|
|
17669
17708
|
expected_activation_id: optional(Union([ApplicationActivationIdSchema2, Null(), Literal("absent")]), "[deploy_release/activate_release/rollback_release] Current activation ID, or absent for first activation; selected from verified plan for automatic deployment"),
|
|
17670
17709
|
configuration_path: optional(String2(), "[put_configuration] Local configuration write JSON including revision and expected revision"),
|
|
17671
|
-
configuration_write: optional(Unknown(), "[
|
|
17710
|
+
configuration_write: optional(Unknown(), "[deploy_application] Parsed immutable configuration write"),
|
|
17672
17711
|
manifest_path: optional(String2(), "[upload_release] Local delivery.manifest.json"),
|
|
17712
|
+
web: optional(ApplicationDeployWebRequestSchema2, "[deploy_application] Immutable staged Web release binding"),
|
|
17673
17713
|
release_id: optional(ApplicationReleaseIdSchema2, "[get_release/get_deploy_plan/deploy_release/activate_release/reconcile_activation/rollback_release] Immutable application release ID; platform selects previous for default rollback"),
|
|
17674
17714
|
source_ref: optional(String2({ pattern: "^[A-Za-z0-9_-]{1,20}$" }), "[get_release_transfer_plan/transfer_release] Source project ref"),
|
|
17675
17715
|
source_release_id: optional(ApplicationReleaseIdSchema2, "[get_release_transfer_plan/transfer_release] Source immutable release ID"),
|
|
17676
17716
|
source_environment_id: optional(ApplicationIdSchema2, "[get_promotion_plan] Source environment"),
|
|
17677
|
-
mutation_id: optional(ApplicationActivationIdSchema2, "[promote_application/get_promotion_status/reconcile_promotion] Stable
|
|
17678
|
-
approved_migration_digest: optional(ApplicationReleaseIdSchema2, "[promote_application] Exact reviewed migration execution-plan digest"),
|
|
17717
|
+
mutation_id: optional(ApplicationActivationIdSchema2, "[deploy_application/promote_application/get_promotion_status/reconcile_promotion] Stable mutation ID"),
|
|
17718
|
+
approved_migration_digest: optional(ApplicationReleaseIdSchema2, "[deploy_application/promote_application] Exact reviewed migration execution-plan digest"),
|
|
17679
17719
|
plan: optional(ApplicationPromotionPlanSchema2, "[promote_application] Immutable plan returned by get_promotion_plan"),
|
|
17680
17720
|
cursor: optional(Union([ApplicationReleaseIdSchema2, ApplicationActivationHistoryCursorSchema2]), "[list_releases/get_history] Returned page cursor"),
|
|
17681
17721
|
limit: optional(Integer({ minimum: 1, maximum: 100 }), "[list_releases/get_history] Page size, default 50/20"),
|
|
@@ -18028,57 +18068,50 @@ function registerApplicationTools(server, http) {
|
|
|
18028
18068
|
const observed = await readDeployPlan(http, args, project);
|
|
18029
18069
|
return observed.failure ?? releaseControlSuccess(operation, { ...observed.identity, plan: observed.plan });
|
|
18030
18070
|
}
|
|
18031
|
-
if (action === "
|
|
18071
|
+
if (action === "deploy_application") {
|
|
18032
18072
|
const environmentId = text(args, "environment_id");
|
|
18033
18073
|
const releaseId = text(args, "release_id");
|
|
18034
|
-
|
|
18035
|
-
|
|
18074
|
+
const mutationId = text(args, "mutation_id");
|
|
18075
|
+
if (!Check2(ApplicationIdSchema2, environmentId) || !Check2(ApplicationReleaseIdSchema2, releaseId) || !Check2(ApplicationActivationIdSchema2, mutationId)) {
|
|
18076
|
+
throw new Error("Invalid application deploy identity");
|
|
18036
18077
|
}
|
|
18037
18078
|
const configurationId = args["configuration_id"];
|
|
18038
|
-
const activationId = args["activation_id"];
|
|
18039
|
-
const expectedActivationId = args["expected_activation_id"];
|
|
18040
18079
|
if (configurationId !== undefined && !Check2(ApplicationConfigurationIdSchema2, configurationId)) {
|
|
18041
18080
|
throw new Error("Invalid application configuration ID");
|
|
18042
18081
|
}
|
|
18043
|
-
if (activationId !== undefined && !Check2(ApplicationActivationIdSchema2, activationId)) {
|
|
18044
|
-
throw new Error("Invalid application activation ID");
|
|
18045
|
-
}
|
|
18046
|
-
if (expectedActivationId !== undefined && expectedActivationId !== null && expectedActivationId !== "absent" && !Check2(ApplicationActivationIdSchema2, expectedActivationId)) {
|
|
18047
|
-
throw new Error("Invalid expected activation ID");
|
|
18048
|
-
}
|
|
18049
18082
|
const configurationWrite = args["configuration_write"];
|
|
18050
18083
|
const parsedConfigurationWrite = configurationWrite === undefined ? undefined : parseApplicationConfigurationWrite(configurationWrite);
|
|
18051
18084
|
const requestedConfigurationId = configurationId ?? parsedConfigurationWrite?.configuration_id;
|
|
18052
18085
|
const body = {
|
|
18086
|
+
mutation_id: mutationId,
|
|
18053
18087
|
release_id: releaseId,
|
|
18054
18088
|
...configurationId === undefined ? {} : { configuration_id: configurationId },
|
|
18055
18089
|
...configurationWrite === undefined ? {} : { configuration_write: configurationWrite },
|
|
18056
|
-
...
|
|
18057
|
-
...
|
|
18058
|
-
expected_activation_id: expectedActivationId === "absent" ? null : expectedActivationId
|
|
18059
|
-
}
|
|
18090
|
+
...typeof args["approved_migration_digest"] === "string" ? { approved_migration_digest: args["approved_migration_digest"] } : {},
|
|
18091
|
+
...args["web"] === undefined ? {} : { web: args["web"] }
|
|
18060
18092
|
};
|
|
18061
|
-
if (!Check2(
|
|
18062
|
-
throw new Error("Invalid application
|
|
18093
|
+
if (!Check2(ApplicationDeployRequestSchema2, body)) {
|
|
18094
|
+
throw new Error("Invalid application deploy request");
|
|
18063
18095
|
}
|
|
18064
|
-
const result = await http.post(`/v1/projects/${project}/applications/${encodeURIComponent(id)}/environments/${encodeURIComponent(environmentId)}/
|
|
18096
|
+
const result = await http.post(`/v1/projects/${project}/applications/${encodeURIComponent(id)}/environments/${encodeURIComponent(environmentId)}/deploy`, body, { timeoutMs: 120000, maxJsonBytes: 131072, responseTimeoutMs: 30000 });
|
|
18065
18097
|
const identity = {
|
|
18066
18098
|
project_ref: ref,
|
|
18067
18099
|
application_id: id,
|
|
18068
18100
|
environment_id: environmentId,
|
|
18069
18101
|
release_id: releaseId,
|
|
18070
|
-
|
|
18071
|
-
...
|
|
18102
|
+
mutation_id: mutationId,
|
|
18103
|
+
...requestedConfigurationId === undefined ? {} : { configuration_id: requestedConfigurationId }
|
|
18072
18104
|
};
|
|
18073
18105
|
if (!result.ok)
|
|
18074
18106
|
return releaseControlMutationFailure(operation, result, identity);
|
|
18075
18107
|
try {
|
|
18076
18108
|
if (result.status !== 200)
|
|
18077
18109
|
throw new Error;
|
|
18078
|
-
const
|
|
18079
|
-
if (
|
|
18110
|
+
const deploy = parseApplicationDeployResult(result.data);
|
|
18111
|
+
if (deploy.project_ref !== ref || deploy.application_id !== id || deploy.environment_id !== environmentId || deploy.release_id !== releaseId || deploy.mutation_id !== mutationId || requestedConfigurationId !== undefined && deploy.configuration_id !== requestedConfigurationId) {
|
|
18080
18112
|
throw new Error;
|
|
18081
|
-
|
|
18113
|
+
}
|
|
18114
|
+
return releaseControlSuccess(operation, deploy);
|
|
18082
18115
|
} catch {
|
|
18083
18116
|
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.status, identity);
|
|
18084
18117
|
}
|
|
@@ -21107,25 +21140,25 @@ var starter_metadata_default = {
|
|
|
21107
21140
|
generatedBy: "supacloud/starter-metadata-v1",
|
|
21108
21141
|
packages: {
|
|
21109
21142
|
compiler: {
|
|
21110
|
-
version: "0.44.
|
|
21143
|
+
version: "0.44.1"
|
|
21111
21144
|
},
|
|
21112
21145
|
app: {
|
|
21113
|
-
version: "0.26.
|
|
21146
|
+
version: "0.26.1",
|
|
21114
21147
|
dependencies: {
|
|
21115
21148
|
rxjs: "7.8.2"
|
|
21116
21149
|
}
|
|
21117
21150
|
},
|
|
21118
21151
|
elysia: {
|
|
21119
|
-
version: "0.29.
|
|
21152
|
+
version: "0.29.2"
|
|
21120
21153
|
},
|
|
21121
21154
|
commands: {
|
|
21122
|
-
version: "0.9.
|
|
21155
|
+
version: "0.9.2"
|
|
21123
21156
|
},
|
|
21124
21157
|
contracts: {
|
|
21125
|
-
version: "0.8.
|
|
21158
|
+
version: "0.8.1"
|
|
21126
21159
|
},
|
|
21127
21160
|
db: {
|
|
21128
|
-
version: "0.16.
|
|
21161
|
+
version: "0.16.1",
|
|
21129
21162
|
peerDependencies: {
|
|
21130
21163
|
"drizzle-orm": "1.0.0-rc.5-169397b"
|
|
21131
21164
|
},
|
|
@@ -21134,7 +21167,7 @@ var starter_metadata_default = {
|
|
|
21134
21167
|
}
|
|
21135
21168
|
},
|
|
21136
21169
|
sdk: {
|
|
21137
|
-
version: "0.41.
|
|
21170
|
+
version: "0.41.2",
|
|
21138
21171
|
peerDependencies: {
|
|
21139
21172
|
"@supabase/supabase-js": "^2.117.3"
|
|
21140
21173
|
}
|
|
@@ -24533,6 +24566,7 @@ var REMOTE_APP_DESCRIPTIONS = {
|
|
|
24533
24566
|
source_environment_id: "[promote-plan/diff/promote] Source environment ID",
|
|
24534
24567
|
mutation_id: "[promote-status/promote-reconcile] Stable promotion mutation ID",
|
|
24535
24568
|
approved_migration_digest: "[promote] Exact reviewed migration execution-plan digest",
|
|
24569
|
+
web: "[release] Immutable staged Web release binding prepared by the deploy profile",
|
|
24536
24570
|
branch_ref: "[preview-plan] Preview branch identity",
|
|
24537
24571
|
branch_name: "[preview/preview-create] Human-readable preview branch name",
|
|
24538
24572
|
data_mode: "[preview-plan/preview/preview-create] schema_only or full_clone",
|
|
@@ -25501,9 +25535,6 @@ async function runAppRelease(request, options, delegate) {
|
|
|
25501
25535
|
if (request.configuration_path !== undefined && request.configuration_id !== undefined) {
|
|
25502
25536
|
throw new Error("app release accepts either --configuration_path or --configuration_id, not both");
|
|
25503
25537
|
}
|
|
25504
|
-
if (request.configuration_path === undefined && request.configuration_id === undefined) {
|
|
25505
|
-
throw new Error("app release requires --configuration_path or --configuration_id");
|
|
25506
|
-
}
|
|
25507
25538
|
if (request.activation_id !== undefined || request.expected_activation_id !== undefined) {
|
|
25508
25539
|
throw new Error("app release generates one activation identity; use app deploy for an exact retry");
|
|
25509
25540
|
}
|
|
@@ -25557,25 +25588,36 @@ async function runAppRelease(request, options, delegate) {
|
|
|
25557
25588
|
configurationWrite = parseApplicationConfigurationWrite(await Bun.file(configurationPath).json());
|
|
25558
25589
|
configurationId = configurationWrite.configuration_id;
|
|
25559
25590
|
} catch {
|
|
25560
|
-
return releasePhaseFailure("configure", releaseControlFailure("applications.
|
|
25591
|
+
return releasePhaseFailure("configure", releaseControlFailure("applications.deploy_application", "INVALID_RESPONSE", null, { project_ref: ref, application_id: id, environment_id: environmentId }), completed);
|
|
25561
25592
|
}
|
|
25562
25593
|
completed.configure = { delegated: true, configuration_id: configurationId };
|
|
25563
25594
|
} else {
|
|
25564
|
-
completed.configure = {
|
|
25595
|
+
completed.configure = {
|
|
25596
|
+
delegated: false,
|
|
25597
|
+
resolved_by: "platform",
|
|
25598
|
+
...configurationId === undefined ? {} : { configuration_id: configurationId }
|
|
25599
|
+
};
|
|
25565
25600
|
}
|
|
25566
25601
|
const deployArgs = {
|
|
25567
|
-
action: "
|
|
25602
|
+
action: "deploy_application",
|
|
25568
25603
|
ref,
|
|
25569
25604
|
id,
|
|
25570
25605
|
environment_id: environmentId,
|
|
25571
25606
|
release_id: releaseId,
|
|
25572
|
-
|
|
25573
|
-
|
|
25574
|
-
...configurationWrite === undefined ? {} : { configuration_write: configurationWrite }
|
|
25607
|
+
mutation_id: activationId,
|
|
25608
|
+
...configurationId === undefined ? {} : { configuration_id: configurationId },
|
|
25609
|
+
...configurationWrite === undefined ? {} : { configuration_write: configurationWrite },
|
|
25610
|
+
...request.web === undefined ? {} : { web: request.web }
|
|
25575
25611
|
};
|
|
25576
25612
|
validateToolArguments(APPLICATION_TOOL_SCHEMA, deployArgs);
|
|
25577
25613
|
const deployed = await delegate(deployArgs);
|
|
25578
25614
|
const deployReceipt = resultObject(deployed);
|
|
25615
|
+
const resolvedConfigurationId = typeof deployReceipt?.configuration_id === "string" ? deployReceipt.configuration_id : undefined;
|
|
25616
|
+
if (resolvedConfigurationId !== undefined) {
|
|
25617
|
+
configurationId = resolvedConfigurationId;
|
|
25618
|
+
const configure = completed.configure;
|
|
25619
|
+
completed.configure = configure && typeof configure === "object" && !Array.isArray(configure) ? { ...configure, configuration_id: resolvedConfigurationId } : { delegated: false, resolved_by: "platform", configuration_id: resolvedConfigurationId };
|
|
25620
|
+
}
|
|
25579
25621
|
if (deployed.isError || !deployReceipt?.ok) {
|
|
25580
25622
|
return releasePhaseFailure("deploy", deployed, completed);
|
|
25581
25623
|
}
|
|
@@ -25588,13 +25630,14 @@ async function runAppRelease(request, options, delegate) {
|
|
|
25588
25630
|
application_id: id,
|
|
25589
25631
|
environment_id: environmentId,
|
|
25590
25632
|
release_id: releaseId,
|
|
25591
|
-
configuration_id: configurationId,
|
|
25633
|
+
...configurationId === undefined ? {} : { configuration_id: configurationId },
|
|
25592
25634
|
manifest_path: manifestPath,
|
|
25593
25635
|
build: buildReceipt ? completed.build : { skipped: true, manifest_path: manifestPath },
|
|
25594
25636
|
phases: completed,
|
|
25595
25637
|
no_op: deployReceipt.action === "no-op" || deployReceipt.no_op === true,
|
|
25596
25638
|
execution_performed: deployReceipt.execution_performed === true,
|
|
25597
|
-
...typeof deployReceipt.activation_id === "string" ? { activation_id: deployReceipt.activation_id } : {}
|
|
25639
|
+
...typeof deployReceipt.activation_id === "string" ? { activation_id: deployReceipt.activation_id } : {},
|
|
25640
|
+
...deployReceipt.web === undefined ? {} : { web: deployReceipt.web }
|
|
25598
25641
|
};
|
|
25599
25642
|
return request.format === "json" || request.json === true ? textResult(JSON.stringify(result, null, 2)) : textResult([
|
|
25600
25643
|
`${ref}/${id}/${environmentId}: ${result.no_op ? "no-op" : "released"}`,
|
|
@@ -27200,6 +27243,7 @@ import { createHash as createHash8 } from "node:crypto";
|
|
|
27200
27243
|
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readdirSync as readdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "node:fs";
|
|
27201
27244
|
import { dirname as dirname10, join as join16, relative as relative9, resolve as resolve21 } from "node:path";
|
|
27202
27245
|
var SAFE_PROJECT_REF = /^[A-Za-z0-9_-]{1,64}$/;
|
|
27246
|
+
var SAFE_ENVIRONMENT_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
27203
27247
|
var BACKUP_ID = /^logical-full_[A-Za-z0-9_-]{1,64}_[a-f0-9]{32}$/;
|
|
27204
27248
|
var SHA256 = /^[a-f0-9]{64}$/;
|
|
27205
27249
|
var SAFE_DATABASE = /^[^\u0000-\u001f\u007f]{1,128}$/;
|
|
@@ -27440,6 +27484,27 @@ function genericScopedReleaseScopeJson(scope) {
|
|
|
27440
27484
|
function genericScopedReleaseScopeSha256(scope) {
|
|
27441
27485
|
return createHash8("sha256").update(genericScopedReleaseScopeJson(scope)).digest("hex");
|
|
27442
27486
|
}
|
|
27487
|
+
function scopeEnvironmentId(scope, action) {
|
|
27488
|
+
const environmentId = isRecord6(scope) ? scope.targetEnvironmentId : undefined;
|
|
27489
|
+
if (typeof environmentId !== "string" || !SAFE_ENVIRONMENT_ID.test(environmentId)) {
|
|
27490
|
+
throw new Error(`Scope for ${action} must be regenerated with a concrete targetEnvironmentId`);
|
|
27491
|
+
}
|
|
27492
|
+
return environmentId;
|
|
27493
|
+
}
|
|
27494
|
+
function requestedScopeEnvironment(args, action) {
|
|
27495
|
+
const environmentId = args.environment_id;
|
|
27496
|
+
if (typeof environmentId !== "string" || !SAFE_ENVIRONMENT_ID.test(environmentId)) {
|
|
27497
|
+
throw new Error(`'environment_id' is required for ${action} and must identify one deployment environment`);
|
|
27498
|
+
}
|
|
27499
|
+
return environmentId;
|
|
27500
|
+
}
|
|
27501
|
+
function assertScopeEnvironment(scope, requestedEnvironmentId, action) {
|
|
27502
|
+
const targetEnvironmentId = scopeEnvironmentId(scope, action);
|
|
27503
|
+
if (targetEnvironmentId !== requestedEnvironmentId) {
|
|
27504
|
+
throw new Error(`Scope target environment '${targetEnvironmentId}' does not match requested environment '${requestedEnvironmentId}'`);
|
|
27505
|
+
}
|
|
27506
|
+
return targetEnvironmentId;
|
|
27507
|
+
}
|
|
27443
27508
|
function runGitRevParse(cwd, args) {
|
|
27444
27509
|
const res = Bun.spawnSync(["git", ...args], { cwd });
|
|
27445
27510
|
if (res.exitCode !== 0 || !res.stdout)
|
|
@@ -27566,10 +27631,10 @@ function collectScopeFiles(cwd, file, files, dir, task) {
|
|
|
27566
27631
|
function handleScopeRebind(args) {
|
|
27567
27632
|
const cwd = typeof args.cwd === "string" && args.cwd.trim() ? resolve21(args.cwd.trim()) : process.cwd();
|
|
27568
27633
|
const targetBaseCommit = resolveGitBaseCommit(cwd, args.base_commit);
|
|
27634
|
+
const requestedEnvironmentId = requestedScopeEnvironment(args, "scope_rebind");
|
|
27569
27635
|
const scopeFiles = collectScopeFiles(cwd, args.file, args.files, args.dir, args.task);
|
|
27570
27636
|
const dryRun = args.dry_run === true;
|
|
27571
|
-
const
|
|
27572
|
-
for (const filePath of scopeFiles) {
|
|
27637
|
+
const parsedScopes = scopeFiles.map((filePath) => {
|
|
27573
27638
|
let content;
|
|
27574
27639
|
try {
|
|
27575
27640
|
content = readFileSync10(filePath, "utf8");
|
|
@@ -27582,15 +27647,20 @@ function handleScopeRebind(args) {
|
|
|
27582
27647
|
} catch {
|
|
27583
27648
|
throw new Error(`Scope file '${filePath}' is not valid JSON`);
|
|
27584
27649
|
}
|
|
27585
|
-
|
|
27650
|
+
const targetEnvironmentId = assertScopeEnvironment(parsed, requestedEnvironmentId, "scope_rebind");
|
|
27651
|
+
const previousBaseCommit = parsed.baseCommit;
|
|
27652
|
+
if (typeof previousBaseCommit !== "string" || !/^[0-9a-f]{40}$/.test(previousBaseCommit)) {
|
|
27586
27653
|
throw new Error(`Scope file '${filePath}' has missing or invalid baseCommit`);
|
|
27587
27654
|
}
|
|
27655
|
+
return { filePath, parsed, targetEnvironmentId };
|
|
27656
|
+
});
|
|
27657
|
+
const scopes = [];
|
|
27658
|
+
for (const { filePath, parsed, targetEnvironmentId } of parsedScopes) {
|
|
27588
27659
|
const previousBaseCommit = parsed.baseCommit;
|
|
27589
27660
|
const updated = previousBaseCommit !== targetBaseCommit;
|
|
27590
27661
|
if (updated) {
|
|
27591
27662
|
parsed.baseCommit = targetBaseCommit;
|
|
27592
27663
|
}
|
|
27593
|
-
const canonicalJson = genericScopedReleaseScopeJson(parsed);
|
|
27594
27664
|
const scopeSha256 = genericScopedReleaseScopeSha256(parsed);
|
|
27595
27665
|
if (updated && !dryRun) {
|
|
27596
27666
|
const formatted = JSON.stringify(canonicalValue(parsed), null, 2) + `
|
|
@@ -27603,6 +27673,7 @@ function handleScopeRebind(args) {
|
|
|
27603
27673
|
target_project_ref: typeof parsed.targetProjectRef === "string" ? parsed.targetProjectRef : "",
|
|
27604
27674
|
previous_base_commit: previousBaseCommit,
|
|
27605
27675
|
new_base_commit: targetBaseCommit,
|
|
27676
|
+
target_environment_id: targetEnvironmentId,
|
|
27606
27677
|
scope_sha256: scopeSha256,
|
|
27607
27678
|
updated
|
|
27608
27679
|
});
|
|
@@ -27617,6 +27688,7 @@ function handleScopeRebind(args) {
|
|
|
27617
27688
|
}
|
|
27618
27689
|
function handleScopeInspect(args) {
|
|
27619
27690
|
const cwd = typeof args.cwd === "string" && args.cwd.trim() ? resolve21(args.cwd.trim()) : process.cwd();
|
|
27691
|
+
const requestedEnvironmentId = requestedScopeEnvironment(args, "scope_inspect");
|
|
27620
27692
|
if (typeof args.file !== "string" || !args.file.trim()) {
|
|
27621
27693
|
throw new Error("'file' is required for scope_inspect");
|
|
27622
27694
|
}
|
|
@@ -27646,7 +27718,11 @@ function handleScopeInspect(args) {
|
|
|
27646
27718
|
} catch {
|
|
27647
27719
|
throw new Error(`Scope file '${args.file}' is not valid JSON`);
|
|
27648
27720
|
}
|
|
27649
|
-
if (!isRecord6(parsed)
|
|
27721
|
+
if (!isRecord6(parsed)) {
|
|
27722
|
+
throw new Error(`Scope file '${args.file}' must be an object and must be regenerated`);
|
|
27723
|
+
}
|
|
27724
|
+
const targetEnvironmentId = assertScopeEnvironment(parsed, requestedEnvironmentId, "scope_inspect");
|
|
27725
|
+
if (typeof parsed.baseCommit !== "string" || !/^[0-9a-f]{40}$/.test(parsed.baseCommit)) {
|
|
27650
27726
|
throw new Error(`Scope file '${args.file}' has missing or invalid baseCommit`);
|
|
27651
27727
|
}
|
|
27652
27728
|
const scopeSha256 = genericScopedReleaseScopeSha256(parsed);
|
|
@@ -27656,6 +27732,7 @@ function handleScopeInspect(args) {
|
|
|
27656
27732
|
scope: {
|
|
27657
27733
|
task_id: parsed.taskId,
|
|
27658
27734
|
target_project_ref: parsed.targetProjectRef,
|
|
27735
|
+
target_environment_id: targetEnvironmentId,
|
|
27659
27736
|
base_commit: parsed.baseCommit,
|
|
27660
27737
|
functions: parsed.functions,
|
|
27661
27738
|
excluded_functions: parsed.excludedFunctions,
|
|
@@ -27693,6 +27770,7 @@ function handleScopeCreate(args, fallbackRef) {
|
|
|
27693
27770
|
if (typeof args.task !== "string" || !args.task.trim()) {
|
|
27694
27771
|
throw new Error("'task' is required for scope_create");
|
|
27695
27772
|
}
|
|
27773
|
+
const targetEnvironmentId = requestedScopeEnvironment(args, "scope_create");
|
|
27696
27774
|
const projectRef = typeof args.ref === "string" && args.ref.trim() || fallbackRef;
|
|
27697
27775
|
if (!projectRef) {
|
|
27698
27776
|
throw new Error("'ref' is required for scope_create");
|
|
@@ -27709,6 +27787,7 @@ function handleScopeCreate(args, fallbackRef) {
|
|
|
27709
27787
|
functions: parseCommaList(args.functions),
|
|
27710
27788
|
migrations: parseCommaList(args.migrations),
|
|
27711
27789
|
targetProjectRef: projectRef,
|
|
27790
|
+
targetEnvironmentId,
|
|
27712
27791
|
taskId: String(args.task).trim(),
|
|
27713
27792
|
web: Boolean(args.web)
|
|
27714
27793
|
};
|
|
@@ -27721,6 +27800,7 @@ function handleScopeCreate(args, fallbackRef) {
|
|
|
27721
27800
|
file: relative9(cwd, filePath),
|
|
27722
27801
|
task_id: scope.taskId,
|
|
27723
27802
|
target_project_ref: projectRef,
|
|
27803
|
+
target_environment_id: targetEnvironmentId,
|
|
27724
27804
|
base_commit: targetBaseCommit,
|
|
27725
27805
|
scope_sha256: scopeSha256,
|
|
27726
27806
|
scope
|
|
@@ -27747,6 +27827,7 @@ function registerReleaseTools(server, http, options = {}) {
|
|
|
27747
27827
|
dir: optional(String2(), "[scope_rebind] Directory containing release scope JSON files (defaults to supacloud/fa/release-scopes, release-scopes, or scopes)"),
|
|
27748
27828
|
task: optional(String2(), "[scope_rebind/scope_create] Task ID or prefix filter for scope files"),
|
|
27749
27829
|
base_commit: optional(String2(), "[scope_rebind/scope_create] Target 40-character base commit SHA or git ref (defaults to origin/main -> main -> HEAD^ -> HEAD)"),
|
|
27830
|
+
environment_id: optional(String2(), "[scope_inspect/scope_rebind/scope_create] Exact target deployment environment"),
|
|
27750
27831
|
functions: optional(String2(), "[scope_create] Comma-separated list of functions to deploy"),
|
|
27751
27832
|
excluded_functions: optional(String2(), "[scope_create] Comma-separated list of functions to exclude"),
|
|
27752
27833
|
migrations: optional(String2(), "[scope_create] Comma-separated list of migrations to apply"),
|
|
@@ -28148,6 +28229,33 @@ function selectDeployment(deployments, requestedId, projectName) {
|
|
|
28148
28229
|
const ids = deployments.map((deployment) => deployment.id).sort().join(", ");
|
|
28149
28230
|
throw new Error(deployments.length === 0 ? "No frontend deployments exist for this project" : `Multiple frontend deployments found (${ids}). Set frontend.id in supacloud.json or pass --id`);
|
|
28150
28231
|
}
|
|
28232
|
+
function selectFrontendTarget(configRoot, config) {
|
|
28233
|
+
if (config.targets === undefined && config.frontend === undefined)
|
|
28234
|
+
return null;
|
|
28235
|
+
const targets = config.targets ? Object.entries(config.targets).filter(([, target]) => target.type === "frontend") : [["frontend", {
|
|
28236
|
+
type: "frontend",
|
|
28237
|
+
root: config.frontend?.root,
|
|
28238
|
+
id: config.frontend?.id,
|
|
28239
|
+
buildCommand: config.frontend?.buildCommand,
|
|
28240
|
+
outputDirectory: config.frontend?.outputDirectory,
|
|
28241
|
+
buildEnv: config.frontend?.buildEnv
|
|
28242
|
+
}]];
|
|
28243
|
+
if (targets.length === 0)
|
|
28244
|
+
return null;
|
|
28245
|
+
if (config.defaultTarget) {
|
|
28246
|
+
const selected = targets.find(([name]) => name === config.defaultTarget);
|
|
28247
|
+
if (selected)
|
|
28248
|
+
return { name: selected[0], config: selected[1], root: targetRoot(configRoot, selected[1], selected[0]) };
|
|
28249
|
+
}
|
|
28250
|
+
const namedWeb = targets.find(([name]) => name === "web");
|
|
28251
|
+
if (namedWeb)
|
|
28252
|
+
return { name: namedWeb[0], config: namedWeb[1], root: targetRoot(configRoot, namedWeb[1], namedWeb[0]) };
|
|
28253
|
+
if (targets.length === 1) {
|
|
28254
|
+
const selected = targets[0];
|
|
28255
|
+
return { name: selected[0], config: selected[1], root: targetRoot(configRoot, selected[1], selected[0]) };
|
|
28256
|
+
}
|
|
28257
|
+
throw new Error(`Multiple frontend deploy targets found (${targets.map(([name]) => name).sort().join(", ")}). Set defaultTarget to the Web target`);
|
|
28258
|
+
}
|
|
28151
28259
|
function targetRoot(configRoot, target, name) {
|
|
28152
28260
|
const root = resolve22(configRoot, target.root || (name === "frontend" ? "." : name));
|
|
28153
28261
|
const prefix = `${resolve22(configRoot)}${sep5}`;
|
|
@@ -28320,6 +28428,71 @@ function payload(response) {
|
|
|
28320
28428
|
throw new Error("Deployment operation returned an invalid response");
|
|
28321
28429
|
return parsed;
|
|
28322
28430
|
}
|
|
28431
|
+
async function stageApplicationWebRelease(http, projectRef, configRoot, skipBuild, json, environmentVariables) {
|
|
28432
|
+
const target = selectFrontendTarget(configRoot, await readDeployConfig(configRoot));
|
|
28433
|
+
if (!target)
|
|
28434
|
+
return null;
|
|
28435
|
+
const projectDirectory = target.root;
|
|
28436
|
+
const targetState = await lstat5(projectDirectory).catch(() => null);
|
|
28437
|
+
if (!targetState?.isDirectory() || targetState.isSymbolicLink()) {
|
|
28438
|
+
throw new Error(`Deploy target '${target.name}' root is not a regular directory: ${projectDirectory}`);
|
|
28439
|
+
}
|
|
28440
|
+
const requestedId = target.config.id;
|
|
28441
|
+
const listResponse = await http.get(`/v1/projects/${encodeURIComponent(projectRef)}/frontend/deployments`);
|
|
28442
|
+
if (!listResponse.ok)
|
|
28443
|
+
throw new Error(`Failed to list frontend deployments (HTTP ${listResponse.status})`);
|
|
28444
|
+
const selected = selectDeployment(deploymentList(listResponse.data), requestedId, await packageName(projectDirectory));
|
|
28445
|
+
const configuredBuildCommand = String(target.config.buildCommand || selected.buildCommand || "").trim();
|
|
28446
|
+
const buildCommand = configuredBuildCommand || (skipBuild ? "" : await defaultBuildCommand(projectDirectory, configRoot));
|
|
28447
|
+
const configuredOutput = String(target.config.outputDirectory || "").trim();
|
|
28448
|
+
const remoteOutput = selected.outputDirectory && selected.outputDirectory !== "." ? selected.outputDirectory : "";
|
|
28449
|
+
const outputDirectory = resolveInsideProject(projectDirectory, configuredOutput || remoteOutput || defaultOutputDirectory(selected.framework));
|
|
28450
|
+
const build = createBuildEnvironment(target.config.buildEnv, environmentVariables);
|
|
28451
|
+
const report = phaseReporter(json);
|
|
28452
|
+
report("web", `${target.name} (${selected.id})`);
|
|
28453
|
+
assertBuildEnvironment(build, skipBuild);
|
|
28454
|
+
if (!skipBuild) {
|
|
28455
|
+
report("build", buildCommand);
|
|
28456
|
+
await runBuild(buildCommand, projectDirectory, build.env, json);
|
|
28457
|
+
} else {
|
|
28458
|
+
report("build", "skipped");
|
|
28459
|
+
}
|
|
28460
|
+
report("package", relative10(projectDirectory, outputDirectory) || ".");
|
|
28461
|
+
const archive = await createFrontendArchive(outputDirectory);
|
|
28462
|
+
try {
|
|
28463
|
+
const authority = payload(await readFrontendReleaseAuthority(http, projectRef, selected.id));
|
|
28464
|
+
const activeReleaseId = typeof authority.active_release_id === "string" ? authority.active_release_id : null;
|
|
28465
|
+
const activeActivationId = typeof authority.active_activation_id === "string" ? authority.active_activation_id : null;
|
|
28466
|
+
const current = Array.isArray(authority.releases) ? record4(authority.releases[0]) : null;
|
|
28467
|
+
if (archive.sha256 === activeReleaseId && archive.treeSha256 !== current?.tree_sha256) {
|
|
28468
|
+
throw new Error("Active Web release tree does not match the local archive");
|
|
28469
|
+
}
|
|
28470
|
+
if (archive.treeSha256 === current?.tree_sha256) {
|
|
28471
|
+
report("done", "Web already current");
|
|
28472
|
+
return {};
|
|
28473
|
+
}
|
|
28474
|
+
report("upload", `${archive.fileCount} files`);
|
|
28475
|
+
const uploaded = payload(await uploadFrontendRelease(http, projectRef, selected.id, archive.archivePath));
|
|
28476
|
+
const release = record4(uploaded.release);
|
|
28477
|
+
const releaseId = requiredString(release?.release_id, "release.release_id");
|
|
28478
|
+
if (releaseId !== archive.sha256)
|
|
28479
|
+
throw new Error("Uploaded Web release identity does not match the local archive");
|
|
28480
|
+
if (release?.tree_sha256 !== archive.treeSha256)
|
|
28481
|
+
throw new Error("Uploaded Web release tree does not match the local build");
|
|
28482
|
+
report("done", releaseId.slice(0, 12));
|
|
28483
|
+
return {
|
|
28484
|
+
request: {
|
|
28485
|
+
deployment_id: selected.id,
|
|
28486
|
+
release_id: releaseId,
|
|
28487
|
+
expected_active_release_id: activeReleaseId ?? "absent",
|
|
28488
|
+
expected_activation_id: activeActivationId ?? "absent",
|
|
28489
|
+
mutation_id: crypto.randomUUID()
|
|
28490
|
+
}
|
|
28491
|
+
};
|
|
28492
|
+
} finally {
|
|
28493
|
+
await archive.cleanup();
|
|
28494
|
+
}
|
|
28495
|
+
}
|
|
28323
28496
|
function phaseReporter(json) {
|
|
28324
28497
|
const started = performance.now();
|
|
28325
28498
|
return (phase, detail) => {
|
|
@@ -28368,12 +28541,10 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28368
28541
|
}
|
|
28369
28542
|
const configurationPath = options.application.configurationPath?.trim();
|
|
28370
28543
|
const configurationId = options.application.configurationId?.trim();
|
|
28371
|
-
if (!configurationPath && !configurationId) {
|
|
28372
|
-
throw new Error("Application profile requires SUPACLOUD_APPLICATION_CONFIGURATION_PATH or SUPACLOUD_APPLICATION_CONFIGURATION_ID");
|
|
28373
|
-
}
|
|
28374
28544
|
if (configurationPath && configurationId) {
|
|
28375
28545
|
throw new Error("Application profile must set only one of SUPACLOUD_APPLICATION_CONFIGURATION_PATH or SUPACLOUD_APPLICATION_CONFIGURATION_ID");
|
|
28376
28546
|
}
|
|
28547
|
+
const stagedWeb = await stageApplicationWebRelease(http, projectRef, configRoot, args.skip_build === true, args.json === true, options.environmentVariables);
|
|
28377
28548
|
const result = await options.applicationRelease({
|
|
28378
28549
|
action: "release",
|
|
28379
28550
|
ref: projectRef,
|
|
@@ -28384,6 +28555,7 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28384
28555
|
...configurationId ? { configuration_id: configurationId } : {},
|
|
28385
28556
|
...options.application.manifestPath ? { manifest_path: options.application.manifestPath } : {},
|
|
28386
28557
|
...args.skip_build === true ? { skip_build: true } : {},
|
|
28558
|
+
...stagedWeb?.request === undefined ? {} : { web: stagedWeb.request },
|
|
28387
28559
|
...args.json === true ? { format: "json", json: true } : {}
|
|
28388
28560
|
});
|
|
28389
28561
|
return result;
|
|
@@ -28887,10 +29059,320 @@ function registerRemoteDevTools(server, options = {}) {
|
|
|
28887
29059
|
throw new Error("Unsupported remote dev action");
|
|
28888
29060
|
});
|
|
28889
29061
|
}
|
|
29062
|
+
|
|
29063
|
+
// src/shared/tools/developer-experience-tools.ts
|
|
29064
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
29065
|
+
import { mkdir as mkdir7, readdir as readdir8, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
|
|
29066
|
+
import { dirname as dirname12, join as join19, resolve as resolve24 } from "node:path";
|
|
29067
|
+
var initToolSchema = {
|
|
29068
|
+
root: optional(String2(), "Project directory to initialize (default: current directory)"),
|
|
29069
|
+
json: optional(Boolean2(), "Emit one machine-readable JSON result")
|
|
29070
|
+
};
|
|
29071
|
+
var environmentToolSchema = {
|
|
29072
|
+
action: withDescription(stringEnum(["list", "check"]), "Environment profile inspection action"),
|
|
29073
|
+
root: optional(String2(), "Project directory containing .env.supacloud.* files"),
|
|
29074
|
+
json: optional(Boolean2(), "Emit one machine-readable JSON result")
|
|
29075
|
+
};
|
|
29076
|
+
var TEST_PROFILE = [
|
|
29077
|
+
"SUPACLOUD_ENV=test",
|
|
29078
|
+
"SUPACLOUD_API_URL=https://management.test.example.com",
|
|
29079
|
+
"SUPACLOUD_API_TOKEN=<test-management-api-token>",
|
|
29080
|
+
"SUPACLOUD_PROJECT_REF=<test-project-ref>",
|
|
29081
|
+
""
|
|
29082
|
+
].join(`
|
|
29083
|
+
`);
|
|
29084
|
+
var PRODUCTION_PROFILE = [
|
|
29085
|
+
"SUPACLOUD_ENV=production",
|
|
29086
|
+
"SUPACLOUD_API_URL=https://management.example.com",
|
|
29087
|
+
"SUPACLOUD_API_TOKEN=<production-management-api-token>",
|
|
29088
|
+
"SUPACLOUD_PROJECT_REF=<production-project-ref>",
|
|
29089
|
+
""
|
|
29090
|
+
].join(`
|
|
29091
|
+
`);
|
|
29092
|
+
function textResult3(text, isError = false) {
|
|
29093
|
+
return { isError, content: [{ type: "text", text }] };
|
|
29094
|
+
}
|
|
29095
|
+
function jsonResult(value, isError = false) {
|
|
29096
|
+
return textResult3(JSON.stringify(value, null, 2), isError);
|
|
29097
|
+
}
|
|
29098
|
+
function record5(value) {
|
|
29099
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
29100
|
+
}
|
|
29101
|
+
function packageDependencies(manifest) {
|
|
29102
|
+
return new Set([
|
|
29103
|
+
...Object.keys(manifest.dependencies ?? {}),
|
|
29104
|
+
...Object.keys(manifest.devDependencies ?? {})
|
|
29105
|
+
]);
|
|
29106
|
+
}
|
|
29107
|
+
function outputDirectoryFor(manifest) {
|
|
29108
|
+
const dependencies = packageDependencies(manifest);
|
|
29109
|
+
if (dependencies.has("next"))
|
|
29110
|
+
return "out";
|
|
29111
|
+
if (dependencies.has("@sveltejs/kit") || dependencies.has("svelte"))
|
|
29112
|
+
return "build";
|
|
29113
|
+
return "dist";
|
|
29114
|
+
}
|
|
29115
|
+
async function readPackageManifest(root) {
|
|
29116
|
+
const path = join19(root, "package.json");
|
|
29117
|
+
if (!existsSync15(path))
|
|
29118
|
+
return {};
|
|
29119
|
+
try {
|
|
29120
|
+
const parsed = JSON.parse(await readFile7(path, "utf8"));
|
|
29121
|
+
const value = record5(parsed);
|
|
29122
|
+
if (!value)
|
|
29123
|
+
throw new Error("package.json must contain an object");
|
|
29124
|
+
const scripts = record5(value.scripts);
|
|
29125
|
+
const dependencies = record5(value.dependencies);
|
|
29126
|
+
const devDependencies = record5(value.devDependencies);
|
|
29127
|
+
return {
|
|
29128
|
+
scripts: scripts ?? undefined,
|
|
29129
|
+
dependencies: dependencies ?? undefined,
|
|
29130
|
+
devDependencies: devDependencies ?? undefined
|
|
29131
|
+
};
|
|
29132
|
+
} catch (error) {
|
|
29133
|
+
throw new Error(`Invalid package.json: ${error instanceof Error ? error.message : String(error)}`);
|
|
29134
|
+
}
|
|
29135
|
+
}
|
|
29136
|
+
async function writeNewFile(path, content) {
|
|
29137
|
+
try {
|
|
29138
|
+
await writeFile6(path, content, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
29139
|
+
return true;
|
|
29140
|
+
} catch (error) {
|
|
29141
|
+
if (error instanceof Error && "code" in error && error.code === "EEXIST")
|
|
29142
|
+
return false;
|
|
29143
|
+
throw error;
|
|
29144
|
+
}
|
|
29145
|
+
}
|
|
29146
|
+
async function ensureGitignore(root) {
|
|
29147
|
+
const path = join19(root, ".gitignore");
|
|
29148
|
+
const existing = existsSync15(path) ? await readFile7(path, "utf8") : "";
|
|
29149
|
+
const required = [".env.supacloud.*", "!.env.supacloud.*.example"];
|
|
29150
|
+
const missing = required.filter((entry) => !existing.split(/\r?\n/).includes(entry));
|
|
29151
|
+
if (missing.length === 0)
|
|
29152
|
+
return false;
|
|
29153
|
+
const prefix = existing.length > 0 && !existing.endsWith(`
|
|
29154
|
+
`) ? `${existing}
|
|
29155
|
+
` : existing;
|
|
29156
|
+
await writeFile6(path, `${prefix}${missing.join(`
|
|
29157
|
+
`)}
|
|
29158
|
+
`, "utf8");
|
|
29159
|
+
return true;
|
|
29160
|
+
}
|
|
29161
|
+
async function initializeProject(request, options) {
|
|
29162
|
+
const root = resolve24(request.root || options.cwd || process.cwd());
|
|
29163
|
+
await mkdir7(root, { recursive: true });
|
|
29164
|
+
const configPath = join19(root, "supacloud.json");
|
|
29165
|
+
if (existsSync15(configPath)) {
|
|
29166
|
+
throw new Error(`supacloud.json already exists in ${root}; init never overwrites project configuration`);
|
|
29167
|
+
}
|
|
29168
|
+
const manifest = await readPackageManifest(root);
|
|
29169
|
+
const hasBuildScript = typeof manifest.scripts?.build === "string" && Boolean(manifest.scripts.build.trim());
|
|
29170
|
+
const outputDirectory = outputDirectoryFor(manifest);
|
|
29171
|
+
const config = {
|
|
29172
|
+
frontend: {
|
|
29173
|
+
root: ".",
|
|
29174
|
+
outputDirectory
|
|
29175
|
+
}
|
|
29176
|
+
};
|
|
29177
|
+
const created = [];
|
|
29178
|
+
try {
|
|
29179
|
+
await writeFile6(configPath, `${JSON.stringify(config, null, 2)}
|
|
29180
|
+
`, {
|
|
29181
|
+
encoding: "utf8",
|
|
29182
|
+
flag: "wx",
|
|
29183
|
+
mode: 420
|
|
29184
|
+
});
|
|
29185
|
+
} catch (error) {
|
|
29186
|
+
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
29187
|
+
throw new Error(`supacloud.json already exists in ${root}; init never overwrites project configuration`);
|
|
29188
|
+
}
|
|
29189
|
+
throw error;
|
|
29190
|
+
}
|
|
29191
|
+
created.push("supacloud.json");
|
|
29192
|
+
if (await writeNewFile(join19(root, ".env.supacloud.test.example"), TEST_PROFILE)) {
|
|
29193
|
+
created.push(".env.supacloud.test.example");
|
|
29194
|
+
}
|
|
29195
|
+
if (await writeNewFile(join19(root, ".env.supacloud.production.example"), PRODUCTION_PROFILE)) {
|
|
29196
|
+
created.push(".env.supacloud.production.example");
|
|
29197
|
+
}
|
|
29198
|
+
if (await ensureGitignore(root))
|
|
29199
|
+
created.push(".gitignore");
|
|
29200
|
+
const result = {
|
|
29201
|
+
schema: "supacloud.developer-experience.init.v1",
|
|
29202
|
+
ok: true,
|
|
29203
|
+
root,
|
|
29204
|
+
created,
|
|
29205
|
+
detected: {
|
|
29206
|
+
package_json: existsSync15(join19(root, "package.json")),
|
|
29207
|
+
build_script: hasBuildScript,
|
|
29208
|
+
output_directory: outputDirectory
|
|
29209
|
+
},
|
|
29210
|
+
next: [
|
|
29211
|
+
"cp .env.supacloud.test.example .env.supacloud.test",
|
|
29212
|
+
"supacloud env check",
|
|
29213
|
+
"supacloud --env test deploy"
|
|
29214
|
+
]
|
|
29215
|
+
};
|
|
29216
|
+
if (request.json === true)
|
|
29217
|
+
return jsonResult(result);
|
|
29218
|
+
return textResult3([
|
|
29219
|
+
`Initialized SupaCloud deployment in ${root}.`,
|
|
29220
|
+
`Created: ${created.join(", ")}.`,
|
|
29221
|
+
hasBuildScript ? `Detected package.json build script; deploy output defaults to ${outputDirectory}.` : "No package.json build script detected; add one before deploying.",
|
|
29222
|
+
"",
|
|
29223
|
+
...result.next
|
|
29224
|
+
].join(`
|
|
29225
|
+
`));
|
|
29226
|
+
}
|
|
29227
|
+
function profileNameFromFile(name) {
|
|
29228
|
+
const match = name.match(/^\.env\.supacloud\.([A-Za-z0-9][A-Za-z0-9_-]{0,63})$/);
|
|
29229
|
+
return match?.[1] ?? null;
|
|
29230
|
+
}
|
|
29231
|
+
async function environmentProfiles(root) {
|
|
29232
|
+
const entries = await readdir8(root, { withFileTypes: true }).catch((error) => {
|
|
29233
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
29234
|
+
return [];
|
|
29235
|
+
throw error;
|
|
29236
|
+
});
|
|
29237
|
+
return entries.filter((entry) => entry.isFile()).map((entry) => {
|
|
29238
|
+
const name = profileNameFromFile(entry.name);
|
|
29239
|
+
return name ? { name, path: join19(root, entry.name), exists: true } : null;
|
|
29240
|
+
}).filter((profile) => profile !== null).sort((left, right) => left.name.localeCompare(right.name));
|
|
29241
|
+
}
|
|
29242
|
+
function statusMissing(context) {
|
|
29243
|
+
if (context.credentialScope === "management") {
|
|
29244
|
+
return [
|
|
29245
|
+
!context.apiUrl ? "SUPACLOUD_API_URL" : null,
|
|
29246
|
+
!context.apiToken ? "SUPACLOUD_API_TOKEN" : null,
|
|
29247
|
+
!context.projectRef ? "SUPACLOUD_PROJECT_REF" : null
|
|
29248
|
+
].filter((value) => value !== null);
|
|
29249
|
+
}
|
|
29250
|
+
if (context.credentialScope === "project_application") {
|
|
29251
|
+
return [
|
|
29252
|
+
!context.inferredSupabaseUrl ? "SUPABASE_URL" : null,
|
|
29253
|
+
!context.inferredServiceRoleKey ? "SUPABASE_SERVICE_ROLE_KEY" : null,
|
|
29254
|
+
!context.projectRef ? "SUPACLOUD_PROJECT_REF" : null
|
|
29255
|
+
].filter((value) => value !== null);
|
|
29256
|
+
}
|
|
29257
|
+
return ["SUPACLOUD_API_URL", "SUPACLOUD_API_TOKEN", "SUPACLOUD_PROJECT_REF"];
|
|
29258
|
+
}
|
|
29259
|
+
function deployMissing(context) {
|
|
29260
|
+
const missing = statusMissing(context);
|
|
29261
|
+
if (context.credentialScope !== "management") {
|
|
29262
|
+
return [...missing, "Management API context"];
|
|
29263
|
+
}
|
|
29264
|
+
if (context.applicationId) {
|
|
29265
|
+
if (!context.applicationEnvironmentId)
|
|
29266
|
+
missing.push("SUPACLOUD_APPLICATION_ENVIRONMENT_ID");
|
|
29267
|
+
if (!context.applicationConfigurationPath && !context.applicationConfigurationId) {
|
|
29268
|
+
missing.push("SUPACLOUD_APPLICATION_CONFIGURATION_PATH or SUPACLOUD_APPLICATION_CONFIGURATION_ID");
|
|
29269
|
+
}
|
|
29270
|
+
}
|
|
29271
|
+
return missing;
|
|
29272
|
+
}
|
|
29273
|
+
async function inspectProfile(profile) {
|
|
29274
|
+
try {
|
|
29275
|
+
const context = resolveSupaCloudContext({}, dirname12(profile.path), {
|
|
29276
|
+
environmentName: profile.name
|
|
29277
|
+
});
|
|
29278
|
+
const status = statusMissing(context);
|
|
29279
|
+
const deploy = deployMissing(context);
|
|
29280
|
+
return {
|
|
29281
|
+
name: profile.name,
|
|
29282
|
+
path: profile.path,
|
|
29283
|
+
environment: context.environment || null,
|
|
29284
|
+
production: context.production,
|
|
29285
|
+
source: "named_env_file",
|
|
29286
|
+
credentialScope: context.credentialScope,
|
|
29287
|
+
projectRef: context.projectRef || null,
|
|
29288
|
+
statusReady: status.length === 0,
|
|
29289
|
+
statusMissing: status,
|
|
29290
|
+
deployReady: deploy.length === 0,
|
|
29291
|
+
deployMissing: deploy,
|
|
29292
|
+
hasApiToken: Boolean(context.apiToken),
|
|
29293
|
+
hasServiceRoleKey: Boolean(context.inferredServiceRoleKey),
|
|
29294
|
+
error: null
|
|
29295
|
+
};
|
|
29296
|
+
} catch (error) {
|
|
29297
|
+
return {
|
|
29298
|
+
name: profile.name,
|
|
29299
|
+
path: profile.path,
|
|
29300
|
+
environment: null,
|
|
29301
|
+
production: false,
|
|
29302
|
+
source: "invalid",
|
|
29303
|
+
credentialScope: "incomplete",
|
|
29304
|
+
projectRef: null,
|
|
29305
|
+
statusReady: false,
|
|
29306
|
+
statusMissing: [],
|
|
29307
|
+
deployReady: false,
|
|
29308
|
+
deployMissing: [],
|
|
29309
|
+
hasApiToken: false,
|
|
29310
|
+
hasServiceRoleKey: false,
|
|
29311
|
+
error: error instanceof Error ? error.message : String(error)
|
|
29312
|
+
};
|
|
29313
|
+
}
|
|
29314
|
+
}
|
|
29315
|
+
async function inspectEnvironment(request, options) {
|
|
29316
|
+
const root = resolve24(request.root || options.cwd || process.cwd());
|
|
29317
|
+
const profiles = await environmentProfiles(root);
|
|
29318
|
+
if (request.action === "list") {
|
|
29319
|
+
const active = options.activeContext?.environment || null;
|
|
29320
|
+
const result = {
|
|
29321
|
+
schema: "supacloud.developer-experience.environments.v1",
|
|
29322
|
+
ok: true,
|
|
29323
|
+
root,
|
|
29324
|
+
active,
|
|
29325
|
+
environments: profiles.map((profile) => ({
|
|
29326
|
+
name: profile.name,
|
|
29327
|
+
path: profile.path,
|
|
29328
|
+
active: profile.name.toLowerCase() === active?.toLowerCase()
|
|
29329
|
+
}))
|
|
29330
|
+
};
|
|
29331
|
+
if (request.json === true)
|
|
29332
|
+
return jsonResult(result);
|
|
29333
|
+
if (profiles.length === 0) {
|
|
29334
|
+
return textResult3(`No .env.supacloud.<name> profiles found in ${root}.
|
|
29335
|
+
Run \`supacloud init\` to create safe examples.`);
|
|
29336
|
+
}
|
|
29337
|
+
return textResult3([
|
|
29338
|
+
`Environment profiles in ${root}:`,
|
|
29339
|
+
...result.environments.map((profile) => `${profile.active ? "*" : " "} ${profile.name} ${profile.path}`)
|
|
29340
|
+
].join(`
|
|
29341
|
+
`));
|
|
29342
|
+
}
|
|
29343
|
+
const reports = await Promise.all(profiles.map((profile) => inspectProfile(profile)));
|
|
29344
|
+
const result = {
|
|
29345
|
+
schema: "supacloud.developer-experience.environment-check.v1",
|
|
29346
|
+
ok: reports.length > 0 && reports.every((report) => report.statusReady),
|
|
29347
|
+
root,
|
|
29348
|
+
active: options.activeContext?.environment || null,
|
|
29349
|
+
environments: reports
|
|
29350
|
+
};
|
|
29351
|
+
if (request.json === true)
|
|
29352
|
+
return jsonResult(result, !result.ok);
|
|
29353
|
+
if (reports.length === 0) {
|
|
29354
|
+
return textResult3(`No environment profiles found in ${root}.
|
|
29355
|
+
Run \`supacloud init\` and copy an example profile.`, true);
|
|
29356
|
+
}
|
|
29357
|
+
const lines = reports.map((report) => {
|
|
29358
|
+
if (report.error)
|
|
29359
|
+
return `FAIL ${report.name}: ${report.error}`;
|
|
29360
|
+
const status = report.statusReady ? "OK" : `FAIL missing ${report.statusMissing.join(", ")}`;
|
|
29361
|
+
const deploy = report.deployReady ? "deploy=ready" : `deploy=blocked(${report.deployMissing.join(", ")})`;
|
|
29362
|
+
const ref = report.projectRef ? `project=${report.projectRef}` : "project=unknown";
|
|
29363
|
+
return `${status} ${report.name} ${deploy} ${ref}`;
|
|
29364
|
+
});
|
|
29365
|
+
return textResult3(lines.join(`
|
|
29366
|
+
`), !result.ok);
|
|
29367
|
+
}
|
|
29368
|
+
function registerDeveloperExperienceTools(server, options = {}) {
|
|
29369
|
+
registerTool(server, "init", "Create SupaCloud deployment configuration and non-secret environment examples without overwriting project files.", initToolSchema, (request) => initializeProject(request, options));
|
|
29370
|
+
registerTool(server, "env", "List or locally validate named SupaCloud environment profiles without contacting the platform or printing secrets.", environmentToolSchema, (request) => inspectEnvironment(request, options));
|
|
29371
|
+
}
|
|
28890
29372
|
// package.json
|
|
28891
29373
|
var package_default = {
|
|
28892
29374
|
name: "@supacloud/cli",
|
|
28893
|
-
version: "0.
|
|
29375
|
+
version: "0.90.0",
|
|
28894
29376
|
description: "Project-scoped CLI for SupaCloud users",
|
|
28895
29377
|
type: "module",
|
|
28896
29378
|
main: "./dist/index.js",
|
|
@@ -28942,14 +29424,14 @@ var package_default = {
|
|
|
28942
29424
|
directory: "packages/cli"
|
|
28943
29425
|
},
|
|
28944
29426
|
dependencies: {
|
|
28945
|
-
"@supacloud/compiler": "^0.44.
|
|
28946
|
-
"@supacloud/delivery": "0.
|
|
28947
|
-
"@supacloud/db": "0.16.
|
|
28948
|
-
typebox: "1.3.
|
|
29427
|
+
"@supacloud/compiler": "^0.44.1",
|
|
29428
|
+
"@supacloud/delivery": "0.15.0",
|
|
29429
|
+
"@supacloud/db": "0.16.1",
|
|
29430
|
+
typebox: "1.3.36"
|
|
28949
29431
|
},
|
|
28950
29432
|
overrides: {
|
|
28951
|
-
"@supacloud/contracts": "0.8.
|
|
28952
|
-
"@supacloud/delivery": "0.
|
|
29433
|
+
"@supacloud/contracts": "0.8.1",
|
|
29434
|
+
"@supacloud/delivery": "0.15.0",
|
|
28953
29435
|
"@graphql-tools/utils": "^12.0.3"
|
|
28954
29436
|
},
|
|
28955
29437
|
devDependencies: {
|
|
@@ -29125,6 +29607,8 @@ USAGE
|
|
|
29125
29607
|
|
|
29126
29608
|
${preferredCommand} [global flags] deploy [--flags]
|
|
29127
29609
|
${preferredCommand} [global flags] <module> <action> [--flags]
|
|
29610
|
+
${preferredCommand} init [--root <directory>]
|
|
29611
|
+
${preferredCommand} env <list|check> [--root <directory>]
|
|
29128
29612
|
${preferredCommand} [global flags] status
|
|
29129
29613
|
${preferredCommand} --help
|
|
29130
29614
|
${preferredCommand} --version
|
|
@@ -29157,6 +29641,9 @@ DEFAULT CONTEXT
|
|
|
29157
29641
|
|
|
29158
29642
|
EXAMPLES
|
|
29159
29643
|
|
|
29644
|
+
${preferredCommand} init
|
|
29645
|
+
${preferredCommand} env check
|
|
29646
|
+
${preferredCommand} env check --json
|
|
29160
29647
|
${preferredCommand} status
|
|
29161
29648
|
${preferredCommand} deploy
|
|
29162
29649
|
${preferredCommand} --env test deploy
|
|
@@ -29178,8 +29665,8 @@ EXAMPLES
|
|
|
29178
29665
|
${preferredCommand} release postgrest_restart --ref abc123
|
|
29179
29666
|
${preferredCommand} release release_canary_fixture_stage_replay --ref abc123 --subject <uuid> --request_id <uuid>
|
|
29180
29667
|
${preferredCommand} release release_canary_fixture_disable_replay --ref abc123 --fixture_id <uuid> --disable_request_id <uuid> --issuer <issuer-url> --subject <uuid>
|
|
29181
|
-
${preferredCommand} release scope_rebind --file supacloud/fa/release-scopes/20260907-intake-p1-production.json
|
|
29182
|
-
${preferredCommand} release scope_inspect --file supacloud/fa/release-scopes/20260907-intake-p1-production.json
|
|
29668
|
+
${preferredCommand} release scope_rebind --file supacloud/fa/release-scopes/20260907-intake-p1-production.json --environment_id production
|
|
29669
|
+
${preferredCommand} release scope_inspect --file supacloud/fa/release-scopes/20260907-intake-p1-production.json --environment_id production
|
|
29183
29670
|
${preferredCommand} queue stats --queue emails
|
|
29184
29671
|
${preferredCommand} queue dlq --queue emails --limit 20
|
|
29185
29672
|
${preferredCommand} frontend list --ref abc123
|
|
@@ -29316,6 +29803,10 @@ function createCliTools(context, confirmProduction) {
|
|
|
29316
29803
|
})));
|
|
29317
29804
|
Object.assign(tools, captureTools((server) => registerLiteCliTools(server)));
|
|
29318
29805
|
Object.assign(tools, captureTools((server) => registerAiTools(server)));
|
|
29806
|
+
Object.assign(tools, captureTools((server) => registerDeveloperExperienceTools(server, {
|
|
29807
|
+
cwd: process.cwd(),
|
|
29808
|
+
activeContext: context
|
|
29809
|
+
})));
|
|
29319
29810
|
Object.assign(tools, captureTools((server) => registerAppTools(server, { onDevProgress: writeDevProgress })));
|
|
29320
29811
|
Object.assign(tools, captureTools((server) => registerAppAliases(server)));
|
|
29321
29812
|
Object.assign(tools, captureTools((server) => registerDbGovernanceTools(server, {
|
|
@@ -29550,7 +30041,7 @@ async function main() {
|
|
|
29550
30041
|
return;
|
|
29551
30042
|
}
|
|
29552
30043
|
const cliTools = createCliTools(context, globalOptions.confirmProduction);
|
|
29553
|
-
if (args.length === 1 && !["ai", "supabase", "lite", "app", "db"].includes(args[0]) && cliTools[args[0]]) {
|
|
30044
|
+
if (args.length === 1 && !["ai", "supabase", "lite", "app", "db", "env"].includes(args[0]) && cliTools[args[0]]) {
|
|
29554
30045
|
if ("action" in cliTools[args[0]].schema) {
|
|
29555
30046
|
if (context.credentialScope !== "management" || !context.apiUrl || !context.apiToken) {
|
|
29556
30047
|
console.error(`This command requires Management API context. Run \`${preferredCommand} status\` to inspect current detection.`);
|