@supacloud/cli 0.96.0 → 0.96.2

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 CHANGED
@@ -26,11 +26,15 @@ supacloud --env test deploy
26
26
  overwriting an existing project configuration. `env list` and `env check` are
27
27
  local-only, redact credentials, and provide stable JSON with `--json` for CI or
28
28
  AI tooling. The real `.env.supacloud.*` files are added to `.gitignore`.
29
- Fill in `SUPACLOUD_APPLICATION_ID` and the Management credentials in the
30
- selected profile, and configure the application's current delivery build.
31
- Standalone frontend deployment is no longer supported. Upgrade the CLI with
29
+ Fill in the Management credentials and project/environment in the selected profile.
30
+ Static frontends need only `frontend` build configuration; no application binding
31
+ or backend delivery build is required. Set `SUPACLOUD_APPLICATION_ID` only for
32
+ executable application delivery. Upgrade the CLI with
32
33
  `npm install -g @supacloud/cli@latest` and upgrade the SupaCloud server together.
33
34
  `deploy` checks the server protocol before building or uploading.
35
+ Use `frontend.name` to select exactly one named site in each environment when
36
+ deployment IDs differ. A missing or ambiguous name fails before upload; it never
37
+ falls back to another site.
34
38
 
35
39
  ## Application Starter
36
40
 
@@ -645,7 +649,12 @@ FA-owned business features are documented in
645
649
  and `--dry_run` are removed. Put build settings in `supacloud.json`; use
646
650
  `app deploy-plan` for read-only review. Historical project-specific manifests
647
651
  and standalone Function targets must move to application delivery configuration.
648
- The CLI rejects them rather than falling back to a partial Web deployment.
652
+ The CLI rejects them rather than silently falling back to a partial Web deployment.
653
+ For an intentional Web-only release in a mixed repository, use
654
+ `supacloud --env test deploy --assets_only`. This preserves historical manifests,
655
+ Functions, schedules and migrations without invoking application compilation.
656
+ Static publication reuses immutable archives, pre-upload CAS, mutation receipts
657
+ and exact post-activation readback. It never retries a conflicting activation.
649
658
 
650
659
  The legacy `.env` fallback is unclassified and therefore does not enable the
651
660
  production confirmation gate. Production automation must select a `prod` or
package/dist/index.js CHANGED
@@ -8767,7 +8767,7 @@ function outcomeUnknownGuidance(text) {
8767
8767
  }
8768
8768
 
8769
8769
  // src/shared/deployment-upgrade.ts
