@supacloud/cli 0.85.0 → 0.87.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 +193 -151
- package/dist/index.js +305 -103
- package/dist/shared/context.d.ts +6 -0
- package/dist/shared/tools/ai-tools.d.ts +1 -1
- package/dist/shared/tools/application-schemas.d.ts +34 -0
- package/dist/shared/tools/application-tools.d.ts +2 -1
- package/dist/shared/tools/deploy-tools.d.ts +15 -1
- package/package.json +5 -5
- package/skills/{supacloud-cli → supacloud}/SKILL.md +17 -17
- package/skills/supacloud/agents/openai.yaml +4 -0
- package/skills/{supacloud-cli → supacloud}/references/command-map.md +7 -7
- package/skills/{supacloud-cli → supacloud}/references/database-workflow.md +7 -7
- package/skills/supacloud-cli/agents/openai.yaml +0 -4
package/dist/index.js
CHANGED
|
@@ -8753,9 +8753,9 @@ function outcomeUnknownGuidance(text) {
|
|
|
8753
8753
|
const safeScope = typeof ref === "string" && /^[a-z0-9-]{1,20}$/.test(ref) && typeof id === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(id) && typeof environment === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(environment);
|
|
8754
8754
|
let command;
|
|
8755
8755
|
if (safeScope && (data.operation === "applications.promote_application" || data.operation === "applications.reconcile_promotion") && typeof data.mutation_id === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(data.mutation_id)) {
|
|
8756
|
-
command = `supacloud
|
|
8756
|
+
command = `supacloud app promote-status --ref ${ref} --id ${id} --environment_id ${environment} --mutation_id ${data.mutation_id}`;
|
|
8757
8757
|
} else if (safeScope && (data.operation === "applications.create_preview" || data.operation === "applications.cleanup_preview")) {
|
|
8758
|
-
command = `supacloud
|
|
8758
|
+
command = `supacloud app preview-list --ref ${ref} --id ${id} --environment_id ${environment}`;
|
|
8759
8759
|
}
|
|
8760
8760
|
return "OUTCOME_UNKNOWN:操作结果无法确认,服务端可能已经完成操作,但客户端未收到可验证的最终结果。" + "请先查询当前状态或操作回执,再决定是否重试;不要直接重复提交。" + (command ? `
|
|
8761
8761
|
保持原 --env/--env-file 选择,先查询:${command}` : "");
|
|
@@ -8978,7 +8978,12 @@ var CORE_CONTEXT_KEYS = [
|
|
|
8978
8978
|
"SUPACLOUD_API_TOKEN",
|
|
8979
8979
|
"SUPACLOUD_PROJECT_REF",
|
|
8980
8980
|
"X_PROJECT_REF",
|
|
8981
|
-
"SUPACLOUD_HOST"
|
|
8981
|
+
"SUPACLOUD_HOST",
|
|
8982
|
+
"SUPACLOUD_APPLICATION_ID",
|
|
8983
|
+
"SUPACLOUD_APPLICATION_ENVIRONMENT_ID",
|
|
8984
|
+
"SUPACLOUD_APPLICATION_CONFIGURATION_PATH",
|
|
8985
|
+
"SUPACLOUD_APPLICATION_CONFIGURATION_ID",
|
|
8986
|
+
"SUPACLOUD_APPLICATION_MANIFEST_PATH"
|
|
8982
8987
|
];
|
|
8983
8988
|
function unquotedEnvValue(rawValue) {
|
|
8984
8989
|
const value = rawValue.trim();
|
|
@@ -9144,6 +9149,12 @@ function resolveSupaCloudContext(env = process.env, cwd = process.cwd(), selecti
|
|
|
9144
9149
|
credentialScope: core.credentialScope,
|
|
9145
9150
|
source: source.kind,
|
|
9146
9151
|
sourcePath: source.path,
|
|
9152
|
+
environmentVariables: source.values,
|
|
9153
|
+
applicationId: source.values.SUPACLOUD_APPLICATION_ID?.trim() || "",
|
|
9154
|
+
applicationEnvironmentId: source.values.SUPACLOUD_APPLICATION_ENVIRONMENT_ID?.trim() || source.environment,
|
|
9155
|
+
applicationConfigurationPath: source.values.SUPACLOUD_APPLICATION_CONFIGURATION_PATH?.trim() || "",
|
|
9156
|
+
applicationConfigurationId: source.values.SUPACLOUD_APPLICATION_CONFIGURATION_ID?.trim() || "",
|
|
9157
|
+
applicationManifestPath: source.values.SUPACLOUD_APPLICATION_MANIFEST_PATH?.trim() || "",
|
|
9147
9158
|
insecureTls
|
|
9148
9159
|
};
|
|
9149
9160
|
}
|
|
@@ -9153,7 +9164,7 @@ var ACTION_POLICY = {
|
|
|
9153
9164
|
deploy: { write: ["deploy"] },
|
|
9154
9165
|
applications: {
|
|
9155
9166
|
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"],
|
|
9156
|
-
write: ["upload_release", "put_configuration", "transfer_release", "promote_application", "reconcile_promotion", "create_preview", "reconcile_preview", "cleanup_preview", "activate_release", "deploy_release", "rollback_release", "reconcile_activation", "retire_activation"]
|
|
9167
|
+
write: ["upload_release", "put_configuration", "release_application", "transfer_release", "promote_application", "reconcile_promotion", "create_preview", "reconcile_preview", "cleanup_preview", "activate_release", "deploy_release", "rollback_release", "reconcile_activation", "retire_activation"]
|
|
9157
9168
|
},
|
|
9158
9169
|
project: {
|
|
9159
9170
|
read: ["get", "endpoints", "health", "logs", "api_keys", "settings", "tasks", "task_detail", "task_stats", "dlq", "background_settings"],
|
|
@@ -10477,6 +10488,37 @@ function parseApplicationDeployPlan(value) {
|
|
|
10477
10488
|
throw new Error("Invalid application deploy plan action");
|
|
10478
10489
|
return value;
|
|
10479
10490
|
}
|
|
10491
|
+
// node_modules/@supacloud/delivery/src/application-release-operation.ts
|
|
10492
|
+
var closed3 = { additionalProperties: false };
|
|
10493
|
+
var nullableActivation = Union([ApplicationActivationIdSchema, Null()]);
|
|
10494
|
+
var ApplicationReleaseRequestSchema = _Object_({
|
|
10495
|
+
release_id: ApplicationReleaseIdSchema,
|
|
10496
|
+
configuration_id: Optional(ApplicationConfigurationIdSchema),
|
|
10497
|
+
configuration_write: Optional(ApplicationConfigurationWriteSchema),
|
|
10498
|
+
activation_id: Optional(ApplicationActivationIdSchema),
|
|
10499
|
+
expected_activation_id: Optional(nullableActivation),
|
|
10500
|
+
expected_plan_sha256: Optional(ApplicationReleaseIdSchema)
|
|
10501
|
+
}, closed3);
|
|
10502
|
+
var ApplicationReleaseResultSchema = _Object_({
|
|
10503
|
+
schema: Literal("supacloud.application-release.v1"),
|
|
10504
|
+
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
10505
|
+
application_id: ApplicationIdSchema,
|
|
10506
|
+
environment_id: ApplicationIdSchema,
|
|
10507
|
+
release_id: ApplicationReleaseIdSchema,
|
|
10508
|
+
configuration_id: ApplicationConfigurationIdSchema,
|
|
10509
|
+
activation_id: ApplicationActivationIdSchema,
|
|
10510
|
+
expected_activation_id: nullableActivation,
|
|
10511
|
+
plan_sha256: ApplicationReleaseIdSchema,
|
|
10512
|
+
action: Union([Literal("activate"), Literal("no-op")]),
|
|
10513
|
+
replayed: Boolean2(),
|
|
10514
|
+
execution_performed: Boolean2()
|
|
10515
|
+
}, closed3);
|
|
10516
|
+
function parseApplicationReleaseResult(value) {
|
|
10517
|
+
if (!Check2(ApplicationReleaseResultSchema, value)) {
|
|
10518
|
+
throw new Error("Invalid application release result");
|
|
10519
|
+
}
|
|
10520
|
+
return structuredClone(value);
|
|
10521
|
+
}
|
|
10480
10522
|
// node_modules/@supacloud/delivery/src/application-history.ts
|
|
10481
10523
|
var scope = {
|
|
10482
10524
|
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
@@ -10561,7 +10603,7 @@ var phaseStatus = Union([
|
|
|
10561
10603
|
Literal("failed"),
|
|
10562
10604
|
Literal("cleaned")
|
|
10563
10605
|
]);
|
|
10564
|
-
var
|
|
10606
|
+
var closed4 = { additionalProperties: false };
|
|
10565
10607
|
var ApplicationPreviewReceiptSchema = _Object_({
|
|
10566
10608
|
schema: Literal("supacloud.application-preview.v1"),
|
|
10567
10609
|
preview_id: String2({ pattern: "^[a-f0-9-]{8,64}$" }),
|
|
@@ -10581,46 +10623,46 @@ var ApplicationPreviewReceiptSchema = _Object_({
|
|
|
10581
10623
|
Literal("cleaned")
|
|
10582
10624
|
]),
|
|
10583
10625
|
resources: _Object_({
|
|
10584
|
-
build_artifact: _Object_({ status: phaseStatus, release_id: ApplicationReleaseIdSchema },
|
|
10626
|
+
build_artifact: _Object_({ status: phaseStatus, release_id: ApplicationReleaseIdSchema }, closed4),
|
|
10585
10627
|
database_branch: _Object_({
|
|
10586
10628
|
status: phaseStatus,
|
|
10587
10629
|
branch_ref: String2({ pattern: "^[A-Za-z0-9_-]{1,20}$" }),
|
|
10588
10630
|
data_mode: Union([Literal("schema_only"), Literal("full_clone")])
|
|
10589
|
-
},
|
|
10631
|
+
}, closed4),
|
|
10590
10632
|
queue_namespace: _Object_({
|
|
10591
10633
|
status: phaseStatus,
|
|
10592
10634
|
namespace: String2({ minLength: 1, maxLength: 128 })
|
|
10593
|
-
},
|
|
10635
|
+
}, closed4),
|
|
10594
10636
|
storage_namespace: _Object_({
|
|
10595
10637
|
status: phaseStatus,
|
|
10596
10638
|
namespace: String2({ minLength: 1, maxLength: 128 })
|
|
10597
|
-
},
|
|
10639
|
+
}, closed4),
|
|
10598
10640
|
test_secret: _Object_({
|
|
10599
10641
|
status: phaseStatus,
|
|
10600
10642
|
name: String2({ minLength: 1, maxLength: 128 }),
|
|
10601
10643
|
value_issued: Literal(false)
|
|
10602
|
-
},
|
|
10644
|
+
}, closed4),
|
|
10603
10645
|
configuration_revision: _Object_({
|
|
10604
10646
|
status: phaseStatus,
|
|
10605
10647
|
configuration_id: Union([ApplicationConfigurationIdSchema, Null()])
|
|
10606
|
-
},
|
|
10648
|
+
}, closed4),
|
|
10607
10649
|
application_activation: _Object_({
|
|
10608
10650
|
status: phaseStatus,
|
|
10609
10651
|
activation_id: Union([ApplicationActivationIdSchema, Null()])
|
|
10610
|
-
},
|
|
10652
|
+
}, closed4),
|
|
10611
10653
|
smoke_test: _Object_({
|
|
10612
10654
|
status: phaseStatus,
|
|
10613
10655
|
checks: _Array_(String2({ minLength: 1, maxLength: 64 }), { maxItems: 32 }),
|
|
10614
10656
|
passed: _Array_(String2({ minLength: 1, maxLength: 64 }), { maxItems: 32 }),
|
|
10615
10657
|
failed: _Array_(String2({ minLength: 1, maxLength: 64 }), { maxItems: 32 })
|
|
10616
|
-
},
|
|
10617
|
-
},
|
|
10658
|
+
}, closed4)
|
|
10659
|
+
}, closed4),
|
|
10618
10660
|
cleanup: _Object_({
|
|
10619
10661
|
required: Boolean2(),
|
|
10620
10662
|
completed: Boolean2(),
|
|
10621
10663
|
error: Union([String2({ minLength: 1, maxLength: 128 }), Null()])
|
|
10622
|
-
},
|
|
10623
|
-
},
|
|
10664
|
+
}, closed4)
|
|
10665
|
+
}, closed4);
|
|
10624
10666
|
function applicationPreviewBranchRef(previewId) {
|
|
10625
10667
|
if (!/^[a-f0-9-]{8,64}$/.test(previewId))
|
|
10626
10668
|
throw new Error("Invalid preview ID");
|
|
@@ -10673,7 +10715,7 @@ function parseApplicationReleaseTransferResult(candidate) {
|
|
|
10673
10715
|
return candidate;
|
|
10674
10716
|
}
|
|
10675
10717
|
// node_modules/@supacloud/delivery/src/deployment-evidence.ts
|
|
10676
|
-
var
|
|
10718
|
+
var closed5 = { additionalProperties: false };
|
|
10677
10719
|
var sha256 = String2({ pattern: "^[a-f0-9]{64}$" });
|
|
10678
10720
|
var isoDate = String2({ minLength: 20, maxLength: 40 });
|
|
10679
10721
|
var status = Union([
|
|
@@ -10700,19 +10742,19 @@ var DatabaseProviderSchema = _Object_({
|
|
|
10700
10742
|
Literal("not-proven"),
|
|
10701
10743
|
Literal("failed")
|
|
10702
10744
|
])
|
|
10703
|
-
},
|
|
10745
|
+
}, closed5),
|
|
10704
10746
|
backup: _Object_({
|
|
10705
10747
|
status,
|
|
10706
10748
|
latest_success_at: Union([isoDate, Null()]),
|
|
10707
10749
|
freshness_seconds: Union([Integer({ minimum: 0 }), Null()])
|
|
10708
|
-
},
|
|
10750
|
+
}, closed5),
|
|
10709
10751
|
recovery: _Object_({
|
|
10710
10752
|
status,
|
|
10711
10753
|
drill_id: Union([String2({ minLength: 1, maxLength: 128 }), Null()]),
|
|
10712
10754
|
rpo_seconds: Union([Integer({ minimum: 0 }), Null()]),
|
|
10713
10755
|
rto_seconds: Union([Integer({ minimum: 0 }), Null()])
|
|
10714
|
-
},
|
|
10715
|
-
},
|
|
10756
|
+
}, closed5)
|
|
10757
|
+
}, closed5);
|
|
10716
10758
|
var componentName = Union([
|
|
10717
10759
|
Literal("management-api"),
|
|
10718
10760
|
Literal("web-console"),
|
|
@@ -10730,7 +10772,7 @@ var DeploymentComponentEvidenceSchema = _Object_({
|
|
|
10730
10772
|
status,
|
|
10731
10773
|
health_check: Union([String2({ minLength: 1, maxLength: 256 }), Null()]),
|
|
10732
10774
|
checked_at: Union([isoDate, Null()])
|
|
10733
|
-
},
|
|
10775
|
+
}, closed5);
|
|
10734
10776
|
var DeploymentEvidenceSchema = _Object_({
|
|
10735
10777
|
schema: Literal(DEPLOYMENT_EVIDENCE_SCHEMA),
|
|
10736
10778
|
status: evidenceStatus,
|
|
@@ -10739,33 +10781,33 @@ var DeploymentEvidenceSchema = _Object_({
|
|
|
10739
10781
|
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
10740
10782
|
application_id: ApplicationIdSchema,
|
|
10741
10783
|
environment_id: ApplicationIdSchema
|
|
10742
|
-
},
|
|
10784
|
+
}, closed5),
|
|
10743
10785
|
source: _Object_({
|
|
10744
10786
|
commit_sha: Union([String2({ pattern: "^[0-9a-f]{7,64}$" }), Null()]),
|
|
10745
10787
|
manifest_sha256: sha256,
|
|
10746
10788
|
contract_schema: Union([String2({ minLength: 1, maxLength: 128 }), Null()]),
|
|
10747
10789
|
environment_binding_version: Union([sha256, Null()])
|
|
10748
|
-
},
|
|
10790
|
+
}, closed5),
|
|
10749
10791
|
database: DatabaseProviderSchema,
|
|
10750
10792
|
components: _Array_(DeploymentComponentEvidenceSchema, { minItems: 1, maxItems: 32 }),
|
|
10751
10793
|
activation: _Object_({
|
|
10752
10794
|
release_id: ApplicationReleaseIdSchema,
|
|
10753
10795
|
configuration_id: ApplicationConfigurationIdSchema,
|
|
10754
10796
|
activation_id: ApplicationConfigurationIdSchema
|
|
10755
|
-
},
|
|
10797
|
+
}, closed5),
|
|
10756
10798
|
health: _Object_({
|
|
10757
10799
|
status,
|
|
10758
10800
|
checked_at: Union([isoDate, Null()]),
|
|
10759
10801
|
authenticated_smoke: status
|
|
10760
|
-
},
|
|
10802
|
+
}, closed5),
|
|
10761
10803
|
rollback: _Object_({
|
|
10762
10804
|
release_id: Union([ApplicationReleaseIdSchema, Null()]),
|
|
10763
10805
|
configuration_id: Union([ApplicationConfigurationIdSchema, Null()]),
|
|
10764
10806
|
status: Union([Literal("ready"), Literal("not-ready"), Literal("unknown")]),
|
|
10765
10807
|
result: Union([status, Null()])
|
|
10766
|
-
},
|
|
10808
|
+
}, closed5),
|
|
10767
10809
|
notes: _Array_(String2({ minLength: 1, maxLength: 512 }), { maxItems: 32 })
|
|
10768
|
-
},
|
|
10810
|
+
}, closed5);
|
|
10769
10811
|
function isIsoDate(value) {
|
|
10770
10812
|
return Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value;
|
|
10771
10813
|
}
|
|
@@ -10798,13 +10840,13 @@ function parseDeploymentEvidence(value) {
|
|
|
10798
10840
|
return structuredClone(value);
|
|
10799
10841
|
}
|
|
10800
10842
|
// node_modules/@supacloud/delivery/src/application-promotion.ts
|
|
10801
|
-
var
|
|
10843
|
+
var closed6 = { additionalProperties: false };
|
|
10802
10844
|
var projectRef2 = String2({ pattern: "^[a-z0-9-]{1,20}$" });
|
|
10803
10845
|
var sha2562 = ApplicationReleaseIdSchema;
|
|
10804
|
-
var
|
|
10846
|
+
var nullableActivation2 = Union([ApplicationActivationIdSchema, Null()]);
|
|
10805
10847
|
var nullableDigest = Union([sha2562, Null()]);
|
|
10806
10848
|
var observation = {
|
|
10807
|
-
activation_id:
|
|
10849
|
+
activation_id: nullableActivation2,
|
|
10808
10850
|
receipt_confirmed: Boolean2(),
|
|
10809
10851
|
ready: Boolean2(),
|
|
10810
10852
|
smoke_verified: Boolean2(),
|
|
@@ -10835,7 +10877,7 @@ var ApplicationPromotionPlanSchema = _Object_({
|
|
|
10835
10877
|
environment_id: ApplicationIdSchema,
|
|
10836
10878
|
release_id: sha2562,
|
|
10837
10879
|
...observation
|
|
10838
|
-
},
|
|
10880
|
+
}, closed6),
|
|
10839
10881
|
target: _Object_({
|
|
10840
10882
|
candidate_release_id: sha2562,
|
|
10841
10883
|
current_release_id: Union([sha2562, Null()]),
|
|
@@ -10843,18 +10885,18 @@ var ApplicationPromotionPlanSchema = _Object_({
|
|
|
10843
10885
|
configuration_id: Union([ApplicationConfigurationIdSchema, Null()]),
|
|
10844
10886
|
configuration: Union([ApplicationConfigurationViewSchema, Null()]),
|
|
10845
10887
|
...observation
|
|
10846
|
-
},
|
|
10888
|
+
}, closed6),
|
|
10847
10889
|
migrations: _Object_({
|
|
10848
10890
|
ledger_digest: sha2562,
|
|
10849
10891
|
ledger_compatible: Boolean2(),
|
|
10850
10892
|
project_migrations_applied: Boolean2(),
|
|
10851
10893
|
pending_versions: _Array_(String2({ pattern: "^\\d{1,20}$" }), { maxItems: 4096, uniqueItems: true }),
|
|
10852
10894
|
operator_provisioning_required: Boolean2()
|
|
10853
|
-
},
|
|
10895
|
+
}, closed6),
|
|
10854
10896
|
backup: _Object_({
|
|
10855
10897
|
required: Boolean2(),
|
|
10856
10898
|
confirmed: Literal(false)
|
|
10857
|
-
},
|
|
10899
|
+
}, closed6),
|
|
10858
10900
|
action: Union([Literal("promote"), Literal("no-op"), Literal("blocked")]),
|
|
10859
10901
|
blockers: _Array_(Enum([...blocker]), {
|
|
10860
10902
|
maxItems: blocker.length,
|
|
@@ -10863,7 +10905,7 @@ var ApplicationPromotionPlanSchema = _Object_({
|
|
|
10863
10905
|
steps: _Array_(String2({ minLength: 1, maxLength: 64 }), { maxItems: 8, uniqueItems: true }),
|
|
10864
10906
|
execution_performed: Literal(false),
|
|
10865
10907
|
data_recovery: Literal("separate-required")
|
|
10866
|
-
},
|
|
10908
|
+
}, closed6);
|
|
10867
10909
|
function applicationPromotionPlanDigest(value) {
|
|
10868
10910
|
return digest(canonical(value));
|
|
10869
10911
|
}
|
|
@@ -15832,7 +15874,7 @@ Actions: list, upsert, delete`, {
|
|
|
15832
15874
|
action: withDescription(stringEnum(["list", "upsert", "delete"]), "Action"),
|
|
15833
15875
|
ref: withDescription(String2(), "Project ref"),
|
|
15834
15876
|
secrets: withDescription(secretsSchema, "[upsert] Secret list as JSON array or KEY=VALUE,KEY2=VALUE2"),
|
|
15835
|
-
"from-env": withDescription(environmentSecretNamesSchema, "[upsert] Comma-separated environment variable names; values are read from
|
|
15877
|
+
"from-env": withDescription(environmentSecretNamesSchema, "[upsert] Comma-separated environment variable names; values are read from the selected CLI environment"),
|
|
15836
15878
|
name: optional(String2(), "[delete] Secret name to delete")
|
|
15837
15879
|
}, async (args) => {
|
|
15838
15880
|
const { action, ref, secrets, name } = args;
|
|
@@ -16810,6 +16852,7 @@ var ApplicationActivationRetirementResultSchema2 = ApplicationActivationRetireme
|
|
|
16810
16852
|
var ApplicationRollbackSnapshotSchema2 = ApplicationRollbackSnapshotSchema;
|
|
16811
16853
|
var ApplicationActivationHistoryCursorSchema2 = ApplicationActivationHistoryCursorSchema;
|
|
16812
16854
|
var ApplicationPromotionPlanSchema2 = ApplicationPromotionPlanSchema;
|
|
16855
|
+
var ApplicationReleaseRequestSchema2 = ApplicationReleaseRequestSchema;
|
|
16813
16856
|
|
|
16814
16857
|
// src/shared/mutation-protocol.ts
|
|
16815
16858
|
import { createHash as createHash6 } from "node:crypto";
|
|
@@ -17049,7 +17092,7 @@ async function fetchMutationStatus(http, ref, mutationId) {
|
|
|
17049
17092
|
}
|
|
17050
17093
|
|
|
17051
17094
|
// src/shared/tools/application-workflow-schemas.ts
|
|
17052
|
-
var
|
|
17095
|
+
var closed7 = { additionalProperties: false };
|
|
17053
17096
|
var ref5 = String2({ pattern: "^[A-Za-z0-9_-]{1,20}$" });
|
|
17054
17097
|
var uuid = ApplicationActivationIdSchema2;
|
|
17055
17098
|
var nullableUuid = Union([uuid, Null()]);
|
|
@@ -17063,7 +17106,7 @@ var ApplicationPromotionResultSchema = _Object_({
|
|
|
17063
17106
|
plan_sha256: ApplicationReleaseIdSchema2,
|
|
17064
17107
|
action: Literal("promote"),
|
|
17065
17108
|
replayed: Boolean2()
|
|
17066
|
-
},
|
|
17109
|
+
}, closed7);
|
|
17067
17110
|
var ApplicationPromotionStatusSchema = _Object_({
|
|
17068
17111
|
...scope2,
|
|
17069
17112
|
mutation: Unknown(),
|
|
@@ -17082,8 +17125,8 @@ var ApplicationPromotionStatusSchema = _Object_({
|
|
|
17082
17125
|
configuration_id: Union([ApplicationConfigurationIdSchema2, Null()]),
|
|
17083
17126
|
backup_id: Union([String2({ pattern: "^logical-full_[a-z0-9-]{1,20}_[a-f0-9]{32}$" }), Null()]),
|
|
17084
17127
|
data_recovery: Literal("separate-required")
|
|
17085
|
-
},
|
|
17086
|
-
},
|
|
17128
|
+
}, closed7)
|
|
17129
|
+
}, closed7);
|
|
17087
17130
|
var phase = Union([Literal("pending"), Literal("ready"), Literal("failed"), Literal("cleaned")]);
|
|
17088
17131
|
var previewId = String2({ pattern: "^[a-f0-9-]{8,64}$" });
|
|
17089
17132
|
var name = String2({ minLength: 1, maxLength: 256 });
|
|
@@ -17102,35 +17145,35 @@ var ApplicationPreviewReceiptSchema2 = _Object_({
|
|
|
17102
17145
|
Literal("cleaned")
|
|
17103
17146
|
]),
|
|
17104
17147
|
resources: _Object_({
|
|
17105
|
-
build_artifact: _Object_({ status: phase, release_id: ApplicationReleaseIdSchema2 },
|
|
17148
|
+
build_artifact: _Object_({ status: phase, release_id: ApplicationReleaseIdSchema2 }, closed7),
|
|
17106
17149
|
database_branch: _Object_({
|
|
17107
17150
|
status: phase,
|
|
17108
17151
|
branch_ref: ref5,
|
|
17109
17152
|
data_mode: Union([Literal("schema_only"), Literal("full_clone")])
|
|
17110
|
-
},
|
|
17111
|
-
queue_namespace: _Object_({ status: phase, namespace: name },
|
|
17112
|
-
storage_namespace: _Object_({ status: phase, namespace: name },
|
|
17113
|
-
test_secret: _Object_({ status: phase, name, value_issued: Literal(false) },
|
|
17114
|
-
configuration_revision: _Object_({ status: phase, configuration_id: Union([ApplicationConfigurationIdSchema2, Null()]) },
|
|
17115
|
-
application_activation: _Object_({ status: phase, activation_id: nullableUuid },
|
|
17116
|
-
smoke_test: _Object_({ status: phase, checks, passed: checks, failed: checks },
|
|
17117
|
-
},
|
|
17153
|
+
}, closed7),
|
|
17154
|
+
queue_namespace: _Object_({ status: phase, namespace: name }, closed7),
|
|
17155
|
+
storage_namespace: _Object_({ status: phase, namespace: name }, closed7),
|
|
17156
|
+
test_secret: _Object_({ status: phase, name, value_issued: Literal(false) }, closed7),
|
|
17157
|
+
configuration_revision: _Object_({ status: phase, configuration_id: Union([ApplicationConfigurationIdSchema2, Null()]) }, closed7),
|
|
17158
|
+
application_activation: _Object_({ status: phase, activation_id: nullableUuid }, closed7),
|
|
17159
|
+
smoke_test: _Object_({ status: phase, checks, passed: checks, failed: checks }, closed7)
|
|
17160
|
+
}, closed7),
|
|
17118
17161
|
cleanup: _Object_({
|
|
17119
17162
|
required: Boolean2(),
|
|
17120
17163
|
completed: Boolean2(),
|
|
17121
17164
|
error: Union([String2({ pattern: "^[A-Z][A-Z0-9_]{0,63}$" }), Null()])
|
|
17122
|
-
},
|
|
17165
|
+
}, closed7),
|
|
17123
17166
|
branch_name: Optional(String2({ minLength: 1, maxLength: 80 })),
|
|
17124
17167
|
queue_name: Optional(name),
|
|
17125
17168
|
test_secret_name: Optional(name),
|
|
17126
17169
|
source_configuration_id: Optional(Union([ApplicationConfigurationIdSchema2, Null()])),
|
|
17127
17170
|
created_at: Optional(timestamp2),
|
|
17128
17171
|
updated_at: Optional(timestamp2)
|
|
17129
|
-
},
|
|
17172
|
+
}, closed7);
|
|
17130
17173
|
var previewListSchema = _Object_({
|
|
17131
17174
|
...scope2,
|
|
17132
17175
|
previews: _Array_(ApplicationPreviewReceiptSchema2, { maxItems: 1000 })
|
|
17133
|
-
},
|
|
17176
|
+
}, closed7);
|
|
17134
17177
|
function assertScope(value, identity) {
|
|
17135
17178
|
if (value.project_ref !== identity.project_ref || value.application_id !== identity.application_id || value.environment_id !== identity.environment_id)
|
|
17136
17179
|
throw new Error("Application workflow scope mismatch");
|
|
@@ -17597,6 +17640,7 @@ var APPLICATION_TOOL_SCHEMA = {
|
|
|
17597
17640
|
"put_configuration",
|
|
17598
17641
|
"get_deploy_plan",
|
|
17599
17642
|
"deploy_release",
|
|
17643
|
+
"release_application",
|
|
17600
17644
|
"get_release_transfer_plan",
|
|
17601
17645
|
"transfer_release",
|
|
17602
17646
|
"get_promotion_plan",
|
|
@@ -17624,6 +17668,7 @@ var APPLICATION_TOOL_SCHEMA = {
|
|
|
17624
17668
|
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"),
|
|
17625
17669
|
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"),
|
|
17626
17670
|
configuration_path: optional(String2(), "[put_configuration] Local configuration write JSON including revision and expected revision"),
|
|
17671
|
+
configuration_write: optional(Unknown(), "[release_application] Parsed immutable configuration write"),
|
|
17627
17672
|
manifest_path: optional(String2(), "[upload_release] Local delivery.manifest.json"),
|
|
17628
17673
|
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"),
|
|
17629
17674
|
source_ref: optional(String2({ pattern: "^[A-Za-z0-9_-]{1,20}$" }), "[get_release_transfer_plan/transfer_release] Source project ref"),
|
|
@@ -17983,6 +18028,61 @@ function registerApplicationTools(server, http) {
|
|
|
17983
18028
|
const observed = await readDeployPlan(http, args, project);
|
|
17984
18029
|
return observed.failure ?? releaseControlSuccess(operation, { ...observed.identity, plan: observed.plan });
|
|
17985
18030
|
}
|
|
18031
|
+
if (action === "release_application") {
|
|
18032
|
+
const environmentId = text(args, "environment_id");
|
|
18033
|
+
const releaseId = text(args, "release_id");
|
|
18034
|
+
if (!Check2(ApplicationIdSchema2, environmentId) || !Check2(ApplicationReleaseIdSchema2, releaseId)) {
|
|
18035
|
+
throw new Error("Invalid application release identity");
|
|
18036
|
+
}
|
|
18037
|
+
const configurationId = args["configuration_id"];
|
|
18038
|
+
const activationId = args["activation_id"];
|
|
18039
|
+
const expectedActivationId = args["expected_activation_id"];
|
|
18040
|
+
if (configurationId !== undefined && !Check2(ApplicationConfigurationIdSchema2, configurationId)) {
|
|
18041
|
+
throw new Error("Invalid application configuration ID");
|
|
18042
|
+
}
|
|
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
|
+
const configurationWrite = args["configuration_write"];
|
|
18050
|
+
const parsedConfigurationWrite = configurationWrite === undefined ? undefined : parseApplicationConfigurationWrite(configurationWrite);
|
|
18051
|
+
const requestedConfigurationId = configurationId ?? parsedConfigurationWrite?.configuration_id;
|
|
18052
|
+
const body = {
|
|
18053
|
+
release_id: releaseId,
|
|
18054
|
+
...configurationId === undefined ? {} : { configuration_id: configurationId },
|
|
18055
|
+
...configurationWrite === undefined ? {} : { configuration_write: configurationWrite },
|
|
18056
|
+
...activationId === undefined ? {} : { activation_id: activationId },
|
|
18057
|
+
...expectedActivationId === undefined ? {} : {
|
|
18058
|
+
expected_activation_id: expectedActivationId === "absent" ? null : expectedActivationId
|
|
18059
|
+
}
|
|
18060
|
+
};
|
|
18061
|
+
if (!Check2(ApplicationReleaseRequestSchema2, body)) {
|
|
18062
|
+
throw new Error("Invalid application release request");
|
|
18063
|
+
}
|
|
18064
|
+
const result = await http.post(`/v1/projects/${project}/applications/${encodeURIComponent(id)}/environments/${encodeURIComponent(environmentId)}/release`, body, { timeoutMs: 120000, maxJsonBytes: 65536, responseTimeoutMs: 30000 });
|
|
18065
|
+
const identity = {
|
|
18066
|
+
project_ref: ref,
|
|
18067
|
+
application_id: id,
|
|
18068
|
+
environment_id: environmentId,
|
|
18069
|
+
release_id: releaseId,
|
|
18070
|
+
...configurationId === undefined ? {} : { configuration_id: configurationId },
|
|
18071
|
+
...activationId === undefined ? {} : { activation_id: activationId }
|
|
18072
|
+
};
|
|
18073
|
+
if (!result.ok)
|
|
18074
|
+
return releaseControlMutationFailure(operation, result, identity);
|
|
18075
|
+
try {
|
|
18076
|
+
if (result.status !== 200)
|
|
18077
|
+
throw new Error;
|
|
18078
|
+
const release = parseApplicationReleaseResult(result.data);
|
|
18079
|
+
if (release.project_ref !== ref || release.application_id !== id || release.environment_id !== environmentId || release.release_id !== releaseId || requestedConfigurationId !== undefined && release.configuration_id !== requestedConfigurationId || activationId !== undefined && release.activation_id !== activationId)
|
|
18080
|
+
throw new Error;
|
|
18081
|
+
return releaseControlSuccess(operation, release);
|
|
18082
|
+
} catch {
|
|
18083
|
+
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.status, identity);
|
|
18084
|
+
}
|
|
18085
|
+
}
|
|
17986
18086
|
if (action === "deploy_release")
|
|
17987
18087
|
return deployAction(http, args, project);
|
|
17988
18088
|
if (action === "rollback_release" || action === "get_rollback_snapshot") {
|
|
@@ -20702,7 +20802,7 @@ import {
|
|
|
20702
20802
|
import { homedir as homedir2 } from "node:os";
|
|
20703
20803
|
import { dirname as dirname4, join as join8, relative as relative4, resolve as resolve11, sep as sep3 } from "node:path";
|
|
20704
20804
|
import { fileURLToPath } from "node:url";
|
|
20705
|
-
var SKILL_NAME = "supacloud
|
|
20805
|
+
var SKILL_NAME = "supacloud";
|
|
20706
20806
|
function regularFiles(rootDirectory, currentDirectory = rootDirectory) {
|
|
20707
20807
|
const files = [];
|
|
20708
20808
|
for (const directoryEntry of readdirSync4(currentDirectory, { withFileTypes: true })) {
|
|
@@ -20740,7 +20840,7 @@ function availableBackupDirectory(destinationDirectory, now) {
|
|
|
20740
20840
|
}
|
|
20741
20841
|
function stagedSkill(sourceDirectory, targetRoot) {
|
|
20742
20842
|
mkdirSync3(targetRoot, { recursive: true });
|
|
20743
|
-
const stagingRoot = mkdtempSync2(join8(targetRoot, ".supacloud-
|
|
20843
|
+
const stagingRoot = mkdtempSync2(join8(targetRoot, ".supacloud-install-"));
|
|
20744
20844
|
const stagingSkill = join8(stagingRoot, SKILL_NAME);
|
|
20745
20845
|
try {
|
|
20746
20846
|
cpSync(sourceDirectory, stagingSkill, { recursive: true, errorOnExist: true });
|
|
@@ -21007,16 +21107,16 @@ var starter_metadata_default = {
|
|
|
21007
21107
|
generatedBy: "supacloud/starter-metadata-v1",
|
|
21008
21108
|
packages: {
|
|
21009
21109
|
compiler: {
|
|
21010
|
-
version: "0.
|
|
21110
|
+
version: "0.44.0"
|
|
21011
21111
|
},
|
|
21012
21112
|
app: {
|
|
21013
|
-
version: "0.
|
|
21113
|
+
version: "0.26.0",
|
|
21014
21114
|
dependencies: {
|
|
21015
21115
|
rxjs: "7.8.2"
|
|
21016
21116
|
}
|
|
21017
21117
|
},
|
|
21018
21118
|
elysia: {
|
|
21019
|
-
version: "0.29.
|
|
21119
|
+
version: "0.29.1"
|
|
21020
21120
|
},
|
|
21021
21121
|
commands: {
|
|
21022
21122
|
version: "0.9.1"
|
|
@@ -21793,8 +21893,8 @@ The compiler discovers this declaration; no runtime container lookup is needed.
|
|
|
21793
21893
|
With the matching candidate/released CLI installed:
|
|
21794
21894
|
|
|
21795
21895
|
\`\`\`sh
|
|
21796
|
-
supacloud
|
|
21797
|
-
supacloud
|
|
21896
|
+
supacloud app generate --kind resource --name inventory --register-in src/app.module.ts --dry-run --format json
|
|
21897
|
+
supacloud app generate --kind resource --name inventory --register-in src/app.module.ts
|
|
21798
21898
|
bun run check
|
|
21799
21899
|
bun run inspect
|
|
21800
21900
|
\`\`\`
|
|
@@ -25449,35 +25549,29 @@ async function runAppRelease(request, options, delegate) {
|
|
|
25449
25549
|
return releasePhaseFailure("upload", releaseControlFailure("applications.upload_release", "INVALID_RESPONSE", null, { project_ref: ref, application_id: id }), completed);
|
|
25450
25550
|
completed.upload = { ok: true, release_id: releaseId };
|
|
25451
25551
|
let configurationId = request.configuration_id;
|
|
25552
|
+
let configurationWrite;
|
|
25553
|
+
const activationId = crypto.randomUUID();
|
|
25452
25554
|
if (request.configuration_path !== undefined) {
|
|
25453
25555
|
const configurationPath = resolve17(root, request.configuration_path);
|
|
25454
|
-
|
|
25455
|
-
|
|
25456
|
-
|
|
25457
|
-
|
|
25458
|
-
environment_id: environmentId,
|
|
25459
|
-
|
|
25460
|
-
};
|
|
25461
|
-
validateToolArguments(APPLICATION_TOOL_SCHEMA, configureArgs);
|
|
25462
|
-
const configured = await delegate(configureArgs);
|
|
25463
|
-
const configurationReceipt = resultObject(configured);
|
|
25464
|
-
if (configured.isError || !configurationReceipt?.ok) {
|
|
25465
|
-
return releasePhaseFailure("configure", configured, completed);
|
|
25466
|
-
}
|
|
25467
|
-
configurationId = releaseField(configurationReceipt, "configuration", "configuration_id");
|
|
25468
|
-
if (!configurationId)
|
|
25469
|
-
return releasePhaseFailure("configure", releaseControlFailure("applications.put_configuration", "INVALID_RESPONSE", null, { project_ref: ref, application_id: id, environment_id: environmentId }), completed);
|
|
25470
|
-
completed.configure = { ok: true, configuration_id: configurationId };
|
|
25556
|
+
try {
|
|
25557
|
+
configurationWrite = parseApplicationConfigurationWrite(await Bun.file(configurationPath).json());
|
|
25558
|
+
configurationId = configurationWrite.configuration_id;
|
|
25559
|
+
} catch {
|
|
25560
|
+
return releasePhaseFailure("configure", releaseControlFailure("applications.release_application", "INVALID_RESPONSE", null, { project_ref: ref, application_id: id, environment_id: environmentId }), completed);
|
|
25561
|
+
}
|
|
25562
|
+
completed.configure = { delegated: true, configuration_id: configurationId };
|
|
25471
25563
|
} else {
|
|
25472
|
-
completed.configure = {
|
|
25564
|
+
completed.configure = { delegated: true, configuration_id: configurationId };
|
|
25473
25565
|
}
|
|
25474
25566
|
const deployArgs = {
|
|
25475
|
-
action: "
|
|
25567
|
+
action: "release_application",
|
|
25476
25568
|
ref,
|
|
25477
25569
|
id,
|
|
25478
25570
|
environment_id: environmentId,
|
|
25479
25571
|
release_id: releaseId,
|
|
25480
|
-
configuration_id: configurationId
|
|
25572
|
+
configuration_id: configurationId,
|
|
25573
|
+
activation_id: activationId,
|
|
25574
|
+
...configurationWrite === undefined ? {} : { configuration_write: configurationWrite }
|
|
25481
25575
|
};
|
|
25482
25576
|
validateToolArguments(APPLICATION_TOOL_SCHEMA, deployArgs);
|
|
25483
25577
|
const deployed = await delegate(deployArgs);
|
|
@@ -25498,7 +25592,7 @@ async function runAppRelease(request, options, delegate) {
|
|
|
25498
25592
|
manifest_path: manifestPath,
|
|
25499
25593
|
build: buildReceipt ? completed.build : { skipped: true, manifest_path: manifestPath },
|
|
25500
25594
|
phases: completed,
|
|
25501
|
-
no_op: deployReceipt.no_op === true,
|
|
25595
|
+
no_op: deployReceipt.action === "no-op" || deployReceipt.no_op === true,
|
|
25502
25596
|
execution_performed: deployReceipt.execution_performed === true,
|
|
25503
25597
|
...typeof deployReceipt.activation_id === "string" ? { activation_id: deployReceipt.activation_id } : {}
|
|
25504
25598
|
};
|
|
@@ -26474,9 +26568,9 @@ function buildDatabaseAiContext(modules, root, moduleName, target) {
|
|
|
26474
26568
|
]
|
|
26475
26569
|
},
|
|
26476
26570
|
verification: [
|
|
26477
|
-
"supacloud
|
|
26478
|
-
"supacloud
|
|
26479
|
-
'supacloud
|
|
26571
|
+
"supacloud db lint --module_file db/modules.ts",
|
|
26572
|
+
"supacloud db explain --target <object>",
|
|
26573
|
+
'supacloud db module_check --module_file db/modules.ts --database_url "$DATABASE_URL"'
|
|
26480
26574
|
]
|
|
26481
26575
|
};
|
|
26482
26576
|
}
|
|
@@ -27684,7 +27778,7 @@ function registerReleaseTools(server, http, options = {}) {
|
|
|
27684
27778
|
content: [
|
|
27685
27779
|
{
|
|
27686
27780
|
type: "text",
|
|
27687
|
-
text: "⚠️ This command requires Management API context. Run `supacloud
|
|
27781
|
+
text: "⚠️ This command requires Management API context. Run `supacloud status` to inspect current detection."
|
|
27688
27782
|
}
|
|
27689
27783
|
]
|
|
27690
27784
|
};
|
|
@@ -27854,6 +27948,14 @@ import { createHash as createHash9 } from "node:crypto";
|
|
|
27854
27948
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
27855
27949
|
import { basename as basename8, dirname as dirname11, join as join17, relative as relative10, resolve as resolve22, sep as sep5 } from "node:path";
|
|
27856
27950
|
var MAX_SOURCE_BYTES = 256 * 1024 * 1024;
|
|
27951
|
+
var PUBLIC_BUILD_ENV_PREFIXES = ["PUBLIC_", "VITE_", "NEXT_PUBLIC_", "NUXT_PUBLIC_", "ASTRO_PUBLIC_"];
|
|
27952
|
+
var SENSITIVE_BUILD_ENV = /(?:^|_)(?:PASSWORD|PASS|SECRET|TOKEN|KEY|CREDENTIAL|AUTHORIZATION|COOKIE|SESSION)(?:_|$)|(?:DATABASE_URL|DATABASE_URI|CONNECTION_STRING|DSN|PRIVATE_KEY)/i;
|
|
27953
|
+
function isPublicBuildEnv(name) {
|
|
27954
|
+
return PUBLIC_BUILD_ENV_PREFIXES.some((prefix) => name.startsWith(prefix));
|
|
27955
|
+
}
|
|
27956
|
+
function isProtectedBuildEnv(name) {
|
|
27957
|
+
return name.startsWith("SUPACLOUD_") || name === "SUPABASE_SERVICE_ROLE_KEY" || name === "SUPABASE_ACCESS_TOKEN" || name === "MANAGEMENT_API_URL" || name === "MANAGEMENT_API_TOKEN";
|
|
27958
|
+
}
|
|
27857
27959
|
var deployToolSchema = {
|
|
27858
27960
|
ref: optional(String2(), "Project ref (defaults to the linked project)"),
|
|
27859
27961
|
target: optional(String2(), "Named deploy target from supacloud.json"),
|
|
@@ -27898,11 +28000,13 @@ async function readJson(path) {
|
|
|
27898
28000
|
throw new Error(`Invalid JSON file ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
27899
28001
|
}
|
|
27900
28002
|
}
|
|
27901
|
-
async function findDeployConfigRoot(startDirectory) {
|
|
28003
|
+
async function findDeployConfigRoot(startDirectory, environmentName) {
|
|
27902
28004
|
let directory = resolve22(startDirectory);
|
|
27903
28005
|
while (true) {
|
|
27904
|
-
|
|
28006
|
+
const environmentFile = environmentName ? `.env.supacloud.${environmentName}` : null;
|
|
28007
|
+
if (await pathExists(join17(directory, "supacloud.json")) || await pathExists(join17(directory, "supacloud.config.ts")) || environmentFile !== null && await pathExists(join17(directory, environmentFile))) {
|
|
27905
28008
|
return directory;
|
|
28009
|
+
}
|
|
27906
28010
|
const parent = dirname11(directory);
|
|
27907
28011
|
if (parent === directory)
|
|
27908
28012
|
return resolve22(startDirectory);
|
|
@@ -27924,6 +28028,26 @@ function optionalBoolean(value, field) {
|
|
|
27924
28028
|
throw new Error(`supacloud.json ${field} must be a boolean`);
|
|
27925
28029
|
return value;
|
|
27926
28030
|
}
|
|
28031
|
+
function optionalStringArray(value, field) {
|
|
28032
|
+
if (value === undefined)
|
|
28033
|
+
return;
|
|
28034
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !item.trim())) {
|
|
28035
|
+
throw new Error(`supacloud.json ${field} must be an array of non-empty strings`);
|
|
28036
|
+
}
|
|
28037
|
+
return value.map((item) => item.trim()).map((name) => {
|
|
28038
|
+
if (!/^[A-Z_][A-Z0-9_]*$/.test(name)) {
|
|
28039
|
+
throw new Error(`supacloud.json ${field} must contain uppercase environment variable names`);
|
|
28040
|
+
}
|
|
28041
|
+
const isPublic = isPublicBuildEnv(name);
|
|
28042
|
+
if (SENSITIVE_BUILD_ENV.test(name) && !isPublic) {
|
|
28043
|
+
throw new Error(`supacloud.json ${field} cannot include sensitive variable '${name}'; use runtime secrets instead`);
|
|
28044
|
+
}
|
|
28045
|
+
if (isProtectedBuildEnv(name)) {
|
|
28046
|
+
throw new Error(`supacloud.json ${field} cannot include platform credential '${name}'`);
|
|
28047
|
+
}
|
|
28048
|
+
return name;
|
|
28049
|
+
});
|
|
28050
|
+
}
|
|
27927
28051
|
function deployTargetConfig(candidate, name) {
|
|
27928
28052
|
const value = record4(candidate);
|
|
27929
28053
|
if (!value || value.type !== "frontend" && value.type !== "edge_function") {
|
|
@@ -27940,6 +28064,7 @@ function deployTargetConfig(candidate, name) {
|
|
|
27940
28064
|
slug: optionalText(value.slug, `targets.${name}.slug`),
|
|
27941
28065
|
buildCommand: optionalText(value.buildCommand, `targets.${name}.buildCommand`),
|
|
27942
28066
|
outputDirectory: optionalText(value.outputDirectory, `targets.${name}.outputDirectory`),
|
|
28067
|
+
buildEnv: optionalStringArray(value.buildEnv, `targets.${name}.buildEnv`),
|
|
27943
28068
|
bundleDirectory: optionalText(value.bundleDirectory, `targets.${name}.bundleDirectory`),
|
|
27944
28069
|
entrypoint: optionalText(value.entrypoint, `targets.${name}.entrypoint`),
|
|
27945
28070
|
verifyJwt: optionalBoolean(value.verifyJwt, `targets.${name}.verifyJwt`),
|
|
@@ -27965,7 +28090,8 @@ async function readDeployConfig(configRoot) {
|
|
|
27965
28090
|
id: optionalText(frontend.id, "frontend.id"),
|
|
27966
28091
|
root: optionalText(frontend.root, "frontend.root"),
|
|
27967
28092
|
buildCommand: optionalText(frontend.buildCommand, "frontend.buildCommand"),
|
|
27968
|
-
outputDirectory: optionalText(frontend.outputDirectory, "frontend.outputDirectory")
|
|
28093
|
+
outputDirectory: optionalText(frontend.outputDirectory, "frontend.outputDirectory"),
|
|
28094
|
+
buildEnv: optionalStringArray(frontend.buildEnv, "frontend.buildEnv")
|
|
27969
28095
|
} : undefined
|
|
27970
28096
|
};
|
|
27971
28097
|
}
|
|
@@ -28036,7 +28162,8 @@ function selectTarget(configRoot, invocationDirectory, config, requestedName) {
|
|
|
28036
28162
|
root: config.frontend?.root,
|
|
28037
28163
|
id: config.frontend?.id,
|
|
28038
28164
|
buildCommand: config.frontend?.buildCommand,
|
|
28039
|
-
outputDirectory: config.frontend?.outputDirectory
|
|
28165
|
+
outputDirectory: config.frontend?.outputDirectory,
|
|
28166
|
+
buildEnv: config.frontend?.buildEnv
|
|
28040
28167
|
}]];
|
|
28041
28168
|
if (targets.length === 0)
|
|
28042
28169
|
throw new Error("supacloud.json defines no deploy targets");
|
|
@@ -28084,10 +28211,28 @@ function resolveInsideProject(projectDirectory, candidate, allowRoot = false) {
|
|
|
28084
28211
|
}
|
|
28085
28212
|
return resolved;
|
|
28086
28213
|
}
|
|
28087
|
-
|
|
28214
|
+
function createBuildEnvironment(names, environmentVariables) {
|
|
28215
|
+
const selectedNames = [...new Set(names || [])].sort();
|
|
28216
|
+
const selectedNameSet = new Set(selectedNames);
|
|
28217
|
+
const values = environmentVariables ?? process.env;
|
|
28218
|
+
const env = Object.fromEntries(Object.entries(process.env).filter(([name]) => !isProtectedBuildEnv(name) && (!isPublicBuildEnv(name) || selectedNameSet.has(name)) && (!SENSITIVE_BUILD_ENV.test(name) || isPublicBuildEnv(name))));
|
|
28219
|
+
const missing = selectedNames.filter((name) => !values[name]?.trim());
|
|
28220
|
+
for (const name of selectedNames) {
|
|
28221
|
+
const value = values[name];
|
|
28222
|
+
if (value !== undefined)
|
|
28223
|
+
env[name] = value;
|
|
28224
|
+
}
|
|
28225
|
+
return { env, names: selectedNames, missing };
|
|
28226
|
+
}
|
|
28227
|
+
function assertBuildEnvironment(build, skipBuild) {
|
|
28228
|
+
if (!skipBuild && build.missing.length > 0) {
|
|
28229
|
+
throw new Error(`Missing build environment variables: ${build.missing.join(", ")}`);
|
|
28230
|
+
}
|
|
28231
|
+
}
|
|
28232
|
+
async function runBuild(command, cwd, environment, json) {
|
|
28088
28233
|
const child = Bun.spawn(["sh", "-c", command], {
|
|
28089
28234
|
cwd,
|
|
28090
|
-
env:
|
|
28235
|
+
env: environment,
|
|
28091
28236
|
stdio: ["inherit", json ? 2 : "inherit", "inherit"]
|
|
28092
28237
|
});
|
|
28093
28238
|
const exitCode = await child.exited;
|
|
@@ -28207,6 +28352,42 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28207
28352
|
if (!projectRef)
|
|
28208
28353
|
throw new Error("A linked project ref is required. Set SUPACLOUD_PROJECT_REF or pass --ref");
|
|
28209
28354
|
const configRoot = await findDeployConfigRoot(invocationDirectory);
|
|
28355
|
+
if (options.application?.id) {
|
|
28356
|
+
if (!options.applicationRelease) {
|
|
28357
|
+
throw new Error("Application release support is unavailable in this CLI context");
|
|
28358
|
+
}
|
|
28359
|
+
if (args.target || args.build_command || args.output_dir) {
|
|
28360
|
+
throw new Error("Application profile deploy does not accept frontend target, build command, or output directory flags");
|
|
28361
|
+
}
|
|
28362
|
+
if (args.dry_run === true || args.plan === true || args.diff === true) {
|
|
28363
|
+
throw new Error("Application profile deploy does not support dry_run, plan, or diff; use app deploy-plan for a read-only plan");
|
|
28364
|
+
}
|
|
28365
|
+
const environmentId = options.application.environmentId.trim();
|
|
28366
|
+
if (!environmentId) {
|
|
28367
|
+
throw new Error("Application profile requires SUPACLOUD_APPLICATION_ENVIRONMENT_ID or SUPACLOUD_ENV");
|
|
28368
|
+
}
|
|
28369
|
+
const configurationPath = options.application.configurationPath?.trim();
|
|
28370
|
+
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
|
+
if (configurationPath && configurationId) {
|
|
28375
|
+
throw new Error("Application profile must set only one of SUPACLOUD_APPLICATION_CONFIGURATION_PATH or SUPACLOUD_APPLICATION_CONFIGURATION_ID");
|
|
28376
|
+
}
|
|
28377
|
+
const result = await options.applicationRelease({
|
|
28378
|
+
action: "release",
|
|
28379
|
+
ref: projectRef,
|
|
28380
|
+
id: options.application.id,
|
|
28381
|
+
environment_id: environmentId,
|
|
28382
|
+
root: configRoot,
|
|
28383
|
+
...configurationPath ? { configuration_path: configurationPath } : {},
|
|
28384
|
+
...configurationId ? { configuration_id: configurationId } : {},
|
|
28385
|
+
...options.application.manifestPath ? { manifest_path: options.application.manifestPath } : {},
|
|
28386
|
+
...args.skip_build === true ? { skip_build: true } : {},
|
|
28387
|
+
...args.json === true ? { format: "json", json: true } : {}
|
|
28388
|
+
});
|
|
28389
|
+
return result;
|
|
28390
|
+
}
|
|
28210
28391
|
const config = await readDeployConfig(configRoot);
|
|
28211
28392
|
const target = selectTarget(configRoot, invocationDirectory, config, String(args.target || "").trim() || undefined);
|
|
28212
28393
|
const projectDirectory = target.root;
|
|
@@ -28215,6 +28396,7 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28215
28396
|
throw new Error(`Deploy target '${target.name}' root is not a regular directory: ${projectDirectory}`);
|
|
28216
28397
|
}
|
|
28217
28398
|
const requestedId = String(args.id || target.config.id || "").trim() || undefined;
|
|
28399
|
+
const build = createBuildEnvironment(target.config.buildEnv, options.environmentVariables);
|
|
28218
28400
|
const report = phaseReporter(args.json === true);
|
|
28219
28401
|
report("inspect", `${target.name} (${projectRef})`);
|
|
28220
28402
|
if (target.config.type === "edge_function") {
|
|
@@ -28252,14 +28434,17 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28252
28434
|
project_ref: projectRef,
|
|
28253
28435
|
slug,
|
|
28254
28436
|
build_command: args.skip_build === true ? null : buildCommand,
|
|
28437
|
+
build_env: build.names,
|
|
28438
|
+
missing_build_env: build.missing,
|
|
28255
28439
|
bundle_directory: bundleDirectory,
|
|
28256
28440
|
expected_active_version: activeVersion,
|
|
28257
28441
|
expected_activation_id: activationId
|
|
28258
28442
|
}, null, 2) }] };
|
|
28259
28443
|
}
|
|
28444
|
+
assertBuildEnvironment(build, args.skip_build === true);
|
|
28260
28445
|
if (args.skip_build !== true) {
|
|
28261
28446
|
report("build", buildCommand);
|
|
28262
|
-
await runBuild(buildCommand, projectDirectory, args.json === true);
|
|
28447
|
+
await runBuild(buildCommand, projectDirectory, build.env, args.json === true);
|
|
28263
28448
|
} else {
|
|
28264
28449
|
report("build", "skipped");
|
|
28265
28450
|
}
|
|
@@ -28309,12 +28494,15 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28309
28494
|
project_ref: projectRef,
|
|
28310
28495
|
deployment_id: selected.id,
|
|
28311
28496
|
build_command: args.skip_build === true ? null : buildCommand,
|
|
28497
|
+
build_env: build.names,
|
|
28498
|
+
missing_build_env: build.missing,
|
|
28312
28499
|
output_directory: outputDirectory
|
|
28313
28500
|
}, null, 2) }] };
|
|
28314
28501
|
}
|
|
28502
|
+
assertBuildEnvironment(build, args.skip_build === true);
|
|
28315
28503
|
if (args.skip_build !== true) {
|
|
28316
28504
|
report("build", buildCommand);
|
|
28317
|
-
await runBuild(buildCommand, projectDirectory, args.json === true);
|
|
28505
|
+
await runBuild(buildCommand, projectDirectory, build.env, args.json === true);
|
|
28318
28506
|
} else {
|
|
28319
28507
|
report("build", "skipped");
|
|
28320
28508
|
}
|
|
@@ -28702,7 +28890,7 @@ function registerRemoteDevTools(server, options = {}) {
|
|
|
28702
28890
|
// package.json
|
|
28703
28891
|
var package_default = {
|
|
28704
28892
|
name: "@supacloud/cli",
|
|
28705
|
-
version: "0.
|
|
28893
|
+
version: "0.87.0",
|
|
28706
28894
|
description: "Project-scoped CLI for SupaCloud users",
|
|
28707
28895
|
type: "module",
|
|
28708
28896
|
main: "./dist/index.js",
|
|
@@ -28720,7 +28908,7 @@ var package_default = {
|
|
|
28720
28908
|
}
|
|
28721
28909
|
},
|
|
28722
28910
|
bin: {
|
|
28723
|
-
|
|
28911
|
+
supacloud: "dist/index.js"
|
|
28724
28912
|
},
|
|
28725
28913
|
files: [
|
|
28726
28914
|
"NOTICE",
|
|
@@ -28754,14 +28942,14 @@ var package_default = {
|
|
|
28754
28942
|
directory: "packages/cli"
|
|
28755
28943
|
},
|
|
28756
28944
|
dependencies: {
|
|
28757
|
-
"@supacloud/compiler": "^0.
|
|
28758
|
-
"@supacloud/delivery": "0.
|
|
28945
|
+
"@supacloud/compiler": "^0.44.0",
|
|
28946
|
+
"@supacloud/delivery": "0.14.0",
|
|
28759
28947
|
"@supacloud/db": "0.16.0",
|
|
28760
28948
|
typebox: "1.3.34"
|
|
28761
28949
|
},
|
|
28762
28950
|
overrides: {
|
|
28763
28951
|
"@supacloud/contracts": "0.8.0",
|
|
28764
|
-
"@supacloud/delivery": "0.
|
|
28952
|
+
"@supacloud/delivery": "0.14.0",
|
|
28765
28953
|
"@graphql-tools/utils": "^12.0.3"
|
|
28766
28954
|
},
|
|
28767
28955
|
devDependencies: {
|
|
@@ -28774,7 +28962,7 @@ var package_default = {
|
|
|
28774
28962
|
};
|
|
28775
28963
|
|
|
28776
28964
|
// src/index.ts
|
|
28777
|
-
var commandName = "supacloud
|
|
28965
|
+
var commandName = "supacloud";
|
|
28778
28966
|
var preferredCommand = commandName;
|
|
28779
28967
|
var projectActionSchema = stringEnum([
|
|
28780
28968
|
"get",
|
|
@@ -28929,7 +29117,7 @@ function printHelp(context) {
|
|
|
28929
29117
|
const autoLink = context.inferredSupabaseUrl ? `Project context: ${context.inferredSupabaseUrl} (${context.source})` : "Project context: not detected";
|
|
28930
29118
|
console.error(`
|
|
28931
29119
|
╔═══════════════════════════════════════════════════════════╗
|
|
28932
|
-
║ supacloud
|
|
29120
|
+
║ supacloud ║
|
|
28933
29121
|
║ Project CLI for SupaCloud users ║
|
|
28934
29122
|
╚═══════════════════════════════════════════════════════════╝
|
|
28935
29123
|
|
|
@@ -28971,6 +29159,8 @@ EXAMPLES
|
|
|
28971
29159
|
|
|
28972
29160
|
${preferredCommand} status
|
|
28973
29161
|
${preferredCommand} deploy
|
|
29162
|
+
${preferredCommand} --env test deploy
|
|
29163
|
+
${preferredCommand} --env production deploy --confirm-production <project-ref>
|
|
28974
29164
|
${preferredCommand} deploy --target web
|
|
28975
29165
|
${preferredCommand} deploy --target api
|
|
28976
29166
|
${preferredCommand} dev sync --env test --target functions --function api
|
|
@@ -29237,7 +29427,7 @@ function createCliTools(context, confirmProduction) {
|
|
|
29237
29427
|
"Provide one of these sources:",
|
|
29238
29428
|
"",
|
|
29239
29429
|
" 1. Named environment file",
|
|
29240
|
-
" supacloud
|
|
29430
|
+
" supacloud --env test status",
|
|
29241
29431
|
"",
|
|
29242
29432
|
" 2. Explicit environment variables",
|
|
29243
29433
|
" SUPACLOUD_API_URL=https://your-project.example.com",
|
|
@@ -29290,7 +29480,7 @@ function createCliTools(context, confirmProduction) {
|
|
|
29290
29480
|
assign(captureTools((server) => registerAuthTools(server, http)));
|
|
29291
29481
|
assign(captureTools((server) => registerOAuthClientTools(server, http)));
|
|
29292
29482
|
assign(captureTools((server) => registerStorageTools(server, http)));
|
|
29293
|
-
const advancedTools = captureTools((server) => registerAdvancedTools(server, http,
|
|
29483
|
+
const advancedTools = captureTools((server) => registerAdvancedTools(server, http, context.environmentVariables, {
|
|
29294
29484
|
readOnly: context.readOnly
|
|
29295
29485
|
}));
|
|
29296
29486
|
assign(advancedTools);
|
|
@@ -29314,6 +29504,18 @@ function createCliTools(context, confirmProduction) {
|
|
|
29314
29504
|
environment: context.environment,
|
|
29315
29505
|
projectRef: context.projectRef || undefined,
|
|
29316
29506
|
cwd: process.cwd(),
|
|
29507
|
+
environmentVariables: context.environmentVariables,
|
|
29508
|
+
application: context.applicationId ? {
|
|
29509
|
+
id: context.applicationId,
|
|
29510
|
+
environmentId: context.applicationEnvironmentId,
|
|
29511
|
+
...context.applicationConfigurationPath ? { configurationPath: context.applicationConfigurationPath } : {},
|
|
29512
|
+
...context.applicationConfigurationId ? { configurationId: context.applicationConfigurationId } : {},
|
|
29513
|
+
...context.applicationManifestPath ? { manifestPath: context.applicationManifestPath } : {}
|
|
29514
|
+
} : undefined,
|
|
29515
|
+
applicationRelease: (args) => tools.app ? tools.app.callback(args) : Promise.resolve({
|
|
29516
|
+
isError: true,
|
|
29517
|
+
content: [{ type: "text", text: "Application release support is unavailable in this CLI context" }]
|
|
29518
|
+
}),
|
|
29317
29519
|
edgeFunctionDeploy: advancedTools.edge_functions?.callback
|
|
29318
29520
|
})));
|
|
29319
29521
|
assign(captureTools((server) => registerGatewayTools(server, http, {
|
|
@@ -29337,7 +29539,7 @@ async function main() {
|
|
|
29337
29539
|
}
|
|
29338
29540
|
const globalOptions = parseGlobalOptions(rawArgs);
|
|
29339
29541
|
const args = globalOptions.args;
|
|
29340
|
-
const contextDirectory = args[0] === "deploy" ? await findDeployConfigRoot(process.cwd()) : process.cwd();
|
|
29542
|
+
const contextDirectory = args[0] === "deploy" ? await findDeployConfigRoot(process.cwd(), globalOptions.environmentName) : process.cwd();
|
|
29341
29543
|
const context = resolveSupaCloudContext(process.env, contextDirectory, {
|
|
29342
29544
|
environmentName: globalOptions.environmentName,
|
|
29343
29545
|
envFile: globalOptions.envFile
|