8770
- var DEPLOYMENT_UPGRADE = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment is no longer supported. Upgrade with `npm install -g @supacloud/cli@latest`, bind application.id and application.environmentId in supacloud.json (or SUPACLOUD_APPLICATION_ID and SUPACLOUD_ENV), then run `supacloud deploy`. SupaCloud owns deployment planning and activation; do not retry with legacy commands.";
8770
+ var DEPLOYMENT_UPGRADE = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment commands are no longer supported. Upgrade with `npm install -g @supacloud/cli@latest`, configure frontend in supacloud.json for static assets, or application.id and application.environmentId for executable application delivery, then run `supacloud deploy`. Use `supacloud deploy --assets_only` to publish only Web assets in a mixed repository. SupaCloud owns activation; do not retry with legacy commands.";
8771
8771
  var removedFrontendActions = new Set([
8772
8772
  "deploy_git",
8773
8773
  "deploy_upload",
@@ -10925,12 +10925,157 @@ function parseDeploymentEvidence(value) {
10925
10925
  }
10926
10926
  return structuredClone(value);
10927
10927
  }
10928
- // node_modules/@supacloud/delivery/src/application-promotion.ts
10928
+ // node_modules/@supacloud/delivery/src/delivery-tuple.ts
10929
+ var sha2563 = String2({ pattern: "^[a-f0-9]{64}$" });
10930
+ var commit = String2({ pattern: "^(?:[a-f0-9]{40}|[a-f0-9]{64})$" });
10931
+ var isoDate2 = String2({ minLength: 20, maxLength: 40 });
10932
+ var DELIVERY_TUPLE_SCHEMA = "supacloud.fa-delivery-tuple.v1";
10933
+ var FaDeliveryTupleSchema = _Object_({
10934
+ schema: Literal(DELIVERY_TUPLE_SCHEMA),
10935
+ customer: Literal("xigu-fa"),
10936
+ fa_commit: commit,
10937
+ cli: _Object_({
10938
+ version: String2({ pattern: "^\\d+\\.\\d+\\.\\d+$" })
10939
+ }, { additionalProperties: false }),
10940
+ platform_commit: commit,
10941
+ edge_runtime: _Object_({
10942
+ version: String2({ minLength: 1, maxLength: 128 }),
10943
+ artifact_sha256: sha2563
10944
+ }, { additionalProperties: false }),
10945
+ compatibility_window: _Object_({
10946
+ contract_schema: String2({ minLength: 1, maxLength: 128 }),
10947
+ starts_at: isoDate2,
10948
+ ends_at: isoDate2,
10949
+ old_client_supported: Boolean2(),
10950
+ partial_deployment_supported: Boolean2()
10951
+ }, { additionalProperties: false })
10952
+ }, { additionalProperties: false });
10953
+ // node_modules/@supacloud/delivery/src/contract-matrix.ts
10929
10954
  var closed6 = { additionalProperties: false };
10955
+ var sha2564 = String2({ pattern: "^[a-f0-9]{64}$" });
10956
+ var generation = Union([Literal("old"), Literal("new")]);
10957
+ var versions = _Object_({ old: sha2564, new: sha2564 }, closed6);
10958
+ var CONTRACT_MATRIX_SCHEMA = "supacloud.consumer-contract-matrix.v1";
10959
+ var FA_CONTRACT_SCENARIOS = [
10960
+ "missing-display-field",
10961
+ "missing-authority-field",
10962
+ "added-field",
10963
+ "legacy-envelope",
10964
+ "lost-write-response",
10965
+ "downgrade"
10966
+ ];
10967
+ var ConsumerContractMatrixSchema = _Object_({
10968
+ schema: Literal(CONTRACT_MATRIX_SCHEMA),
10969
+ customer: Literal("xigu-fa"),
10970
+ baseline_tuple_sha256: sha2564,
10971
+ candidate_tuple_sha256: sha2564,
10972
+ artifacts: _Object_({ frontend: versions, functions: versions, database: versions }, closed6),
10973
+ cases: _Array_(_Object_({
10974
+ frontend: generation,
10975
+ functions: generation,
10976
+ database: generation,
10977
+ scenarios: _Array_(_Object_({
10978
+ name: Enum(FA_CONTRACT_SCENARIOS),
10979
+ expected: Union([Literal("compatible"), Literal("blocked-safely")])
10980
+ }, closed6), { minItems: FA_CONTRACT_SCENARIOS.length, maxItems: FA_CONTRACT_SCENARIOS.length })
10981
+ }, closed6), { minItems: 8, maxItems: 8 })
10982
+ }, closed6);
10983
+ // node_modules/@supacloud/delivery/src/fa-stability.ts
10984
+ var closed7 = { additionalProperties: false };
10985
+ var hash3 = String2({ pattern: "^[a-f0-9]{64}$" });
10986
+ var label = String2({ minLength: 1, maxLength: 256, pattern: "\\S" });
10987
+ var timestamp2 = String2({ minLength: 24, maxLength: 24 });
10988
+ var count = Integer({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER });
10989
+ var environment2 = Union([Literal("test"), Literal("production")]);
10990
+ var FA_REQUIRED_ACCEPTANCE = {
10991
+ login: "real-browser",
10992
+ permissions: "real-http",
10993
+ upload: "real-http",
10994
+ "async-task": "real-worker",
10995
+ deploy: "real-http",
10996
+ "database-migration": "real-database",
10997
+ schedule: "real-worker",
10998
+ rollback: "real-drill",
10999
+ "error-policy": "real-http",
11000
+ "alert-delivery": "real-drill"
11001
+ };
11002
+ var FA_BUSINESS_OPERATIONS = ["login", "permissions", "upload", "async-task", "report", "deploy"];
11003
+ var operation = Enum(FA_BUSINESS_OPERATIONS);
11004
+ var proof = _Object_({
11005
+ path: String2({ pattern: "^[A-Za-z0-9_-][A-Za-z0-9_./-]{0,255}$" }),
11006
+ sha256: hash3
11007
+ }, closed7);
11008
+ var FaBusinessObservationSchema = _Object_({
11009
+ id: String2({ pattern: "^[A-Za-z0-9_-]{1,128}$" }),
11010
+ tuple_sha256: hash3,
11011
+ operation,
11012
+ started_at: timestamp2,
11013
+ finished_at: timestamp2,
11014
+ outcome: Enum(["success", "failure", "timeout", "unknown"]),
11015
+ attempts: Integer({ minimum: 1, maximum: 1000 }),
11016
+ rollbacks: count
11017
+ }, closed7);
11018
+ var FaServiceObjectivesSchema = _Object_({
11019
+ status: Literal("approved"),
11020
+ owner: label,
11021
+ approval_reference: label,
11022
+ approved_at: timestamp2,
11023
+ project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
11024
+ environment: environment2,
11025
+ alert_route: label,
11026
+ window_hours: Number2({ exclusiveMinimum: 0, maximum: 8760 }),
11027
+ max_evidence_age_hours: Number2({ exclusiveMinimum: 0, maximum: 168 }),
11028
+ operations: _Array_(_Object_({
11029
+ operation,
11030
+ minimum_samples: Integer({ minimum: 1, maximum: Number.MAX_SAFE_INTEGER }),
11031
+ availability_percent: Number2({ exclusiveMinimum: 0, maximum: 100 }),
11032
+ p95_ms: Number2({ exclusiveMinimum: 0, maximum: Number.MAX_SAFE_INTEGER })
11033
+ }, closed7), { minItems: FA_BUSINESS_OPERATIONS.length, maxItems: FA_BUSINESS_OPERATIONS.length })
11034
+ }, closed7);
11035
+ var FaStabilityEvidenceSchema = _Object_({
11036
+ schema: Literal("supacloud.fa-stability-evidence.v1"),
11037
+ environment: environment2,
11038
+ project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
11039
+ tuple_sha256: hash3,
11040
+ matrix_sha256: hash3,
11041
+ objectives_sha256: hash3,
11042
+ recorded_at: timestamp2,
11043
+ window_start: timestamp2,
11044
+ window_end: timestamp2,
11045
+ reviewed_by: label,
11046
+ review_reference: label,
11047
+ acceptance: _Array_(_Object_({
11048
+ id: Enum(Object.keys(FA_REQUIRED_ACCEPTANCE)),
11049
+ execution: Enum([
11050
+ "real-browser",
11051
+ "real-http",
11052
+ "real-worker",
11053
+ "real-database",
11054
+ "real-drill",
11055
+ "local-fake"
11056
+ ]),
11057
+ passed: Boolean2(),
11058
+ measured_at: timestamp2,
11059
+ proof
11060
+ }, closed7), { minItems: 10, maxItems: 10 }),
11061
+ matrix: _Array_(_Object_({
11062
+ combination: label,
11063
+ scenario: label,
11064
+ outcome: Union([Literal("compatible"), Literal("blocked-safely")]),
11065
+ execution: Union([Literal("real-http-and-database"), Literal("local-fake")]),
11066
+ passed: Boolean2(),
11067
+ measured_at: timestamp2,
11068
+ proof
11069
+ }, closed7), { minItems: 48, maxItems: 48 }),
11070
+ observation: proof,
11071
+ alert: _Object_({ route: label, acknowledged_by: label, delivered_at: timestamp2 }, closed7)
11072
+ }, closed7);
11073
+ // node_modules/@supacloud/delivery/src/application-promotion.ts
11074
+ var closed8 = { additionalProperties: false };
10930
11075
  var projectRef2 = String2({ pattern: "^[a-z0-9-]{1,20}$" });
10931
- var sha2563 = ApplicationReleaseIdSchema;
11076
+ var sha2565 = ApplicationReleaseIdSchema;
10932
11077
  var nullableActivation2 = Union([ApplicationActivationIdSchema, Null()]);
10933
- var nullableDigest = Union([sha2563, Null()]);
11078
+ var nullableDigest = Union([sha2565, Null()]);
10934
11079
  var observation = {
10935
11080
  activation_id: nullableActivation2,
10936
11081
  receipt_confirmed: Boolean2(),
@@ -10956,33 +11101,33 @@ var ApplicationPromotionPlanSchema = _Object_({
10956
11101
  project_ref: projectRef2,
10957
11102
  application_id: ApplicationIdSchema,
10958
11103
  environment_id: ApplicationIdSchema,
10959
- manifest_sha256: sha2563,
10960
- plan_sha256: sha2563,
11104
+ manifest_sha256: sha2565,
11105
+ plan_sha256: sha2565,
10961
11106
  source: _Object_({
10962
11107
  project_ref: projectRef2,
10963
11108
  environment_id: ApplicationIdSchema,
10964
- release_id: sha2563,
11109
+ release_id: sha2565,
10965
11110
  ...observation
10966
- }, closed6),
11111
+ }, closed8),
10967
11112
  target: _Object_({
10968
- candidate_release_id: sha2563,
10969
- current_release_id: Union([sha2563, Null()]),
11113
+ candidate_release_id: sha2565,
11114
+ current_release_id: Union([sha2565, Null()]),
10970
11115
  artifact_action: Union([Literal("materialize"), Literal("reuse")]),
10971
11116
  configuration_id: Union([ApplicationConfigurationIdSchema, Null()]),
10972
11117
  configuration: Union([ApplicationConfigurationViewSchema, Null()]),
10973
11118
  ...observation
10974
- }, closed6),
11119
+ }, closed8),
10975
11120
  migrations: _Object_({
10976
- ledger_digest: sha2563,
11121
+ ledger_digest: sha2565,
10977
11122
  ledger_compatible: Boolean2(),
10978
11123
  project_migrations_applied: Boolean2(),
10979
11124
  pending_versions: _Array_(String2({ pattern: "^\\d{1,20}$" }), { maxItems: 4096, uniqueItems: true }),
10980
11125
  operator_provisioning_required: Boolean2()
10981
- }, closed6),
11126
+ }, closed8),
10982
11127
  backup: _Object_({
10983
11128
  required: Boolean2(),
10984
11129
  confirmed: Literal(false)
10985
- }, closed6),
11130
+ }, closed8),
10986
11131
  action: Union([Literal("promote"), Literal("no-op"), Literal("blocked")]),
10987
11132
  blockers: _Array_(Enum([...blocker]), {
10988
11133
  maxItems: blocker.length,
@@ -10991,7 +11136,7 @@ var ApplicationPromotionPlanSchema = _Object_({
10991
11136
  steps: _Array_(String2({ minLength: 1, maxLength: 64 }), { maxItems: 8, uniqueItems: true }),
10992
11137
  execution_performed: Literal(false),
10993
11138
  data_recovery: Literal("separate-required")
10994
- }, closed6);
11139
+ }, closed8);
10995
11140
  function applicationPromotionPlanDigest(value) {
10996
11141
  return digest(canonical(value));
10997
11142
  }
@@ -16350,6 +16495,39 @@ async function getFrontendRelease(http, projectRef, deploymentId, releaseId) {
16350
16495
  }
16351
16496
  return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release });
16352
16497
  }
16498
+ async function uploadFrontendRelease(http, projectRef, deploymentId, archivePath) {
16499
+ const endpoint = releaseEndpoint(projectRef, deploymentId);
16500
+ const archive = await verifiedArchive(archivePath);
16501
+ let response;
16502
+ try {
16503
+ response = await http.postBinary(endpoint, {
16504
+ stream: archiveStream(archive),
16505
+ byteLength: archive.sizeBytes
16506
+ }, {
16507
+ contentType: FRONTEND_ARCHIVE_CONTENT_TYPE,
16508
+ contentLength: archive.sizeBytes,
16509
+ contentSha256: archive.sha256,
16510
+ maxJsonBytes: RESPONSE_MAX_BYTES,
16511
+ timeoutMs: UPLOAD_REQUEST_TIMEOUT_MS,
16512
+ responseTimeoutMs: MUTATION_RESPONSE_TIMEOUT_MS
16513
+ });
16514
+ } finally {
16515
+ await archive.handle.close();
16516
+ }
16517
+ const release = response.ok ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId: archive.sha256 }) : null;
16518
+ if (!release) {
16519
+ if (response.status >= 400 && response.status < 500 && response.status !== 408 && !response.transportError) {
16520
+ return releaseFailure("frontend.upload_release", "HTTP_ERROR", response.status);
16521
+ }
16522
+ return uploadReadback(http, projectRef, deploymentId, archive.sha256, response.status);
16523
+ }
16524
+ const readback = await http.get(`${endpoint}/${release.release_id}`, { maxJsonBytes: RESPONSE_MAX_BYTES });
16525
+ const verified = readback.ok ? releaseEnvelope(readback.data, { projectRef, deploymentId, releaseId: release.release_id }) : null;
16526
+ if (!verified || verified.tree_sha256 !== release.tree_sha256) {
16527
+ return releaseFailure("frontend.upload_release", "OUTCOME_UNKNOWN", readback.status);
16528
+ }
16529
+ return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release: verified });
16530
+ }
16353
16531
  async function uploadProjectWebRelease(http, projectRef, environmentId, deploymentId, archivePath) {
16354
16532
  const endpoint = `/v1/projects/${encodeURIComponent(projectRef)}/environments/${encodeURIComponent(environmentId)}/deployments/web-release?deployment_id=${encodeURIComponent(deploymentId)}`;
16355
16533
  const archive = await verifiedArchive(archivePath);
@@ -16404,6 +16582,16 @@ async function uploadProjectWebRelease(http, projectRef, environmentId, deployme
16404
16582
  await archive.handle.close();
16405
16583
  }
16406
16584
  }
16585
+ async function uploadReadback(http, projectRef, deploymentId, releaseId, uploadStatus) {
16586
+ const response = await http.get(releasePath(projectRef, deploymentId, releaseId), {
16587
+ maxJsonBytes: RESPONSE_MAX_BYTES
16588
+ });
16589
+ const release = response.ok ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId }) : null;
16590
+ if (!release) {
16591
+ return releaseFailure("frontend.upload_release", "OUTCOME_UNKNOWN", uploadStatus);
16592
+ }
16593
+ return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release });
16594
+ }
16407
16595
  function stableJson(candidate) {
16408
16596
  if (candidate === null || typeof candidate !== "object")
16409
16597
  return JSON.stringify(candidate);
@@ -16523,6 +16711,57 @@ async function getActiveFrontendRelease(http, projectRef, deploymentId) {
16523
16711
  const snapshot = await readActiveFrontendRelease(http, projectRef, deploymentId);
16524
16712
  return "failure" in snapshot ? snapshot.failure : toolResponse(snapshot.inventory);
16525
16713
  }
16714
+ async function publishFrontendRelease(http, projectRef, deploymentId, archivePath, expectedTreeSha256) {
16715
+ const authority = await readActiveFrontendRelease(http, projectRef, deploymentId);
16716
+ if ("failure" in authority)
16717
+ return authority.failure;
16718
+ const inventory = authority.inventory;
16719
+ const current = inventory.releases[0];
16720
+ if (current?.tree_sha256 === expectedTreeSha256) {
16721
+ return toolResponse({
16722
+ operation: "frontend.deploy",
16723
+ project_ref: projectRef,
16724
+ deployment_id: deploymentId,
16725
+ active_release_id: inventory.active_release_id,
16726
+ activation_id: inventory.active_activation_id,
16727
+ release: current,
16728
+ unchanged: true
16729
+ });
16730
+ }
16731
+ const uploaded = await uploadFrontendRelease(http, projectRef, deploymentId, archivePath);
16732
+ if (uploaded.isError)
16733
+ return uploaded;
16734
+ const value = JSON.parse(uploaded.content[0].text);
16735
+ const envelope = value && typeof value === "object" && !Array.isArray(value) ? value : null;
16736
+ const candidate = envelope?.release;
16737
+ const release = candidate && typeof candidate === "object" && !Array.isArray(candidate) ? candidate : null;
16738
+ if (!release || release.tree_sha256 !== expectedTreeSha256 || typeof release.release_id !== "string" || !RELEASE_ID_PATTERN.test(release.release_id)) {
16739
+ return releaseFailure("frontend.deploy", "INVALID_RESPONSE", 200);
16740
+ }
16741
+ const mutationId = crypto.randomUUID();
16742
+ const activated = await activateFrontendRelease(http, {
16743
+ projectRef,
16744
+ deploymentId,
16745
+ releaseId: release.release_id,
16746
+ mutationId,
16747
+ expectedActiveReleaseId: inventory.active_release_id ?? "absent",
16748
+ expectedActivationId: inventory.active_activation_id ?? "absent"
16749
+ });
16750
+ const activatedPayload = JSON.parse(activated.content[0].text);
16751
+ const active = activatedPayload.release;
16752
+ const treeMismatch = !activated.isError && (!active || typeof active !== "object" || !("tree_sha256" in active) || active.tree_sha256 !== expectedTreeSha256);
16753
+ return {
16754
+ ...toolResponse({
16755
+ ...treeMismatch ? { ok: false, error: { code: "OUTCOME_UNKNOWN", http_status: 200 } } : activatedPayload,
16756
+ operation: "frontend.deploy",
16757
+ mutation_id: mutationId,
16758
+ target_release_id: release.release_id,
16759
+ previous_release_id: inventory.active_release_id,
16760
+ previous_activation_id: inventory.active_activation_id
16761
+ }),
16762
+ ...activated.isError || treeMismatch ? { isError: true } : {}
16763
+ };
16764
+ }
16526
16765
  async function rollbackFrontendRelease(http, projectRef, deploymentId, releaseId) {
16527
16766
  if (releaseId !== undefined && !RELEASE_ID_PATTERN.test(releaseId)) {
16528
16767
  throw new Error("'release_id' must be a SHA-256 digest");
@@ -17097,12 +17336,12 @@ async function fetchMutationStatus(http, ref, mutationId) {
17097
17336
  }
17098
17337
 
17099
17338
  // src/shared/tools/application-workflow-schemas.ts
17100
- var closed7 = { additionalProperties: false };
17339
+ var closed9 = { additionalProperties: false };
17101
17340
  var ref5 = String2({ pattern: "^[A-Za-z0-9_-]{1,20}$" });
17102
17341
  var uuid = ApplicationActivationIdSchema2;
17103
17342
  var nullableUuid = Union([uuid, Null()]);
17104
17343
  var nullableDigest2 = Union([ApplicationReleaseIdSchema2, Null()]);
17105
- var timestamp2 = String2({ pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$" });
17344
+ var timestamp3 = String2({ pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$" });
17106
17345
  var scope2 = { project_ref: ref5, application_id: ApplicationIdSchema2, environment_id: ApplicationIdSchema2 };
17107
17346
  var ApplicationPromotionResultSchema = _Object_({
17108
17347
  ...scope2,
@@ -17111,7 +17350,7 @@ var ApplicationPromotionResultSchema = _Object_({
17111
17350
  plan_sha256: ApplicationReleaseIdSchema2,
17112
17351
  action: Literal("promote"),
17113
17352
  replayed: Boolean2()
17114
- }, closed7);
17353
+ }, closed9);
17115
17354
  var ApplicationPromotionStatusSchema = _Object_({
17116
17355
  ...scope2,
17117
17356
  mutation: Unknown(),
@@ -17130,8 +17369,8 @@ var ApplicationPromotionStatusSchema = _Object_({
17130
17369
  configuration_id: Union([ApplicationConfigurationIdSchema2, Null()]),
17131
17370
  backup_id: Union([String2({ pattern: "^logical-full_[a-z0-9-]{1,20}_[a-f0-9]{32}$" }), Null()]),
17132
17371
  data_recovery: Literal("separate-required")
17133
- }, closed7)
17134
- }, closed7);
17372
+ }, closed9)
17373
+ }, closed9);
17135
17374
  var phase = Union([Literal("pending"), Literal("ready"), Literal("failed"), Literal("cleaned")]);
17136
17375
  var previewId = String2({ pattern: "^[a-f0-9-]{8,64}$" });
17137
17376
  var name = String2({ minLength: 1, maxLength: 256 });
@@ -17141,7 +17380,7 @@ var ApplicationPreviewReceiptSchema2 = _Object_({
17141
17380
  ...scope2,
17142
17381
  preview_id: previewId,
17143
17382
  release_id: ApplicationReleaseIdSchema2,
17144
- expires_at: Union([timestamp2, Null()]),
17383
+ expires_at: Union([timestamp3, Null()]),
17145
17384
  status: Union([
17146
17385
  Literal("planned"),
17147
17386
  Literal("provisioning"),
@@ -17150,35 +17389,35 @@ var ApplicationPreviewReceiptSchema2 = _Object_({
17150
17389
  Literal("cleaned")
17151
17390
  ]),
17152
17391
  resources: _Object_({
17153
- build_artifact: _Object_({ status: phase, release_id: ApplicationReleaseIdSchema2 }, closed7),
17392
+ build_artifact: _Object_({ status: phase, release_id: ApplicationReleaseIdSchema2 }, closed9),
17154
17393
  database_branch: _Object_({
17155
17394
  status: phase,
17156
17395
  branch_ref: ref5,
17157
17396
  data_mode: Union([Literal("schema_only"), Literal("full_clone")])
17158
- }, closed7),
17159
- queue_namespace: _Object_({ status: phase, namespace: name }, closed7),
17160
- storage_namespace: _Object_({ status: phase, namespace: name }, closed7),
17161
- test_secret: _Object_({ status: phase, name, value_issued: Literal(false) }, closed7),
17162
- configuration_revision: _Object_({ status: phase, configuration_id: Union([ApplicationConfigurationIdSchema2, Null()]) }, closed7),
17163
- application_activation: _Object_({ status: phase, activation_id: nullableUuid }, closed7),
17164
- smoke_test: _Object_({ status: phase, checks, passed: checks, failed: checks }, closed7)
17165
- }, closed7),
17397
+ }, closed9),
17398
+ queue_namespace: _Object_({ status: phase, namespace: name }, closed9),
17399
+ storage_namespace: _Object_({ status: phase, namespace: name }, closed9),
17400
+ test_secret: _Object_({ status: phase, name, value_issued: Literal(false) }, closed9),
17401
+ configuration_revision: _Object_({ status: phase, configuration_id: Union([ApplicationConfigurationIdSchema2, Null()]) }, closed9),
17402
+ application_activation: _Object_({ status: phase, activation_id: nullableUuid }, closed9),
17403
+ smoke_test: _Object_({ status: phase, checks, passed: checks, failed: checks }, closed9)
17404
+ }, closed9),
17166
17405
  cleanup: _Object_({
17167
17406
  required: Boolean2(),
17168
17407
  completed: Boolean2(),
17169
17408
  error: Union([String2({ pattern: "^[A-Z][A-Z0-9_]{0,63}$" }), Null()])
17170
- }, closed7),
17409
+ }, closed9),
17171
17410
  branch_name: Optional(String2({ minLength: 1, maxLength: 80 })),
17172
17411
  queue_name: Optional(name),
17173
17412
  test_secret_name: Optional(name),
17174
17413
  source_configuration_id: Optional(Union([ApplicationConfigurationIdSchema2, Null()])),
17175
- created_at: Optional(timestamp2),
17176
- updated_at: Optional(timestamp2)
17177
- }, closed7);
17414
+ created_at: Optional(timestamp3),
17415
+ updated_at: Optional(timestamp3)
17416
+ }, closed9);
17178
17417
  var previewListSchema = _Object_({
17179
17418
  ...scope2,
17180
17419
  previews: _Array_(ApplicationPreviewReceiptSchema2, { maxItems: 1000 })
17181
- }, closed7);
17420
+ }, closed9);
17182
17421
  function assertScope(value, identity) {
17183
17422
  if (value.project_ref !== identity.project_ref || value.application_id !== identity.application_id || value.environment_id !== identity.environment_id)
17184
17423
  throw new Error("Application workflow scope mismatch");
@@ -17372,14 +17611,14 @@ var actionFields = {
17372
17611
  reconcile_preview: ["preview_id"],
17373
17612
  cleanup_preview: ["preview_id"]
17374
17613
  };
17375
- function timestamp3(value) {
17614
+ function timestamp4(value) {
17376
17615
  return Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value;
17377
17616
  }
17378
17617
  function receipt(value, identity) {
17379
17618
  if (!Check2(receiptSchema, value) || value.project_ref !== identity.ref || value.application_id !== identity.id || value.environment_id !== identity.environment || identity.previewId && value.preview_id !== identity.previewId || value.resources.build_artifact.release_id !== value.release_id || value.resources.storage_namespace.namespace !== value.resources.database_branch.branch_ref) {
17380
17619
  throw new Error("Invalid preview receipt");
17381
17620
  }
17382
- if (value.expires_at !== undefined && value.expires_at !== null && !timestamp3(value.expires_at) || value.created_at !== undefined && !timestamp3(value.created_at) || value.updated_at !== undefined && !timestamp3(value.updated_at) || value.expires_at !== undefined && value.expires_at !== null && value.created_at !== undefined && !Check2(ttlSecondsSchema, (Date.parse(value.expires_at) - Date.parse(value.created_at)) / 1000)) {
17621
+ if (value.expires_at !== undefined && value.expires_at !== null && !timestamp4(value.expires_at) || value.created_at !== undefined && !timestamp4(value.created_at) || value.updated_at !== undefined && !timestamp4(value.updated_at) || value.expires_at !== undefined && value.expires_at !== null && value.created_at !== undefined && !Check2(ttlSecondsSchema, (Date.parse(value.expires_at) - Date.parse(value.created_at)) / 1000)) {
17383
17622
  throw new Error("Invalid preview expiry");
17384
17623
  }
17385
17624
  if (value.status === "ready") {
@@ -21106,22 +21345,22 @@ var starter_metadata_default = {
21106
21345
  generatedBy: "supacloud/starter-metadata-v1",
21107
21346
  packages: {
21108
21347
  compiler: {
21109
- version: "0.46.0"
21348
+ version: "0.46.1"
21110
21349
  },
21111
21350
  app: {
21112
- version: "0.26.1",
21351
+ version: "0.27.0",
21113
21352
  dependencies: {
21114
21353
  rxjs: "7.8.2"
21115
21354
  }
21116
21355
  },
21117
21356
  elysia: {
21118
- version: "0.29.2"
21357
+ version: "0.30.0"
21119
21358
  },
21120
21359
  commands: {
21121
21360
  version: "0.9.2"
21122
21361
  },
21123
21362
  contracts: {
21124
- version: "0.8.1"
21363
+ version: "0.9.0"
21125
21364
  },
21126
21365
  db: {
21127
21366
  version: "0.17.0",
@@ -26168,7 +26407,7 @@ import {
26168
26407
  reverseDatabase
26169
26408
  } from "@supacloud/db";
26170
26409
  import { parseDatabaseSourcesConfig } from "@supacloud/db/source-contracts";
26171
- var hash3 = (content) => createHash7("sha256").update(content).digest("hex");
26410
+ var hash4 = (content) => createHash7("sha256").update(content).digest("hex");
26172
26411
  var result = (value, isError = false) => ({
26173
26412
  isError,
26174
26413
  content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
@@ -26299,7 +26538,7 @@ async function initializeCandidate(stage, majorVersion = 17) {
26299
26538
  await mkdir6(join14(stage, "supabase/migrations"), { recursive: true });
26300
26539
  await mkdir6(join14(stage, "supabase/schemas"), { recursive: true });
26301
26540
  await writeFile5(join14(stage, "supabase/config.toml"), [
26302
- `project_id = "supacloud-candidate-${hash3(stage).slice(0, 12)}"`,
26541
+ `project_id = "supacloud-candidate-${hash4(stage).slice(0, 12)}"`,
26303
26542
  "[db]",
26304
26543
  `major_version = ${majorVersion}`,
26305
26544
  "[db.migrations]",
@@ -26427,7 +26666,7 @@ async function migrations(root, path) {
26427
26666
  const files = [];
26428
26667
  for (const file of names) {
26429
26668
  const text = await readFile5(await projectPath2(root, `${path}/${file}`), "utf8");
26430
- files.push({ file, text, sha256: hash3(text) });
26669
+ files.push({ file, text, sha256: hash4(text) });
26431
26670
  }
26432
26671
  return { dir, files };
26433
26672
  }
@@ -26457,7 +26696,7 @@ async function migrationAction(args, root, options) {
26457
26696
  files: input.files.map(({ file, sha256 }) => ({ file, sha256 })),
26458
26697
  dryRun
26459
26698
  };
26460
- const digest = hash3(JSON.stringify(report));
26699
+ const digest = hash4(JSON.stringify(report));
26461
26700
  if (dryRun.isError)
26462
26701
  return result({ ...report, ok: false, digest, executionPerformed: false }, true);
26463
26702
  if (args.action === "plan")
@@ -28074,7 +28313,7 @@ async function requireProjectDeploymentProtocol(http, projectRef, environmentId)
28074
28313
  throw new Error("DEPLOYMENT_PROTOCOL_MISMATCH: Upgrade the SupaCloud server and CLI together (`npm install -g @supacloud/cli@latest`), then retry `supacloud deploy`. No upload or deployment was attempted; legacy endpoints will not be used.");
28075
28314
  }
28076
28315
  }
28077
- var operation = "applications.project_deploy";
28316
+ var operation2 = "applications.project_deploy";
28078
28317
  var scopeSchema = _Object_({
28079
28318
  project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
28080
28319
  application_id: ApplicationIdSchema,
@@ -28123,7 +28362,7 @@ async function runProjectDeployment(http, args) {
28123
28362
  ...args.web_release === undefined ? {} : { web_release: args.web_release }
28124
28363
  };
28125
28364
  if (!Check2(scopeSchema, scope) || !Check2(ApplicationDeployRequestSchema, request) || request.configuration_id !== undefined && request.configuration_write !== undefined && request.configuration_id !== request.configuration_write.configuration_id) {
28126
- return releaseControlFailure(operation, "INVALID_RESPONSE", null);
28365
+ return releaseControlFailure(operation2, "INVALID_RESPONSE", null);
28127
28366
  }
28128
28367
  const expected = { ...scope, request };
28129
28368
  const identity = {
@@ -28141,13 +28380,13 @@ async function runProjectDeployment(http, args) {
28141
28380
  }, { timeoutMs: 120000, maxJsonBytes: 131072, responseTimeoutMs: 30000 });
28142
28381
  if (result.ok && result.status === 200) {
28143
28382
  try {
28144
- return releaseControlSuccess(operation, {
28383
+ return releaseControlSuccess(operation2, {
28145
28384
  ...responseReceipt(result.data, expected),
28146
28385
  deployment_id: mutation_id
28147
28386
  });
28148
28387
  } catch {}
28149
28388
  } else if (!result.ok && !result.transportError && !result.responseReadError && result.status < 500 && result.status !== 408) {
28150
- return releaseControlMutationFailure(operation, result, identity);
28389
+ return releaseControlMutationFailure(operation2, result, identity);
28151
28390
  }
28152
28391
  const observed = await http.get(`${endpoint}/${encodeURIComponent(mutation_id)}`, {
28153
28392
  retry: false,
@@ -28161,14 +28400,14 @@ async function runProjectDeployment(http, args) {
28161
28400
  if (state.deployment_id !== mutation_id || state.project_ref !== scope.project_ref || state.application_id !== scope.application_id || state.environment_id !== scope.environment_id || state.status !== "succeeded" || state.phase !== "verifying")
28162
28401
  throw new Error;
28163
28402
  const receipt = parseApplicationDeployResult(state.receipt, expected);
28164
- return releaseControlSuccess(operation, {
28403
+ return releaseControlSuccess(operation2, {
28165
28404
  ...receipt,
28166
28405
  deployment_id: mutation_id,
28167
28406
  replayed: true,
28168
28407
  execution_performed: false
28169
28408
  });
28170
28409
  } catch {
28171
- return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.transportError ? null : result.status, identity);
28410
+ return releaseControlFailure(operation2, "OUTCOME_UNKNOWN", result.transportError ? null : result.status, identity);
28172
28411
  }
28173
28412
  }
28174
28413
 
@@ -28186,6 +28425,7 @@ var deployToolSchema = {
28186
28425
  ref: optional(String2(), "Project ref (defaults to the linked project)"),
28187
28426
  cwd: optional(String2(), "Project directory (default: current directory)"),
28188
28427
  skip_build: optional(Boolean2(), "Use an existing output directory without building"),
28428
+ assets_only: optional(Boolean2(), "Publish only configured static assets; leave backend Functions, schedules and migrations unchanged"),
28189
28429
  json: optional(Boolean2(), "Print only the final JSON result")
28190
28430
  };
28191
28431
  function record4(candidate) {
@@ -28280,6 +28520,7 @@ function deployTargetConfig(candidate, name) {
28280
28520
  type: value.type,
28281
28521
  root: optionalText(value.root, `targets.${name}.root`),
28282
28522
  id: optionalText(value.id, `targets.${name}.id`),
28523
+ name: optionalText(value.name, `targets.${name}.name`),
28283
28524
  slug: optionalText(value.slug, `targets.${name}.slug`),
28284
28525
  buildCommand: optionalText(value.buildCommand, `targets.${name}.buildCommand`),
28285
28526
  outputDirectory: optionalText(value.outputDirectory, `targets.${name}.outputDirectory`),
@@ -28330,6 +28571,7 @@ async function readDeployConfig(configRoot) {
28330
28571
  targets: targetValues ? Object.fromEntries(Object.entries(targetValues).map(([name, value]) => [name, deployTargetConfig(value, name)])) : undefined,
28331
28572
  frontend: frontend ? {
28332
28573
  id: optionalText(frontend.id, "frontend.id"),
28574
+ name: optionalText(frontend.name, "frontend.name"),
28333
28575
  root: optionalText(frontend.root, "frontend.root"),
28334
28576
  buildCommand: optionalText(frontend.buildCommand, "frontend.buildCommand"),
28335
28577
  outputDirectory: optionalText(frontend.outputDirectory, "frontend.outputDirectory"),
@@ -28392,13 +28634,22 @@ function deploymentList(candidate) {
28392
28634
  throw new Error("Invalid frontend deployment list response");
28393
28635
  return values.map(frontendDeployment);
28394
28636
  }
28395
- function selectDeployment(deployments, requestedId, projectName) {
28637
+ function selectDeployment(deployments, requestedId, projectName, requestedName) {
28396
28638
  if (requestedId) {
28397
28639
  const selected = deployments.find((deployment) => deployment.id === requestedId);
28398
28640
  if (!selected)
28399
28641
  throw new Error(`Frontend deployment '${requestedId}' was not found`);
28642
+ if (requestedName && selected.name !== requestedName) {
28643
+ throw new Error(`Frontend deployment '${requestedId}' does not match name '${requestedName}'`);
28644
+ }
28400
28645
  return selected;
28401
28646
  }
28647
+ if (requestedName) {
28648
+ const matches = deployments.filter((deployment) => deployment.name === requestedName);
28649
+ if (matches.length !== 1)
28650
+ throw new Error(`Expected exactly one frontend deployment named '${requestedName}'`);
28651
+ return matches[0];
28652
+ }
28402
28653
  if (deployments.length === 1)
28403
28654
  return deployments[0];
28404
28655
  if (projectName) {
@@ -28416,6 +28667,7 @@ function selectFrontendTarget(configRoot, config) {
28416
28667
  type: "frontend",
28417
28668
  root: config.frontend?.root,
28418
28669
  id: config.frontend?.id,
28670
+ name: config.frontend?.name,
28419
28671
  buildCommand: config.frontend?.buildCommand,
28420
28672
  outputDirectory: config.frontend?.outputDirectory,
28421
28673
  buildEnv: config.frontend?.buildEnv
@@ -28580,7 +28832,7 @@ function payload(response) {
28580
28832
  throw new Error("Deployment operation returned an invalid response");
28581
28833
  return parsed;
28582
28834
  }
28583
- async function stageApplicationWebRelease(http, projectRef, environmentId, configRoot, skipBuild, json, environmentVariables) {
28835
+ async function stageApplicationWebRelease(http, projectRef, environmentId, configRoot, skipBuild, json, environmentVariables, assetsOnly = false) {
28584
28836
  const target = selectFrontendTarget(configRoot, await readDeployConfig(configRoot));
28585
28837
  if (!target)
28586
28838
  return null;
@@ -28593,7 +28845,7 @@ async function stageApplicationWebRelease(http, projectRef, environmentId, confi
28593
28845
  const listResponse = await http.get(`/v1/projects/${encodeURIComponent(projectRef)}/frontend/deployments`);
28594
28846
  if (!listResponse.ok)
28595
28847
  throw new Error(`Failed to list frontend deployments (HTTP ${listResponse.status})`);
28596
- const selected = selectDeployment(deploymentList(listResponse.data), requestedId, await packageName(projectDirectory));
28848
+ const selected = selectDeployment(deploymentList(listResponse.data), requestedId, await packageName(projectDirectory), target.config.name);
28597
28849
  const configuredBuildCommand = String(target.config.buildCommand || selected.buildCommand || "").trim();
28598
28850
  const buildCommand = configuredBuildCommand || (skipBuild ? "" : await defaultBuildCommand(projectDirectory, configRoot));
28599
28851
  const configuredOutput = String(target.config.outputDirectory || "").trim();
@@ -28606,6 +28858,9 @@ async function stageApplicationWebRelease(http, projectRef, environmentId, confi
28606
28858
  }
28607
28859
  const archive = await createFrontendArchive(outputDirectory);
28608
28860
  try {
28861
+ if (assetsOnly) {
28862
+ return { result: await publishFrontendRelease(http, projectRef, selected.id, archive.archivePath, archive.treeSha256) };
28863
+ }
28609
28864
  const uploaded = payload(await uploadProjectWebRelease(http, projectRef, environmentId, selected.id, archive.archivePath));
28610
28865
  const release = record4(uploaded.release);
28611
28866
  const releaseId = requiredString(release?.release_id, "release.release_id");
@@ -28635,7 +28890,23 @@ function registerDeployTools(server, http, options = {}) {
28635
28890
  ...config.application,
28636
28891
  environmentId: options.environment || config.application.environmentId
28637
28892
  } : undefined;
28638
- if (await hasProjectReleaseManifest(configRoot)) {
28893
+ const legacyManifest = await hasProjectReleaseManifest(configRoot);
28894
+ const assetsOnly = args.assets_only === true || !application?.id && selectFrontendTarget(configRoot, config) !== null && !legacyManifest && !Object.values(config.targets ?? {}).some((target) => target.type === "edge_function");
28895
+ if (assetsOnly) {
28896
+ if (!selectFrontendTarget(configRoot, config)) {
28897
+ throw new Error("Static asset deployment requires a frontend configuration in supacloud.json");
28898
+ }
28899
+ const environmentId = options.environment?.trim() || application?.environmentId?.trim();
28900
+ if (!environmentId || !Check2(ApplicationIdSchema, environmentId)) {
28901
+ throw new Error("Static asset deployment requires SUPACLOUD_ENV");
28902
+ }
28903
+ await requireProjectDeploymentProtocol(http, projectRef, environmentId);
28904
+ const staged = await stageApplicationWebRelease(http, projectRef, environmentId, configRoot, args.skip_build === true, args.json === true, options.environmentVariables, true);
28905
+ if (!staged?.result)
28906
+ throw new Error("Static asset deployment did not produce a receipt");
28907
+ return staged.result;
28908
+ }
28909
+ if (legacyManifest) {
28639
28910
  throw new Error(`${DEPLOYMENT_UPGRADE} Replace deploy-manifest.json with the current application delivery configuration; no remote mutation was performed.`);
28640
28911
  }
28641
28912
  if (application?.id) {
@@ -28963,7 +29234,7 @@ var TEST_PROFILE = [
28963
29234
  "SUPACLOUD_API_URL=https://management.test.example.com",
28964
29235
  "SUPACLOUD_API_TOKEN=<test-management-api-token>",
28965
29236
  "SUPACLOUD_PROJECT_REF=<test-project-ref>",
28966
- "SUPACLOUD_APPLICATION_ID=<application-id>",
29237
+ "# Optional for executable application delivery: SUPACLOUD_APPLICATION_ID=<application-id>",
28967
29238
  ""
28968
29239
  ].join(`
28969
29240
  `);
@@ -28972,7 +29243,7 @@ var PRODUCTION_PROFILE = [
28972
29243
  "SUPACLOUD_API_URL=https://management.example.com",
28973
29244
  "SUPACLOUD_API_TOKEN=<production-management-api-token>",
28974
29245
  "SUPACLOUD_PROJECT_REF=<production-project-ref>",
28975
- "SUPACLOUD_APPLICATION_ID=<application-id>",
29246
+ "# Optional for executable application delivery: SUPACLOUD_APPLICATION_ID=<application-id>",
28976
29247
  ""
28977
29248
  ].join(`
28978
29249
  `);
@@ -29096,7 +29367,7 @@ async function initializeProject(request, options) {
29096
29367
  },
29097
29368
  next: [
29098
29369
  "cp .env.supacloud.test.example .env.supacloud.test",
29099
- "Set SUPACLOUD_APPLICATION_ID to the application's ID and configure its current SupaCloud delivery build.",
29370
+ "Configure frontend assets; set SUPACLOUD_APPLICATION_ID only for executable application delivery.",
29100
29371
  "supacloud env check",
29101
29372
  "supacloud --env test deploy"
29102
29373
  ]
@@ -29144,12 +29415,12 @@ function statusMissing(context) {
29144
29415
  }
29145
29416
  return ["SUPACLOUD_API_URL", "SUPACLOUD_API_TOKEN", "SUPACLOUD_PROJECT_REF"];
29146
29417
  }
29147
- function deployMissing(context, application) {
29418
+ function deployMissing(context, application, hasFrontend = false) {
29148
29419
  const missing = statusMissing(context);
29149
29420
  if (context.credentialScope !== "management") {
29150
29421
  return [...missing, "Management API context"];
29151
29422
  }
29152
- if (!Check2(ApplicationIdSchema, context.applicationId || application?.id)) {
29423
+ if (!(hasFrontend && !context.applicationId && !application) && !Check2(ApplicationIdSchema, context.applicationId || application?.id)) {
29153
29424
  missing.push("valid SUPACLOUD_APPLICATION_ID or supacloud.json application.id");
29154
29425
  }
29155
29426
  if (!Check2(ApplicationIdSchema, context.applicationEnvironmentId || application?.environmentId)) {
@@ -29169,7 +29440,8 @@ async function inspectProfile(profile) {
29169
29440
  throw error;
29170
29441
  });
29171
29442
  const config = record5(JSON.parse(configText));
29172
- const deploy = deployMissing(context, record5(config?.application));
29443
+ const hasFrontend = record5(config?.frontend) !== null || Object.values(record5(config?.targets) ?? {}).some((target) => record5(target)?.type === "frontend");
29444
+ const deploy = deployMissing(context, record5(config?.application), hasFrontend);
29173
29445
  return {
29174
29446
  name: profile.name,
29175
29447
  path: profile.path,
@@ -29265,7 +29537,7 @@ function registerDeveloperExperienceTools(server, options = {}) {
29265
29537
  // package.json
29266
29538
  var package_default = {
29267
29539
  name: "@supacloud/cli",
29268
- version: "0.96.0",
29540
+ version: "0.96.2",
29269
29541
  description: "Project-scoped CLI for SupaCloud users",
29270
29542
  type: "module",
29271
29543
  main: "./dist/index.js",
@@ -29317,14 +29589,14 @@ var package_default = {
29317
29589
  directory: "packages/cli"
29318
29590
  },
29319
29591
  dependencies: {
29320
- "@supacloud/compiler": "^0.46.0",
29321
- "@supacloud/delivery": "0.17.0",
29592
+ "@supacloud/compiler": "^0.46.1",
29593
+ "@supacloud/delivery": "0.18.0",
29322
29594
  "@supacloud/db": "0.17.0",
29323
29595
  typebox: "1.3.36"
29324
29596
  },
29325
29597
  overrides: {
29326
- "@supacloud/contracts": "0.8.1",
29327
- "@supacloud/delivery": "0.17.0",
29598
+ "@supacloud/contracts": "0.9.0",
29599
+ "@supacloud/delivery": "0.18.0",
29328
29600
  "@graphql-tools/utils": "^12.0.3"
29329
29601
  },
29330
29602
  devDependencies: {
@@ -1,2 +1,2 @@
1
- export declare const DEPLOYMENT_UPGRADE = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment is no longer supported. Upgrade with `npm install -g @supacloud/cli@latest`, bind application.id and application.environmentId in supacloud.json (or SUPACLOUD_APPLICATION_ID and SUPACLOUD_ENV), then run `supacloud deploy`. SupaCloud owns deployment planning and activation; do not retry with legacy commands.";
1
+ export declare const DEPLOYMENT_UPGRADE = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment commands are no longer supported. Upgrade with `npm install -g @supacloud/cli@latest`, configure frontend in supacloud.json for static assets, or application.id and application.environmentId for executable application delivery, then run `supacloud deploy`. Use `supacloud deploy --assets_only` to publish only Web assets in a mixed repository. SupaCloud owns activation; do not retry with legacy commands.";
2
2
  export declare function assertCurrentDeploymentInput(tool: string, input: unknown): void;
@@ -26,6 +26,7 @@ export declare const deployToolSchema: {
26
26
  ref: Type.TOptional<Type.TString>;
27
27
  cwd: Type.TOptional<Type.TString>;
28
28
  skip_build: Type.TOptional<Type.TBoolean>;
29
+ assets_only: Type.TOptional<Type.TBoolean>;
29
30
  json: Type.TOptional<Type.TBoolean>;
30
31
  };
31
32
  export declare function findDeployConfigRoot(startDirectory: string, environmentName?: string): Promise<string>;
@@ -15,7 +15,7 @@ export declare const environmentToolSchema: ToolSchema;
15
15
  declare function outputDirectoryFor(manifest: PackageManifest): string;
16
16
  declare function profileNameFromFile(name: string): string | null;
17
17
  declare function statusMissing(context: ResolvedContext): string[];
18
- declare function deployMissing(context: ResolvedContext, application?: Record<string, unknown> | null): string[];
18
+ declare function deployMissing(context: ResolvedContext, application?: Record<string, unknown> | null, hasFrontend?: boolean): string[];
19
19
  export declare function registerDeveloperExperienceTools(server: ToolServer, options?: DeveloperExperienceOptions): void;
20
20
  export declare const __internal: {
21
21
  outputDirectoryFor: typeof outputDirectoryFor;
@@ -46,6 +46,7 @@ export declare function uploadProjectWebRelease(http: FrontendReleaseHttp, proje
46
46
  export declare function uploadFrontendSource(http: FrontendReleaseHttp, projectRef: string, deploymentId: string, archivePath: string): Promise<ToolResponse>;
47
47
  export declare function getActiveFrontendRelease(http: FrontendReleaseHttp, projectRef: string, deploymentId: string): Promise<ToolResponse>;
48
48
  export declare function readFrontendReleaseAuthority(http: FrontendReleaseHttp, projectRef: string, deploymentId: string): Promise<ToolResponse>;
49
+ export declare function publishFrontendRelease(http: FrontendReleaseHttp, projectRef: string, deploymentId: string, archivePath: string, expectedTreeSha256: string): Promise<ToolResponse>;
49
50
  export declare function rollbackFrontendRelease(http: FrontendReleaseHttp, projectRef: string, deploymentId: string, releaseId?: string): Promise<ToolResponse>;
50
51
  export declare function activateFrontendRelease(http: FrontendReleaseHttp, input: {
51
52
  projectRef: string;
@@ -131,7 +131,7 @@ import { Type as Type2 } from "typebox";
131
131
  import { Value as Value2 } from "typebox/value";
132
132
 
133
133
  // src/shared/deployment-upgrade.ts
134
- var DEPLOYMENT_UPGRADE = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment is no longer supported. Upgrade with `npm install -g @supacloud/cli@latest`, bind application.id and application.environmentId in supacloud.json (or SUPACLOUD_APPLICATION_ID and SUPACLOUD_ENV), then run `supacloud deploy`. SupaCloud owns deployment planning and activation; do not retry with legacy commands.";
134
+ var DEPLOYMENT_UPGRADE = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment commands are no longer supported. Upgrade with `npm install -g @supacloud/cli@latest`, configure frontend in supacloud.json for static assets, or application.id and application.environmentId for executable application delivery, then run `supacloud deploy`. Use `supacloud deploy --assets_only` to publish only Web assets in a mixed repository. SupaCloud owns activation; do not retry with legacy commands.";
135
135
  var removedFrontendActions = new Set([
136
136
  "deploy_git",
137
137
  "deploy_upload",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/cli",
3
- "version": "0.96.0",
3
+ "version": "0.96.2",
4
4
  "description": "Project-scoped CLI for SupaCloud users",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -52,14 +52,14 @@
52
52
  "directory": "packages/cli"
53
53
  },
54
54
  "dependencies": {
55
- "@supacloud/compiler": "^0.46.0",
56
- "@supacloud/delivery": "0.17.0",
55
+ "@supacloud/compiler": "^0.46.1",
56
+ "@supacloud/delivery": "0.18.0",
57
57
  "@supacloud/db": "0.17.0",
58
58
  "typebox": "1.3.36"
59
59
  },
60
60
  "overrides": {
61
- "@supacloud/contracts": "0.8.1",
62
- "@supacloud/delivery": "0.17.0",
61
+ "@supacloud/contracts": "0.9.0",
62
+ "@supacloud/delivery": "0.18.0",
63
63
  "@graphql-tools/utils": "^12.0.3"
64
64
  },
65
65
  "devDependencies": {