@supacloud/cli 0.93.0 → 0.95.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 +23 -32
- package/dist/index.js +195 -549
- package/dist/shared/deployment-upgrade.d.ts +2 -0
- package/dist/shared/tools/app-starter-database.d.ts +1 -1
- package/dist/shared/tools/app-starter-reactive.d.ts +2 -2
- package/dist/shared/tools/application-tools.d.ts +1 -1
- package/dist/shared/tools/deploy-tools.d.ts +0 -8
- package/dist/shared/tools/developer-experience-tools.d.ts +1 -1
- package/dist/shared/tools/project-deployment.d.ts +1 -0
- package/dist/shared/tools/remote-dev-tools.d.ts +1 -1
- package/dist/tool-runtime.js +25 -0
- package/package.json +3 -3
- package/skills/supacloud/SKILL.md +9 -0
- package/skills/supacloud/references/command-map.md +3 -5
package/dist/index.js
CHANGED
|
@@ -8766,6 +8766,28 @@ function outcomeUnknownGuidance(text) {
|
|
|
8766
8766
|
保持原 --env/--env-file 选择,先查询:${command}` : "");
|
|
8767
8767
|
}
|
|
8768
8768
|
|
|
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.";
|
|
8771
|
+
var removedFrontendActions = new Set([
|
|
8772
|
+
"deploy_git",
|
|
8773
|
+
"deploy_upload",
|
|
8774
|
+
"redeploy",
|
|
8775
|
+
"upload_release",
|
|
8776
|
+
"activate_release"
|
|
8777
|
+
]);
|
|
8778
|
+
var removedDeployFlags = ["target", "id", "build_command", "output_dir", "plan", "diff", "dry_run"];
|
|
8779
|
+
function assertCurrentDeploymentInput(tool, input) {
|
|
8780
|
+
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
8781
|
+
return;
|
|
8782
|
+
const args = input;
|
|
8783
|
+
if (tool === "frontend" && typeof args["action"] === "string" && removedFrontendActions.has(args["action"])) {
|
|
8784
|
+
throw new Error(DEPLOYMENT_UPGRADE);
|
|
8785
|
+
}
|
|
8786
|
+
if (tool === "deploy" && removedDeployFlags.some((flag) => Object.hasOwn(args, flag))) {
|
|
8787
|
+
throw new Error(`${DEPLOYMENT_UPGRADE} Put build settings in the frontend configuration. For read-only review use \`supacloud app deploy-plan\`.`);
|
|
8788
|
+
}
|
|
8789
|
+
}
|
|
8790
|
+
|
|
8769
8791
|
// src/shared/cli.ts
|
|
8770
8792
|
function cliToolResultIsError(toolResult) {
|
|
8771
8793
|
if (toolResult.isError === true)
|
|
@@ -8889,6 +8911,7 @@ async function runCli(cliTools, args, options = {}) {
|
|
|
8889
8911
|
const parsedArgs = parseCliFlags(args, startIdx, tool.schema);
|
|
8890
8912
|
if (startIdx === 2)
|
|
8891
8913
|
parsedArgs.action = args[1];
|
|
8914
|
+
assertCurrentDeploymentInput(args[0], parsedArgs);
|
|
8892
8915
|
validateToolArguments(tool.schema, parsedArgs);
|
|
8893
8916
|
const result = await tool.callback(parsedArgs);
|
|
8894
8917
|
if (result && result.content && Array.isArray(result.content)) {
|
|
@@ -11188,6 +11211,7 @@ var resultSchema = _Object_({
|
|
|
11188
11211
|
});
|
|
11189
11212
|
function registerTool(server, name, description, schema, callback) {
|
|
11190
11213
|
server.tool(name, description, schema, async (input) => {
|
|
11214
|
+
assertCurrentDeploymentInput(name, input);
|
|
11191
11215
|
const args = parseToolArguments(schema, input);
|
|
11192
11216
|
const result = await callback(args);
|
|
11193
11217
|
if (!Check2(resultSchema, result))
|
|
@@ -16319,39 +16343,6 @@ async function getFrontendRelease(http, projectRef, deploymentId, releaseId) {
|
|
|
16319
16343
|
}
|
|
16320
16344
|
return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release });
|
|
16321
16345
|
}
|
|
16322
|
-
async function uploadFrontendRelease(http, projectRef, deploymentId, archivePath) {
|
|
16323
|
-
const endpoint = releaseEndpoint(projectRef, deploymentId);
|
|
16324
|
-
const archive = await verifiedArchive(archivePath);
|
|
16325
|
-
let response;
|
|
16326
|
-
try {
|
|
16327
|
-
response = await http.postBinary(endpoint, {
|
|
16328
|
-
stream: archiveStream(archive),
|
|
16329
|
-
byteLength: archive.sizeBytes
|
|
16330
|
-
}, {
|
|
16331
|
-
contentType: FRONTEND_ARCHIVE_CONTENT_TYPE,
|
|
16332
|
-
contentLength: archive.sizeBytes,
|
|
16333
|
-
contentSha256: archive.sha256,
|
|
16334
|
-
maxJsonBytes: RESPONSE_MAX_BYTES,
|
|
16335
|
-
timeoutMs: UPLOAD_REQUEST_TIMEOUT_MS,
|
|
16336
|
-
responseTimeoutMs: MUTATION_RESPONSE_TIMEOUT_MS
|
|
16337
|
-
});
|
|
16338
|
-
} finally {
|
|
16339
|
-
await archive.handle.close();
|
|
16340
|
-
}
|
|
16341
|
-
const release = response.ok ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId: archive.sha256 }) : null;
|
|
16342
|
-
if (!release) {
|
|
16343
|
-
if (response.status >= 400 && response.status < 500 && response.status !== 408 && !response.transportError) {
|
|
16344
|
-
return releaseFailure("frontend.upload_release", "HTTP_ERROR", response.status);
|
|
16345
|
-
}
|
|
16346
|
-
return uploadReadback(http, projectRef, deploymentId, archive.sha256, response.status);
|
|
16347
|
-
}
|
|
16348
|
-
const readback = await http.get(`${endpoint}/${release.release_id}`, { maxJsonBytes: RESPONSE_MAX_BYTES });
|
|
16349
|
-
const verified = readback.ok ? releaseEnvelope(readback.data, { projectRef, deploymentId, releaseId: release.release_id }) : null;
|
|
16350
|
-
if (!verified || verified.tree_sha256 !== release.tree_sha256) {
|
|
16351
|
-
return releaseFailure("frontend.upload_release", "OUTCOME_UNKNOWN", readback.status);
|
|
16352
|
-
}
|
|
16353
|
-
return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release: verified });
|
|
16354
|
-
}
|
|
16355
16346
|
async function uploadProjectWebRelease(http, projectRef, environmentId, deploymentId, archivePath) {
|
|
16356
16347
|
const endpoint = `/v1/projects/${encodeURIComponent(projectRef)}/environments/${encodeURIComponent(environmentId)}/deployments/web-release?deployment_id=${encodeURIComponent(deploymentId)}`;
|
|
16357
16348
|
const archive = await verifiedArchive(archivePath);
|
|
@@ -16406,41 +16397,6 @@ async function uploadProjectWebRelease(http, projectRef, environmentId, deployme
|
|
|
16406
16397
|
await archive.handle.close();
|
|
16407
16398
|
}
|
|
16408
16399
|
}
|
|
16409
|
-
async function uploadFrontendSource(http, projectRef, deploymentId, archivePath) {
|
|
16410
|
-
const endpoint = `${deploymentEndpoint(projectRef, deploymentId)}/deploy/upload`;
|
|
16411
|
-
const archive = await verifiedArchive(archivePath);
|
|
16412
|
-
try {
|
|
16413
|
-
const response = await http.postBinary(endpoint, {
|
|
16414
|
-
stream: archiveStream(archive),
|
|
16415
|
-
byteLength: archive.sizeBytes
|
|
16416
|
-
}, {
|
|
16417
|
-
contentType: FRONTEND_ARCHIVE_CONTENT_TYPE,
|
|
16418
|
-
contentLength: archive.sizeBytes,
|
|
16419
|
-
contentSha256: archive.sha256,
|
|
16420
|
-
maxJsonBytes: RESPONSE_MAX_BYTES,
|
|
16421
|
-
timeoutMs: UPLOAD_REQUEST_TIMEOUT_MS
|
|
16422
|
-
});
|
|
16423
|
-
if (!response.ok) {
|
|
16424
|
-
return releaseFailure("frontend.deploy_upload", response.status >= 400 && response.status < 500 ? "HTTP_ERROR" : "OUTCOME_UNKNOWN", response.status);
|
|
16425
|
-
}
|
|
16426
|
-
if (!response.data || typeof response.data !== "object" || !("success" in response.data) || response.data.success !== true) {
|
|
16427
|
-
return releaseFailure("frontend.deploy_upload", "INVALID_RESPONSE", response.status);
|
|
16428
|
-
}
|
|
16429
|
-
return toolResponse(response.data);
|
|
16430
|
-
} finally {
|
|
16431
|
-
await archive.handle.close();
|
|
16432
|
-
}
|
|
16433
|
-
}
|
|
16434
|
-
async function uploadReadback(http, projectRef, deploymentId, releaseId, uploadStatus) {
|
|
16435
|
-
const response = await http.get(releasePath(projectRef, deploymentId, releaseId), {
|
|
16436
|
-
maxJsonBytes: RESPONSE_MAX_BYTES
|
|
16437
|
-
});
|
|
16438
|
-
const release = response.ok ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId }) : null;
|
|
16439
|
-
if (!release) {
|
|
16440
|
-
return releaseFailure("frontend.upload_release", "OUTCOME_UNKNOWN", uploadStatus);
|
|
16441
|
-
}
|
|
16442
|
-
return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release });
|
|
16443
|
-
}
|
|
16444
16400
|
function stableJson(candidate) {
|
|
16445
16401
|
if (candidate === null || typeof candidate !== "object")
|
|
16446
16402
|
return JSON.stringify(candidate);
|
|
@@ -16518,9 +16474,6 @@ async function activeReleaseReadback(http, identity) {
|
|
|
16518
16474
|
if (inventory.active_release_id !== identity.releaseId || inventory.active_activation_id !== identity.mutationId) {
|
|
16519
16475
|
return { release: null, status: 200 };
|
|
16520
16476
|
}
|
|
16521
|
-
if (snapshot.exactReadback) {
|
|
16522
|
-
return { release: inventory.releases[0] ?? null, status: 200 };
|
|
16523
|
-
}
|
|
16524
16477
|
const releaseRead = await http.get(releasePath(identity.projectRef, identity.deploymentId, identity.releaseId), { maxJsonBytes: RESPONSE_MAX_BYTES });
|
|
16525
16478
|
const release = releaseRead.ok ? releaseEnvelope(releaseRead.data, {
|
|
16526
16479
|
projectRef: identity.projectRef,
|
|
@@ -16538,43 +16491,31 @@ async function readActiveFrontendRelease(http, projectRef, deploymentId) {
|
|
|
16538
16491
|
if (inventory.next_cursor !== null || inventory.releases.length !== (inventory.active_release_id === null ? 0 : 1) || inventory.releases[0] && inventory.releases[0].release_id !== inventory.active_release_id) {
|
|
16539
16492
|
return { failure: releaseReadFailure("frontend.get_active_release", response), status: response.status };
|
|
16540
16493
|
}
|
|
16541
|
-
return { inventory
|
|
16542
|
-
}
|
|
16543
|
-
if (response.ok || response.status !== 404) {
|
|
16544
|
-
return { failure: releaseReadFailure("frontend.get_active_release", response), status: response.status };
|
|
16494
|
+
return { inventory };
|
|
16545
16495
|
}
|
|
16546
|
-
|
|
16547
|
-
maxJsonBytes: RESPONSE_MAX_BYTES
|
|
16548
|
-
});
|
|
16549
|
-
const history = historyResponse.ok && historyResponse.status === 200 ? releaseInventory(historyResponse.data, { projectRef, deploymentId }) : null;
|
|
16550
|
-
if (!history || history.releases.length > 1) {
|
|
16496
|
+
if (response.status === 404) {
|
|
16551
16497
|
return {
|
|
16552
|
-
failure:
|
|
16553
|
-
|
|
16554
|
-
|
|
16555
|
-
|
|
16556
|
-
|
|
16557
|
-
|
|
16558
|
-
|
|
16559
|
-
|
|
16560
|
-
|
|
16561
|
-
|
|
16562
|
-
|
|
16563
|
-
|
|
16564
|
-
|
|
16565
|
-
failure: releaseReadFailure("frontend.get_active_release", exactResponse),
|
|
16566
|
-
status: exactResponse.status
|
|
16498
|
+
failure: {
|
|
16499
|
+
isError: true,
|
|
16500
|
+
content: [{ type: "text", text: JSON.stringify({
|
|
16501
|
+
ok: false,
|
|
16502
|
+
operation: "frontend.get_active_release",
|
|
16503
|
+
error: {
|
|
16504
|
+
code: "DEPLOYMENT_UPGRADE_REQUIRED",
|
|
16505
|
+
http_status: 404,
|
|
16506
|
+
message: `${DEPLOYMENT_UPGRADE} Check that the deployment exists and upgrade the server if this endpoint is unavailable.`
|
|
16507
|
+
}
|
|
16508
|
+
}) }]
|
|
16509
|
+
},
|
|
16510
|
+
status: response.status
|
|
16567
16511
|
};
|
|
16568
16512
|
}
|
|
16569
|
-
return {
|
|
16513
|
+
return { failure: releaseReadFailure("frontend.get_active_release", response), status: response.status };
|
|
16570
16514
|
}
|
|
16571
16515
|
async function getActiveFrontendRelease(http, projectRef, deploymentId) {
|
|
16572
16516
|
const snapshot = await readActiveFrontendRelease(http, projectRef, deploymentId);
|
|
16573
16517
|
return "failure" in snapshot ? snapshot.failure : toolResponse(snapshot.inventory);
|
|
16574
16518
|
}
|
|
16575
|
-
async function readFrontendReleaseAuthority(http, projectRef, deploymentId) {
|
|
16576
|
-
return getActiveFrontendRelease(http, projectRef, deploymentId);
|
|
16577
|
-
}
|
|
16578
16519
|
async function rollbackFrontendRelease(http, projectRef, deploymentId, releaseId) {
|
|
16579
16520
|
if (releaseId !== undefined && !RELEASE_ID_PATTERN.test(releaseId)) {
|
|
16580
16521
|
throw new Error("'release_id' must be a SHA-256 digest");
|
|
@@ -16670,7 +16611,6 @@ async function readPreviousFrontendRelease(http, projectRef, deploymentId) {
|
|
|
16670
16611
|
releases: [],
|
|
16671
16612
|
next_cursor: null
|
|
16672
16613
|
},
|
|
16673
|
-
exactReadback: false,
|
|
16674
16614
|
...previous ? { previousRelease: previous } : {}
|
|
16675
16615
|
};
|
|
16676
16616
|
}
|
|
@@ -16740,16 +16680,13 @@ async function activationReadback(http, input, mutationId, activationStatus) {
|
|
|
16740
16680
|
// src/shared/tools/frontend-tools.ts
|
|
16741
16681
|
function registerFrontendTools(server, http) {
|
|
16742
16682
|
registerTool(server, "frontend", `Frontend hosting and immutable prebuilt releases. Supports: static, react, vue, svelte, sveltekit, sveltekit-static, nextjs, nuxt, astro.
|
|
16743
|
-
Actions: list, get, create, update, delete,
|
|
16683
|
+
Actions: list, get, create, update, delete, build_logs, add_domain, remove_domain, set_env, list_frameworks, list_records, list_releases, get_active_release, get_release, rollback. Publish with supacloud deploy.`, {
|
|
16744
16684
|
action: withDescription(stringEnum([
|
|
16745
16685
|
"list",
|
|
16746
16686
|
"get",
|
|
16747
16687
|
"create",
|
|
16748
16688
|
"update",
|
|
16749
16689
|
"delete",
|
|
16750
|
-
"deploy_git",
|
|
16751
|
-
"deploy_upload",
|
|
16752
|
-
"redeploy",
|
|
16753
16690
|
"build_logs",
|
|
16754
16691
|
"add_domain",
|
|
16755
16692
|
"remove_domain",
|
|
@@ -16759,8 +16696,6 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16759
16696
|
"list_releases",
|
|
16760
16697
|
"get_active_release",
|
|
16761
16698
|
"get_release",
|
|
16762
|
-
"upload_release",
|
|
16763
|
-
"activate_release",
|
|
16764
16699
|
"rollback"
|
|
16765
16700
|
]), "Action"),
|
|
16766
16701
|
ref: optional(String2(), "Project ref"),
|
|
@@ -16774,13 +16709,7 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16774
16709
|
node_version: optional(String2(), "[create/update] Node.js version"),
|
|
16775
16710
|
health_check_path: optional(String2(), "[create/update] SSR readiness path (default: /)"),
|
|
16776
16711
|
env_vars: optional(Record(String2(), String2()), "[create/update/set_env] Environment variables"),
|
|
16777
|
-
|
|
16778
|
-
branch: optional(String2(), "[deploy_git] Branch (default: main)"),
|
|
16779
|
-
archive_path: optional(String2(), "[deploy_upload/upload_release] Local tar.zst file path"),
|
|
16780
|
-
release_id: optional(String2(), "[get_release/activate_release] SHA-256 release ID; [rollback] optional, defaults to journal-verified previous release"),
|
|
16781
|
-
expected_active_release_id: optional(String2(), "[activate_release] Current release SHA-256 or absent"),
|
|
16782
|
-
expected_activation_id: optional(String2(), "[activate_release] Current activation UUIDv4 or absent"),
|
|
16783
|
-
mutation_id: optional(String2(), "[activate_release] Required retry-stable UUIDv4"),
|
|
16712
|
+
release_id: optional(String2(), "[get_release] SHA-256 release ID; [rollback] optional, defaults to journal-verified previous release"),
|
|
16784
16713
|
cursor: optional(String2(), "[list_releases] Last release SHA-256 cursor"),
|
|
16785
16714
|
limit: optional(Number2(), "[list_releases] Page size, 1-100 (default 50)")
|
|
16786
16715
|
}, async (args) => {
|
|
@@ -16797,13 +16726,7 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16797
16726
|
node_version,
|
|
16798
16727
|
health_check_path,
|
|
16799
16728
|
env_vars,
|
|
16800
|
-
git_url,
|
|
16801
|
-
branch,
|
|
16802
|
-
archive_path,
|
|
16803
16729
|
release_id,
|
|
16804
|
-
expected_active_release_id,
|
|
16805
|
-
expected_activation_id,
|
|
16806
|
-
mutation_id,
|
|
16807
16730
|
cursor,
|
|
16808
16731
|
limit
|
|
16809
16732
|
} = args;
|
|
@@ -16858,22 +16781,6 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16858
16781
|
need("id", id);
|
|
16859
16782
|
text = (await http.delete(`/v1/projects/${ref}/frontend/deployments/${id}`)).ok ? `✅ Deleted` : `❌ Failed`;
|
|
16860
16783
|
break;
|
|
16861
|
-
case "deploy_git":
|
|
16862
|
-
need("ref", ref);
|
|
16863
|
-
need("id", id);
|
|
16864
|
-
need("git_url", git_url);
|
|
16865
|
-
text = ok(await http.post(`/v1/projects/${ref}/frontend/deployments/${id}/deploy/git`, { git_url, branch }));
|
|
16866
|
-
break;
|
|
16867
|
-
case "deploy_upload":
|
|
16868
|
-
need("ref", ref);
|
|
16869
|
-
need("id", id);
|
|
16870
|
-
need("archive_path", archive_path);
|
|
16871
|
-
return uploadFrontendSource(http, ref, id, archive_path);
|
|
16872
|
-
case "redeploy":
|
|
16873
|
-
need("ref", ref);
|
|
16874
|
-
need("id", id);
|
|
16875
|
-
text = ok(await http.post(`/v1/projects/${ref}/frontend/deployments/${id}/redeploy`));
|
|
16876
|
-
break;
|
|
16877
16784
|
case "build_logs":
|
|
16878
16785
|
need("ref", ref);
|
|
16879
16786
|
need("id", id);
|
|
@@ -16919,26 +16826,6 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16919
16826
|
need("ref", ref);
|
|
16920
16827
|
need("id", id);
|
|
16921
16828
|
return getActiveFrontendRelease(http, ref, id);
|
|
16922
|
-
case "upload_release":
|
|
16923
|
-
need("ref", ref);
|
|
16924
|
-
need("id", id);
|
|
16925
|
-
need("archive_path", archive_path);
|
|
16926
|
-
return uploadFrontendRelease(http, ref, id, archive_path);
|
|
16927
|
-
case "activate_release":
|
|
16928
|
-
need("ref", ref);
|
|
16929
|
-
need("id", id);
|
|
16930
|
-
need("release_id", release_id);
|
|
16931
|
-
need("expected_active_release_id", expected_active_release_id);
|
|
16932
|
-
need("expected_activation_id", expected_activation_id);
|
|
16933
|
-
need("mutation_id", mutation_id);
|
|
16934
|
-
return activateFrontendRelease(http, {
|
|
16935
|
-
projectRef: ref,
|
|
16936
|
-
deploymentId: id,
|
|
16937
|
-
releaseId: release_id,
|
|
16938
|
-
expectedActiveReleaseId: expected_active_release_id,
|
|
16939
|
-
expectedActivationId: expected_activation_id,
|
|
16940
|
-
mutationId: mutation_id
|
|
16941
|
-
});
|
|
16942
16829
|
case "rollback":
|
|
16943
16830
|
need("ref", ref);
|
|
16944
16831
|
need("id", id);
|
|
@@ -21212,7 +21099,7 @@ var starter_metadata_default = {
|
|
|
21212
21099
|
generatedBy: "supacloud/starter-metadata-v1",
|
|
21213
21100
|
packages: {
|
|
21214
21101
|
compiler: {
|
|
21215
|
-
version: "0.
|
|
21102
|
+
version: "0.45.0"
|
|
21216
21103
|
},
|
|
21217
21104
|
app: {
|
|
21218
21105
|
version: "0.26.1",
|
|
@@ -21230,7 +21117,7 @@ var starter_metadata_default = {
|
|
|
21230
21117
|
version: "0.8.1"
|
|
21231
21118
|
},
|
|
21232
21119
|
db: {
|
|
21233
|
-
version: "0.16.
|
|
21120
|
+
version: "0.16.2",
|
|
21234
21121
|
peerDependencies: {
|
|
21235
21122
|
"drizzle-orm": "1.0.0-rc.5-169397b"
|
|
21236
21123
|
},
|
|
@@ -21250,15 +21137,18 @@ var starter_metadata_default = {
|
|
|
21250
21137
|
// src/shared/tools/app-starter-reactive.ts
|
|
21251
21138
|
var STARTER_REACTIVE_GUIDE = `# Reactive development / 响应式开发
|
|
21252
21139
|
|
|
21253
|
-
RxJS is
|
|
21254
|
-
|
|
21140
|
+
RxJS is the default and only reactive event library in the starter ecosystem.
|
|
21141
|
+
Ordinary queries and business commands still use async/await. Use RxJS for
|
|
21142
|
+
ongoing events and timing/composition, not as a new
|
|
21255
21143
|
transaction, retry or durable-delivery system.
|
|
21256
21144
|
|
|
21257
21145
|
Host defaults:
|
|
21258
21146
|
- In a native Angular host, use signal/resource APIs from @supacloud/app/angular
|
|
21259
21147
|
and Angular's scheduler. Do not mix them with the legacy root signal graph.
|
|
21260
21148
|
- In framework-neutral code, use async/await for one result and RxJS for event
|
|
21261
|
-
composition.
|
|
21149
|
+
composition. Raw continuous protocols use AsyncIterable unless an existing
|
|
21150
|
+
RxJS/Angular boundary is the better fit. The host owns cancellation through
|
|
21151
|
+
an explicit signal.
|
|
21262
21152
|
|
|
21263
21153
|
- Import native operators from rxjs; do not invent another event/operator library.
|
|
21264
21154
|
- Import takeUntilAborted / toReadableStream from @supacloud/app/reactive.
|
|
@@ -21307,7 +21197,9 @@ Read README.md and REACTIVE.md before adding asynchronous features. If the
|
|
|
21307
21197
|
application is hosted by Angular, read the @supacloud/app/angular guidance
|
|
21308
21198
|
before choosing a signal API.
|
|
21309
21199
|
Prefer the generated contracts and existing project-bound @supacloud/js client.
|
|
21310
|
-
Use async/await for a single result; RxJS is the default event-composition
|
|
21200
|
+
Use async/await for a single result; RxJS is the default event-composition
|
|
21201
|
+
library. Do not introduce another reactive library without a documented special
|
|
21202
|
+
requirement and equivalent lifecycle tests.
|
|
21311
21203
|
Bind subscriptions to an explicit owner and propagate cancellation to native I/O.
|
|
21312
21204
|
Never automatically retry a write or turn observable delivery into durable ack.
|
|
21313
21205
|
Do not bypass authorization, transactions, idempotency or audit to simplify code.
|
|
@@ -23121,6 +23013,12 @@ After installing dependencies, run \`bun run db:generate\` once and commit db/co
|
|
|
23121
23013
|
The default \`bun run check\` and build fail on stale database contracts before any
|
|
23122
23014
|
compiler regeneration. After an intentional source change, run db:generate again,
|
|
23123
23015
|
review the diff, then run check. Ordinary checks are offline.
|
|
23016
|
+
The compiler also runs this source-contract gate on compile/check/dev through
|
|
23017
|
+
databaseGovernance.mode = "check", including incremental cache hits. Missing
|
|
23018
|
+
adoption files or stale contracts fail closed; no contracts are silently regenerated.
|
|
23019
|
+
This is not SQL lint or live Catalog reconciliation. Before promotion, declare
|
|
23020
|
+
the real database modules, their SQL and tests, then explicitly use mode "enforce"
|
|
23021
|
+
with a separately selected read-only local/test database connection.
|
|
23124
23022
|
|
|
23125
23023
|
- Maintain one schema-qualified function with explicit grants per db/functions/*.sql.
|
|
23126
23024
|
- Preserve migrations/ and its existing executor/ledger. Add forward migrations only.
|
|
@@ -23270,6 +23168,7 @@ export default defineSupacloudConfig({
|
|
|
23270
23168
|
outDir: "generated",
|
|
23271
23169
|
strict: true,
|
|
23272
23170
|
moduleBoundaryPreset: "modular-monolith",
|
|
23171
|
+
databaseGovernance: { mode: "check" },
|
|
23273
23172
|
effect: {
|
|
23274
23173
|
requireRouteEffects: true,
|
|
23275
23174
|
requireErrorMappings: true,
|
|
@@ -28108,6 +28007,117 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
28108
28007
|
import { createHash as createHash9 } from "node:crypto";
|
|
28109
28008
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
28110
28009
|
import { basename as basename8, dirname as dirname11, join as join17, relative as relative10, resolve as resolve22, sep as sep5 } from "node:path";
|
|
28010
|
+
|
|
28011
|
+
// src/shared/tools/project-deployment.ts
|
|
28012
|
+
async function requireProjectDeploymentProtocol(http, projectRef, environmentId) {
|
|
28013
|
+
const response = await http.get(`/v1/projects/${encodeURIComponent(projectRef)}/environments/${encodeURIComponent(environmentId)}/deployments/protocol`, { retry: false, totalTimeoutMs: 5000, maxJsonBytes: 4096 });
|
|
28014
|
+
if (response.transportError || response.responseReadError || response.status >= 500 || response.status === 401 || response.status === 403 || response.status === 429) {
|
|
28015
|
+
throw new Error(`DEPLOYMENT_PROTOCOL_UNAVAILABLE: Cannot verify the selected server (HTTP ${response.status}). Check connectivity, credentials and server health; no upload or deployment was attempted.`);
|
|
28016
|
+
}
|
|
28017
|
+
const data = response.data;
|
|
28018
|
+
if (response.status !== 200 || !response.ok || !data || typeof data !== "object" || !("protocol" in data) || data.protocol !== "supacloud.project-deployment.v1" || !("project_ref" in data) || data.project_ref !== projectRef || !("environment_id" in data) || data.environment_id !== environmentId) {
|
|
28019
|
+
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.");
|
|
28020
|
+
}
|
|
28021
|
+
}
|
|
28022
|
+
var operation = "applications.project_deploy";
|
|
28023
|
+
var scopeSchema = _Object_({
|
|
28024
|
+
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
28025
|
+
application_id: ApplicationIdSchema,
|
|
28026
|
+
environment_id: ApplicationIdSchema
|
|
28027
|
+
});
|
|
28028
|
+
var statusSchema = _Object_({
|
|
28029
|
+
schema: Literal("supacloud.project-deployment-status.v1"),
|
|
28030
|
+
deployment_id: ApplicationDeployRequestSchema.properties.mutation_id,
|
|
28031
|
+
status: Union([
|
|
28032
|
+
Literal("pending"),
|
|
28033
|
+
Literal("running"),
|
|
28034
|
+
Literal("succeeded"),
|
|
28035
|
+
Literal("failed_retryable"),
|
|
28036
|
+
Literal("failed_terminal"),
|
|
28037
|
+
Literal("outcome_unknown")
|
|
28038
|
+
]),
|
|
28039
|
+
phase: Union([
|
|
28040
|
+
Literal("queued"),
|
|
28041
|
+
Literal("prepared"),
|
|
28042
|
+
Literal("migrating"),
|
|
28043
|
+
Literal("activating"),
|
|
28044
|
+
Literal("binding-web"),
|
|
28045
|
+
Literal("verifying")
|
|
28046
|
+
]),
|
|
28047
|
+
operation: Literal("application.release.deploy"),
|
|
28048
|
+
...scopeSchema.properties,
|
|
28049
|
+
receipt: Optional(Unknown()),
|
|
28050
|
+
failure_code: Optional(String2({ pattern: "^[A-Z][A-Z0-9_]{0,63}$" }))
|
|
28051
|
+
}, { additionalProperties: false });
|
|
28052
|
+
function responseReceipt(data, expected) {
|
|
28053
|
+
if (!data || typeof data !== "object" || Array.isArray(data) || !("ok" in data) || data.ok !== true) {
|
|
28054
|
+
throw new Error("Invalid project deployment response");
|
|
28055
|
+
}
|
|
28056
|
+
const { ok: _ok, ...receipt } = data;
|
|
28057
|
+
return parseApplicationDeployResult(receipt, expected);
|
|
28058
|
+
}
|
|
28059
|
+
async function runProjectDeployment(http, args) {
|
|
28060
|
+
const scope = { project_ref: args.ref, application_id: args.id, environment_id: args.environment_id };
|
|
28061
|
+
const request = {
|
|
28062
|
+
mutation_id: args.mutation_id,
|
|
28063
|
+
release_id: args.release_id,
|
|
28064
|
+
...args.configuration_id === undefined ? {} : { configuration_id: args.configuration_id },
|
|
28065
|
+
...args.configuration_write === undefined ? {} : { configuration_write: args.configuration_write },
|
|
28066
|
+
...args.expected_plan_sha256 === undefined ? {} : { expected_plan_sha256: args.expected_plan_sha256 },
|
|
28067
|
+
...args.approved_migration_digest === undefined ? {} : { approved_migration_digest: args.approved_migration_digest },
|
|
28068
|
+
...args.web_release === undefined ? {} : { web_release: args.web_release }
|
|
28069
|
+
};
|
|
28070
|
+
if (!Check2(scopeSchema, scope) || !Check2(ApplicationDeployRequestSchema, request) || request.configuration_id !== undefined && request.configuration_write !== undefined && request.configuration_id !== request.configuration_write.configuration_id) {
|
|
28071
|
+
return releaseControlFailure(operation, "INVALID_RESPONSE", null);
|
|
28072
|
+
}
|
|
28073
|
+
const expected = { ...scope, request };
|
|
28074
|
+
const identity = {
|
|
28075
|
+
...scope,
|
|
28076
|
+
deployment_id: request.mutation_id,
|
|
28077
|
+
mutation_id: request.mutation_id,
|
|
28078
|
+
release_id: request.release_id
|
|
28079
|
+
};
|
|
28080
|
+
const endpoint = `/v1/projects/${encodeURIComponent(scope.project_ref)}/environments/${encodeURIComponent(scope.environment_id)}/deployments`;
|
|
28081
|
+
const { mutation_id, ...candidate } = request;
|
|
28082
|
+
const result = await http.post(endpoint, {
|
|
28083
|
+
...candidate,
|
|
28084
|
+
deployment_id: mutation_id,
|
|
28085
|
+
application_id: scope.application_id
|
|
28086
|
+
}, { timeoutMs: 120000, maxJsonBytes: 131072, responseTimeoutMs: 30000 });
|
|
28087
|
+
if (result.ok && result.status === 200) {
|
|
28088
|
+
try {
|
|
28089
|
+
return releaseControlSuccess(operation, {
|
|
28090
|
+
...responseReceipt(result.data, expected),
|
|
28091
|
+
deployment_id: mutation_id
|
|
28092
|
+
});
|
|
28093
|
+
} catch {}
|
|
28094
|
+
} else if (!result.ok && !result.transportError && !result.responseReadError && result.status < 500 && result.status !== 408) {
|
|
28095
|
+
return releaseControlMutationFailure(operation, result, identity);
|
|
28096
|
+
}
|
|
28097
|
+
const observed = await http.get(`${endpoint}/${encodeURIComponent(mutation_id)}`, {
|
|
28098
|
+
retry: false,
|
|
28099
|
+
totalTimeoutMs: 30000,
|
|
28100
|
+
maxJsonBytes: 131072
|
|
28101
|
+
});
|
|
28102
|
+
try {
|
|
28103
|
+
if (!observed.ok || observed.status !== 200 || !Check2(statusSchema, observed.data))
|
|
28104
|
+
throw new Error;
|
|
28105
|
+
const state = observed.data;
|
|
28106
|
+
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")
|
|
28107
|
+
throw new Error;
|
|
28108
|
+
const receipt = parseApplicationDeployResult(state.receipt, expected);
|
|
28109
|
+
return releaseControlSuccess(operation, {
|
|
28110
|
+
...receipt,
|
|
28111
|
+
deployment_id: mutation_id,
|
|
28112
|
+
replayed: true,
|
|
28113
|
+
execution_performed: false
|
|
28114
|
+
});
|
|
28115
|
+
} catch {
|
|
28116
|
+
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.transportError ? null : result.status, identity);
|
|
28117
|
+
}
|
|
28118
|
+
}
|
|
28119
|
+
|
|
28120
|
+
// src/shared/tools/deploy-tools.ts
|
|
28111
28121
|
var MAX_SOURCE_BYTES = 256 * 1024 * 1024;
|
|
28112
28122
|
var PUBLIC_BUILD_ENV_PREFIXES = ["PUBLIC_", "VITE_", "NEXT_PUBLIC_", "NUXT_PUBLIC_", "ASTRO_PUBLIC_"];
|
|
28113
28123
|
var SENSITIVE_BUILD_ENV = /(?:^|_)(?:PASSWORD|PASS|SECRET|TOKEN|KEY|CREDENTIAL|AUTHORIZATION|COOKIE|SESSION)(?:_|$)|(?:DATABASE_URL|DATABASE_URI|CONNECTION_STRING|DSN|PRIVATE_KEY)/i;
|
|
@@ -28119,15 +28129,8 @@ function isProtectedBuildEnv(name) {
|
|
|
28119
28129
|
}
|
|
28120
28130
|
var deployToolSchema = {
|
|
28121
28131
|
ref: optional(String2(), "Project ref (defaults to the linked project)"),
|
|
28122
|
-
target: optional(String2(), "Named deploy target from supacloud.json"),
|
|
28123
|
-
id: optional(String2(), "Frontend deployment ID (auto-selected when unambiguous)"),
|
|
28124
28132
|
cwd: optional(String2(), "Project directory (default: current directory)"),
|
|
28125
|
-
build_command: optional(String2(), "Build command override"),
|
|
28126
|
-
output_dir: optional(String2(), "Build output directory override"),
|
|
28127
28133
|
skip_build: optional(Boolean2(), "Use an existing output directory without building"),
|
|
28128
|
-
dry_run: optional(Boolean2(), "Resolve and validate the deployment without building or publishing"),
|
|
28129
|
-
plan: optional(Boolean2(), "Build and compare the release with current authority without publishing"),
|
|
28130
|
-
diff: optional(Boolean2(), "Build and report the immutable release-level diff without publishing"),
|
|
28131
28134
|
json: optional(Boolean2(), "Print only the final JSON result")
|
|
28132
28135
|
};
|
|
28133
28136
|
function record4(candidate) {
|
|
@@ -28386,40 +28389,6 @@ function targetRoot(configRoot, target, name) {
|
|
|
28386
28389
|
}
|
|
28387
28390
|
return root;
|
|
28388
28391
|
}
|
|
28389
|
-
function selectTarget(configRoot, invocationDirectory, config, requestedName) {
|
|
28390
|
-
const targets = config.targets ? Object.entries(config.targets) : [["frontend", {
|
|
28391
|
-
type: "frontend",
|
|
28392
|
-
root: config.frontend?.root,
|
|
28393
|
-
id: config.frontend?.id,
|
|
28394
|
-
buildCommand: config.frontend?.buildCommand,
|
|
28395
|
-
outputDirectory: config.frontend?.outputDirectory,
|
|
28396
|
-
buildEnv: config.frontend?.buildEnv
|
|
28397
|
-
}]];
|
|
28398
|
-
if (targets.length === 0)
|
|
28399
|
-
throw new Error("supacloud.json defines no deploy targets");
|
|
28400
|
-
if (requestedName) {
|
|
28401
|
-
const selected = targets.find(([name]) => name === requestedName);
|
|
28402
|
-
if (!selected)
|
|
28403
|
-
throw new Error(`Deploy target '${requestedName}' was not found in supacloud.json`);
|
|
28404
|
-
return { name: selected[0], config: selected[1], root: targetRoot(configRoot, selected[1], selected[0]) };
|
|
28405
|
-
}
|
|
28406
|
-
const containing = targets.map(([name, target]) => ({ name, target, root: targetRoot(configRoot, target, name) })).filter((candidate) => invocationDirectory === candidate.root || invocationDirectory.startsWith(`${candidate.root}${sep5}`)).sort((left, right) => right.root.length - left.root.length);
|
|
28407
|
-
if (containing.length === 1 || containing.length > 1 && containing[0].root !== containing[1].root) {
|
|
28408
|
-
const selected = containing[0];
|
|
28409
|
-
return { name: selected.name, config: selected.target, root: selected.root };
|
|
28410
|
-
}
|
|
28411
|
-
if (config.defaultTarget) {
|
|
28412
|
-
const selected = targets.find(([name]) => name === config.defaultTarget);
|
|
28413
|
-
if (!selected)
|
|
28414
|
-
throw new Error(`supacloud.json defaultTarget '${config.defaultTarget}' was not found`);
|
|
28415
|
-
return { name: selected[0], config: selected[1], root: targetRoot(configRoot, selected[1], selected[0]) };
|
|
28416
|
-
}
|
|
28417
|
-
if (targets.length === 1) {
|
|
28418
|
-
const selected = targets[0];
|
|
28419
|
-
return { name: selected[0], config: selected[1], root: targetRoot(configRoot, selected[1], selected[0]) };
|
|
28420
|
-
}
|
|
28421
|
-
throw new Error(`Multiple deploy targets found (${targets.map(([name]) => name).sort().join(", ")}). Pass --target`);
|
|
28422
|
-
}
|
|
28423
28392
|
function defaultOutputDirectory(framework) {
|
|
28424
28393
|
switch (framework) {
|
|
28425
28394
|
case "sveltekit-static":
|
|
@@ -28599,24 +28568,8 @@ async function stageApplicationWebRelease(http, projectRef, environmentId, confi
|
|
|
28599
28568
|
await archive.cleanup();
|
|
28600
28569
|
}
|
|
28601
28570
|
}
|
|
28602
|
-
function deployResponse(result, json) {
|
|
28603
|
-
if (json)
|
|
28604
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
28605
|
-
const lines = [
|
|
28606
|
-
result.unchanged === true ? "Already up to date." : `Deployed ${String(result.target || result.deployment_id || result.slug)}.`,
|
|
28607
|
-
result.url ? `URL: ${String(result.url)}` : null,
|
|
28608
|
-
result.release_id ? `Release: ${String(result.release_id)}` : null,
|
|
28609
|
-
result.active_version ? `Active version: ${String(result.active_version)}` : null,
|
|
28610
|
-
result.file_count ? `Files: ${String(result.file_count)}` : null
|
|
28611
|
-
].filter((line) => Boolean(line));
|
|
28612
|
-
return { content: [{ type: "text", text: lines.join(`
|
|
28613
|
-
`) }] };
|
|
28614
|
-
}
|
|
28615
28571
|
function registerDeployTools(server, http, options = {}) {
|
|
28616
28572
|
registerTool(server, "deploy", "Build and publish the linked project with one command", deployToolSchema, async (args) => {
|
|
28617
|
-
if (args.dry_run === true && (args.plan === true || args.diff === true)) {
|
|
28618
|
-
throw new Error("Use dry_run for resolution only, or plan/diff for a built release comparison, not both");
|
|
28619
|
-
}
|
|
28620
28573
|
const invocationDirectory = resolve22(String(args.cwd || options.cwd || process.cwd()));
|
|
28621
28574
|
const projectRef = String(args.ref || options.projectRef || "").trim();
|
|
28622
28575
|
if (!projectRef)
|
|
@@ -28627,8 +28580,8 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28627
28580
|
...config.application,
|
|
28628
28581
|
environmentId: options.environment || config.application.environmentId
|
|
28629
28582
|
} : undefined;
|
|
28630
|
-
if (
|
|
28631
|
-
throw new Error(
|
|
28583
|
+
if (await hasProjectReleaseManifest(configRoot)) {
|
|
28584
|
+
throw new Error(`${DEPLOYMENT_UPGRADE} Replace deploy-manifest.json with the current application delivery configuration; no remote mutation was performed.`);
|
|
28632
28585
|
}
|
|
28633
28586
|
if (application?.id) {
|
|
28634
28587
|
if (Object.values(config.targets ?? {}).some((target) => target.type === "edge_function")) {
|
|
@@ -28637,12 +28590,6 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28637
28590
|
if (!options.applicationRelease) {
|
|
28638
28591
|
throw new Error("Application release support is unavailable in this CLI context");
|
|
28639
28592
|
}
|
|
28640
|
-
if (args.target || args.build_command || args.output_dir) {
|
|
28641
|
-
throw new Error("Application profile deploy does not accept frontend target, build command, or output directory flags");
|
|
28642
|
-
}
|
|
28643
|
-
if (args.dry_run === true || args.plan === true || args.diff === true) {
|
|
28644
|
-
throw new Error("Application profile deploy does not support dry_run, plan, or diff; use app deploy-plan for a read-only plan");
|
|
28645
|
-
}
|
|
28646
28593
|
const environmentId = application.environmentId?.trim();
|
|
28647
28594
|
if (!environmentId || !Check2(ApplicationIdSchema, environmentId) || !Check2(ApplicationIdSchema, application.id)) {
|
|
28648
28595
|
throw new Error("Application profile requires SUPACLOUD_APPLICATION_ENVIRONMENT_ID or SUPACLOUD_ENV");
|
|
@@ -28652,6 +28599,7 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28652
28599
|
if (configurationPath && configurationId) {
|
|
28653
28600
|
throw new Error("Application profile must set only one of SUPACLOUD_APPLICATION_CONFIGURATION_PATH or SUPACLOUD_APPLICATION_CONFIGURATION_ID");
|
|
28654
28601
|
}
|
|
28602
|
+
await requireProjectDeploymentProtocol(http, projectRef, environmentId);
|
|
28655
28603
|
const stagedWeb = await stageApplicationWebRelease(http, projectRef, environmentId, configRoot, args.skip_build === true, args.json === true, options.environmentVariables);
|
|
28656
28604
|
const result = await options.applicationRelease({
|
|
28657
28605
|
action: "release",
|
|
@@ -28668,215 +28616,7 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28668
28616
|
});
|
|
28669
28617
|
return result;
|
|
28670
28618
|
}
|
|
28671
|
-
|
|
28672
|
-
if (!args.target && target.config.type === "frontend" && (Object.values(config.targets ?? {}).some((candidate) => candidate.type === "edge_function") || await pathExists(join17(configRoot, "supacloud.config.ts")) || await pathExists(join17(configRoot, "supabase", "migrations")) || await pathExists(join17(configRoot, "supabase", "functions")))) {
|
|
28673
|
-
throw new Error("PROJECT_DEPLOYMENT_UNSUPPORTED: Backend declarations were detected but are not covered by this deployment. No Web-only fallback or remote mutation was performed.");
|
|
28674
|
-
}
|
|
28675
|
-
const projectDirectory = target.root;
|
|
28676
|
-
const targetState = await lstat5(projectDirectory).catch(() => null);
|
|
28677
|
-
if (!targetState?.isDirectory() || targetState.isSymbolicLink()) {
|
|
28678
|
-
throw new Error(`Deploy target '${target.name}' root is not a regular directory: ${projectDirectory}`);
|
|
28679
|
-
}
|
|
28680
|
-
const requestedId = String(args.id || target.config.id || "").trim() || undefined;
|
|
28681
|
-
const build = createBuildEnvironment(target.config.buildEnv, options.environmentVariables);
|
|
28682
|
-
if (target.config.type === "edge_function") {
|
|
28683
|
-
if (args.diff === true)
|
|
28684
|
-
throw new Error("Function release diffs require an immutable function release manifest");
|
|
28685
|
-
if (!options.edgeFunctionDeploy)
|
|
28686
|
-
throw new Error("Edge Function deploy support is unavailable in this CLI context");
|
|
28687
|
-
const slug = target.config.slug || requestedId || target.name;
|
|
28688
|
-
const functionListResponse = await options.edgeFunctionDeploy({
|
|
28689
|
-
action: "list",
|
|
28690
|
-
ref: projectRef
|
|
28691
|
-
});
|
|
28692
|
-
if (functionListResponse.isError) {
|
|
28693
|
-
throw new Error(`Unable to read the current identity for Edge Function '${slug}'`);
|
|
28694
|
-
}
|
|
28695
|
-
const functionListText = functionListResponse.content.find((chunk) => chunk.type === "text")?.text;
|
|
28696
|
-
if (!functionListText)
|
|
28697
|
-
throw new Error(`Unable to read the current identity for Edge Function '${slug}'`);
|
|
28698
|
-
const functions = projectedFunctionList(JSON.parse(functionListText));
|
|
28699
|
-
if (!functions)
|
|
28700
|
-
throw new Error(`Invalid current identity for Edge Function '${slug}'`);
|
|
28701
|
-
const current = functions?.find((candidate) => candidate.slug === slug);
|
|
28702
|
-
const activeVersion = current && typeof current.version === "number" ? String(current.version) : "absent";
|
|
28703
|
-
const activationId = current && typeof current.activation_id === "string" ? current.activation_id : "legacy";
|
|
28704
|
-
if (!activeVersion || !activationId)
|
|
28705
|
-
throw new Error(`Edge Function '${slug}' has an invalid active identity`);
|
|
28706
|
-
const buildCommand = String(args.build_command || target.config.buildCommand || "").trim() || (args.skip_build === true ? "" : await defaultBuildCommand(projectDirectory, configRoot));
|
|
28707
|
-
const bundleDirectory = resolveInsideProject(projectDirectory, String(args.output_dir || target.config.bundleDirectory || target.config.outputDirectory || "dist"), true);
|
|
28708
|
-
if (args.dry_run === true || args.plan === true) {
|
|
28709
|
-
return { content: [{ type: "text", text: JSON.stringify({
|
|
28710
|
-
ok: true,
|
|
28711
|
-
dry_run: true,
|
|
28712
|
-
type: target.config.type,
|
|
28713
|
-
target: target.name,
|
|
28714
|
-
project_ref: projectRef,
|
|
28715
|
-
slug,
|
|
28716
|
-
build_command: args.skip_build === true ? null : buildCommand,
|
|
28717
|
-
build_env: build.names,
|
|
28718
|
-
missing_build_env: build.missing,
|
|
28719
|
-
bundle_directory: bundleDirectory,
|
|
28720
|
-
expected_active_version: activeVersion,
|
|
28721
|
-
expected_activation_id: activationId
|
|
28722
|
-
}, null, 2) }] };
|
|
28723
|
-
}
|
|
28724
|
-
assertBuildEnvironment(build, args.skip_build === true);
|
|
28725
|
-
if (args.skip_build !== true) {
|
|
28726
|
-
await runBuild(buildCommand, projectDirectory, build.env, args.json === true);
|
|
28727
|
-
}
|
|
28728
|
-
const deployed = await options.edgeFunctionDeploy({
|
|
28729
|
-
action: "deploy_bundle",
|
|
28730
|
-
ref: projectRef,
|
|
28731
|
-
slug,
|
|
28732
|
-
"bundle-dir": bundleDirectory,
|
|
28733
|
-
entrypoint: target.config.entrypoint || "index.ts",
|
|
28734
|
-
minify: target.config.minify,
|
|
28735
|
-
verify_jwt: target.config.verifyJwt,
|
|
28736
|
-
framework: target.config.framework,
|
|
28737
|
-
"expected-active-version": activeVersion,
|
|
28738
|
-
"expected-activation-id": activationId
|
|
28739
|
-
});
|
|
28740
|
-
if (deployed.isError)
|
|
28741
|
-
return deployed;
|
|
28742
|
-
const deployedText = deployed.content.find((chunk) => chunk.type === "text")?.text;
|
|
28743
|
-
const deployedPayload = deployedText ? record4(JSON.parse(deployedText)) : null;
|
|
28744
|
-
return deployResponse({
|
|
28745
|
-
ok: true,
|
|
28746
|
-
unchanged: false,
|
|
28747
|
-
type: target.config.type,
|
|
28748
|
-
target: target.name,
|
|
28749
|
-
project_ref: projectRef,
|
|
28750
|
-
slug,
|
|
28751
|
-
active_version: deployedPayload?.active_version,
|
|
28752
|
-
activation_id: deployedPayload?.activation_id
|
|
28753
|
-
}, args.json === true);
|
|
28754
|
-
}
|
|
28755
|
-
const listResponse = await http.get(`/v1/projects/${encodeURIComponent(projectRef)}/frontend/deployments`);
|
|
28756
|
-
if (!listResponse.ok)
|
|
28757
|
-
throw new Error(`Failed to list frontend deployments (HTTP ${listResponse.status})`);
|
|
28758
|
-
const selected = selectDeployment(deploymentList(listResponse.data), requestedId, await packageName(projectDirectory));
|
|
28759
|
-
const configuredBuildCommand = String(args.build_command || target.config.buildCommand || selected.buildCommand || "").trim();
|
|
28760
|
-
const buildCommand = configuredBuildCommand || (args.skip_build === true ? "" : await defaultBuildCommand(projectDirectory, configRoot));
|
|
28761
|
-
const configuredOutput = String(args.output_dir || target.config.outputDirectory || "").trim();
|
|
28762
|
-
const remoteOutput = selected.outputDirectory && selected.outputDirectory !== "." ? selected.outputDirectory : "";
|
|
28763
|
-
const outputDirectory = resolveInsideProject(projectDirectory, configuredOutput || remoteOutput || defaultOutputDirectory(selected.framework));
|
|
28764
|
-
if (args.dry_run === true) {
|
|
28765
|
-
return { content: [{ type: "text", text: JSON.stringify({
|
|
28766
|
-
ok: true,
|
|
28767
|
-
dry_run: true,
|
|
28768
|
-
project_ref: projectRef,
|
|
28769
|
-
deployment_id: selected.id,
|
|
28770
|
-
build_command: args.skip_build === true ? null : buildCommand,
|
|
28771
|
-
build_env: build.names,
|
|
28772
|
-
missing_build_env: build.missing,
|
|
28773
|
-
output_directory: outputDirectory
|
|
28774
|
-
}, null, 2) }] };
|
|
28775
|
-
}
|
|
28776
|
-
assertBuildEnvironment(build, args.skip_build === true);
|
|
28777
|
-
if (args.skip_build !== true) {
|
|
28778
|
-
await runBuild(buildCommand, projectDirectory, build.env, args.json === true);
|
|
28779
|
-
}
|
|
28780
|
-
const archive = await createFrontendArchive(outputDirectory);
|
|
28781
|
-
try {
|
|
28782
|
-
const inventory = payload(await readFrontendReleaseAuthority(http, projectRef, selected.id));
|
|
28783
|
-
const activeReleaseId = typeof inventory.active_release_id === "string" ? inventory.active_release_id : null;
|
|
28784
|
-
const activeActivationId = typeof inventory.active_activation_id === "string" ? inventory.active_activation_id : null;
|
|
28785
|
-
const current = Array.isArray(inventory.releases) ? record4(inventory.releases[0]) : null;
|
|
28786
|
-
if (archive.sha256 === activeReleaseId && archive.treeSha256 !== current?.tree_sha256) {
|
|
28787
|
-
throw new Error("Active release tree does not match the local archive");
|
|
28788
|
-
}
|
|
28789
|
-
const unchanged = archive.treeSha256 === current?.tree_sha256;
|
|
28790
|
-
if (args.plan === true || args.diff === true) {
|
|
28791
|
-
return { content: [{ type: "text", text: JSON.stringify({
|
|
28792
|
-
schema: "supacloud.frontend-deploy-plan.v1",
|
|
28793
|
-
ok: true,
|
|
28794
|
-
planned: true,
|
|
28795
|
-
published: false,
|
|
28796
|
-
unchanged,
|
|
28797
|
-
environment: options.environment ?? null,
|
|
28798
|
-
type: "frontend",
|
|
28799
|
-
target: target.name,
|
|
28800
|
-
project_ref: projectRef,
|
|
28801
|
-
deployment_id: selected.id,
|
|
28802
|
-
comparison: "immutable_release",
|
|
28803
|
-
archive_format: FRONTEND_ARCHIVE_FORMAT,
|
|
28804
|
-
release_id: archive.sha256,
|
|
28805
|
-
tree_sha256: archive.treeSha256,
|
|
28806
|
-
active_release_id: activeReleaseId,
|
|
28807
|
-
active_tree_sha256: current?.tree_sha256 ?? null,
|
|
28808
|
-
expected_active_release_id: activeReleaseId ?? "absent",
|
|
28809
|
-
expected_activation_id: activeActivationId ?? "absent",
|
|
28810
|
-
actions: unchanged ? [] : ["upload_release", "activate_release"],
|
|
28811
|
-
file_count: archive.fileCount,
|
|
28812
|
-
source_bytes: archive.sourceBytes,
|
|
28813
|
-
archive_bytes: archive.archiveBytes
|
|
28814
|
-
}, null, 2) }] };
|
|
28815
|
-
}
|
|
28816
|
-
if (unchanged) {
|
|
28817
|
-
return deployResponse({
|
|
28818
|
-
ok: true,
|
|
28819
|
-
unchanged: true,
|
|
28820
|
-
project_ref: projectRef,
|
|
28821
|
-
deployment_id: selected.id,
|
|
28822
|
-
release_id: activeReleaseId,
|
|
28823
|
-
tree_sha256: archive.treeSha256,
|
|
28824
|
-
url: selected.deploymentUrl,
|
|
28825
|
-
file_count: archive.fileCount,
|
|
28826
|
-
source_bytes: archive.sourceBytes
|
|
28827
|
-
}, args.json === true);
|
|
28828
|
-
}
|
|
28829
|
-
const uploaded = payload(await uploadFrontendRelease(http, projectRef, selected.id, archive.archivePath));
|
|
28830
|
-
const release = record4(uploaded.release);
|
|
28831
|
-
const releaseId = requiredString(release?.release_id, "release.release_id");
|
|
28832
|
-
if (releaseId !== archive.sha256)
|
|
28833
|
-
throw new Error("Uploaded release identity does not match the local archive");
|
|
28834
|
-
if (release?.tree_sha256 !== archive.treeSha256)
|
|
28835
|
-
throw new Error("Uploaded release tree does not match the local build");
|
|
28836
|
-
const mutationId = crypto.randomUUID();
|
|
28837
|
-
const activationResponse = await activateFrontendRelease(http, {
|
|
28838
|
-
projectRef,
|
|
28839
|
-
deploymentId: selected.id,
|
|
28840
|
-
releaseId,
|
|
28841
|
-
expectedActiveReleaseId: activeReleaseId || "absent",
|
|
28842
|
-
expectedActivationId: activeActivationId || "absent",
|
|
28843
|
-
mutationId
|
|
28844
|
-
});
|
|
28845
|
-
if (activationResponse.isError) {
|
|
28846
|
-
const failure = record4(JSON.parse(activationResponse.content[0]?.text ?? "{}"));
|
|
28847
|
-
return {
|
|
28848
|
-
isError: true,
|
|
28849
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
28850
|
-
...failure,
|
|
28851
|
-
operation: "deploy",
|
|
28852
|
-
project_ref: projectRef,
|
|
28853
|
-
deployment_id: selected.id,
|
|
28854
|
-
mutation_id: mutationId,
|
|
28855
|
-
target_release_id: releaseId,
|
|
28856
|
-
expected_active_release_id: activeReleaseId ?? "absent",
|
|
28857
|
-
expected_activation_id: activeActivationId ?? "absent"
|
|
28858
|
-
}) }]
|
|
28859
|
-
};
|
|
28860
|
-
}
|
|
28861
|
-
const activated = payload(activationResponse);
|
|
28862
|
-
const finalResponse = await http.get(`/v1/projects/${encodeURIComponent(projectRef)}/frontend/deployments/${encodeURIComponent(selected.id)}`);
|
|
28863
|
-
const finalDeployment = finalResponse.ok ? frontendDeployment(finalResponse.data) : selected;
|
|
28864
|
-
return deployResponse({
|
|
28865
|
-
ok: true,
|
|
28866
|
-
unchanged: false,
|
|
28867
|
-
project_ref: projectRef,
|
|
28868
|
-
deployment_id: selected.id,
|
|
28869
|
-
release_id: activated.active_release_id,
|
|
28870
|
-
activation_id: activated.activation_id,
|
|
28871
|
-
previous_release_id: activeReleaseId,
|
|
28872
|
-
previous_activation_id: activeActivationId,
|
|
28873
|
-
url: finalDeployment.deploymentUrl,
|
|
28874
|
-
file_count: archive.fileCount,
|
|
28875
|
-
source_bytes: archive.sourceBytes
|
|
28876
|
-
}, args.json === true);
|
|
28877
|
-
} finally {
|
|
28878
|
-
await archive.cleanup();
|
|
28879
|
-
}
|
|
28619
|
+
throw new Error(DEPLOYMENT_UPGRADE);
|
|
28880
28620
|
});
|
|
28881
28621
|
}
|
|
28882
28622
|
|
|
@@ -29168,6 +28908,7 @@ var TEST_PROFILE = [
|
|
|
29168
28908
|
"SUPACLOUD_API_URL=https://management.test.example.com",
|
|
29169
28909
|
"SUPACLOUD_API_TOKEN=<test-management-api-token>",
|
|
29170
28910
|
"SUPACLOUD_PROJECT_REF=<test-project-ref>",
|
|
28911
|
+
"SUPACLOUD_APPLICATION_ID=<application-id>",
|
|
29171
28912
|
""
|
|
29172
28913
|
].join(`
|
|
29173
28914
|
`);
|
|
@@ -29176,6 +28917,7 @@ var PRODUCTION_PROFILE = [
|
|
|
29176
28917
|
"SUPACLOUD_API_URL=https://management.example.com",
|
|
29177
28918
|
"SUPACLOUD_API_TOKEN=<production-management-api-token>",
|
|
29178
28919
|
"SUPACLOUD_PROJECT_REF=<production-project-ref>",
|
|
28920
|
+
"SUPACLOUD_APPLICATION_ID=<application-id>",
|
|
29179
28921
|
""
|
|
29180
28922
|
].join(`
|
|
29181
28923
|
`);
|
|
@@ -29299,6 +29041,7 @@ async function initializeProject(request, options) {
|
|
|
29299
29041
|
},
|
|
29300
29042
|
next: [
|
|
29301
29043
|
"cp .env.supacloud.test.example .env.supacloud.test",
|
|
29044
|
+
"Set SUPACLOUD_APPLICATION_ID to the application's ID and configure its current SupaCloud delivery build.",
|
|
29302
29045
|
"supacloud env check",
|
|
29303
29046
|
"supacloud --env test deploy"
|
|
29304
29047
|
]
|
|
@@ -29346,17 +29089,16 @@ function statusMissing(context) {
|
|
|
29346
29089
|
}
|
|
29347
29090
|
return ["SUPACLOUD_API_URL", "SUPACLOUD_API_TOKEN", "SUPACLOUD_PROJECT_REF"];
|
|
29348
29091
|
}
|
|
29349
|
-
function deployMissing(context) {
|
|
29092
|
+
function deployMissing(context, application) {
|
|
29350
29093
|
const missing = statusMissing(context);
|
|
29351
29094
|
if (context.credentialScope !== "management") {
|
|
29352
29095
|
return [...missing, "Management API context"];
|
|
29353
29096
|
}
|
|
29354
|
-
if (context.applicationId) {
|
|
29355
|
-
|
|
29356
|
-
|
|
29357
|
-
|
|
29358
|
-
|
|
29359
|
-
}
|
|
29097
|
+
if (!Check2(ApplicationIdSchema, context.applicationId || application?.id)) {
|
|
29098
|
+
missing.push("valid SUPACLOUD_APPLICATION_ID or supacloud.json application.id");
|
|
29099
|
+
}
|
|
29100
|
+
if (!Check2(ApplicationIdSchema, context.applicationEnvironmentId || application?.environmentId)) {
|
|
29101
|
+
missing.push("valid SUPACLOUD_APPLICATION_ENVIRONMENT_ID or SUPACLOUD_ENV");
|
|
29360
29102
|
}
|
|
29361
29103
|
return missing;
|
|
29362
29104
|
}
|
|
@@ -29366,7 +29108,13 @@ async function inspectProfile(profile) {
|
|
|
29366
29108
|
environmentName: profile.name
|
|
29367
29109
|
});
|
|
29368
29110
|
const status = statusMissing(context);
|
|
29369
|
-
const
|
|
29111
|
+
const configText = await readFile8(join19(dirname12(profile.path), "supacloud.json"), "utf8").catch((error) => {
|
|
29112
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
29113
|
+
return "{}";
|
|
29114
|
+
throw error;
|
|
29115
|
+
});
|
|
29116
|
+
const config = record5(JSON.parse(configText));
|
|
29117
|
+
const deploy = deployMissing(context, record5(config?.application));
|
|
29370
29118
|
return {
|
|
29371
29119
|
name: profile.name,
|
|
29372
29120
|
path: profile.path,
|
|
@@ -29459,109 +29207,10 @@ function registerDeveloperExperienceTools(server, options = {}) {
|
|
|
29459
29207
|
registerTool(server, "init", "Create SupaCloud deployment configuration and non-secret environment examples without overwriting project files.", initToolSchema, (request) => initializeProject(request, options));
|
|
29460
29208
|
registerTool(server, "env", "List or locally validate named SupaCloud environment profiles without contacting the platform or printing secrets.", environmentToolSchema, (request) => inspectEnvironment(request, options));
|
|
29461
29209
|
}
|
|
29462
|
-
|
|
29463
|
-
// src/shared/tools/project-deployment.ts
|
|
29464
|
-
var operation = "applications.project_deploy";
|
|
29465
|
-
var scopeSchema = _Object_({
|
|
29466
|
-
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
29467
|
-
application_id: ApplicationIdSchema,
|
|
29468
|
-
environment_id: ApplicationIdSchema
|
|
29469
|
-
});
|
|
29470
|
-
var statusSchema = _Object_({
|
|
29471
|
-
schema: Literal("supacloud.project-deployment-status.v1"),
|
|
29472
|
-
deployment_id: ApplicationDeployRequestSchema.properties.mutation_id,
|
|
29473
|
-
status: Union([
|
|
29474
|
-
Literal("pending"),
|
|
29475
|
-
Literal("running"),
|
|
29476
|
-
Literal("succeeded"),
|
|
29477
|
-
Literal("failed_retryable"),
|
|
29478
|
-
Literal("failed_terminal"),
|
|
29479
|
-
Literal("outcome_unknown")
|
|
29480
|
-
]),
|
|
29481
|
-
phase: Union([
|
|
29482
|
-
Literal("queued"),
|
|
29483
|
-
Literal("prepared"),
|
|
29484
|
-
Literal("migrating"),
|
|
29485
|
-
Literal("activating"),
|
|
29486
|
-
Literal("binding-web"),
|
|
29487
|
-
Literal("verifying")
|
|
29488
|
-
]),
|
|
29489
|
-
operation: Literal("application.release.deploy"),
|
|
29490
|
-
...scopeSchema.properties,
|
|
29491
|
-
receipt: Optional(Unknown()),
|
|
29492
|
-
failure_code: Optional(String2({ pattern: "^[A-Z][A-Z0-9_]{0,63}$" }))
|
|
29493
|
-
}, { additionalProperties: false });
|
|
29494
|
-
function responseReceipt(data, expected) {
|
|
29495
|
-
if (!data || typeof data !== "object" || Array.isArray(data) || !("ok" in data) || data.ok !== true) {
|
|
29496
|
-
throw new Error("Invalid project deployment response");
|
|
29497
|
-
}
|
|
29498
|
-
const { ok: _ok, ...receipt } = data;
|
|
29499
|
-
return parseApplicationDeployResult(receipt, expected);
|
|
29500
|
-
}
|
|
29501
|
-
async function runProjectDeployment(http, args) {
|
|
29502
|
-
const scope = { project_ref: args.ref, application_id: args.id, environment_id: args.environment_id };
|
|
29503
|
-
const request = {
|
|
29504
|
-
mutation_id: args.mutation_id,
|
|
29505
|
-
release_id: args.release_id,
|
|
29506
|
-
...args.configuration_id === undefined ? {} : { configuration_id: args.configuration_id },
|
|
29507
|
-
...args.configuration_write === undefined ? {} : { configuration_write: args.configuration_write },
|
|
29508
|
-
...args.expected_plan_sha256 === undefined ? {} : { expected_plan_sha256: args.expected_plan_sha256 },
|
|
29509
|
-
...args.approved_migration_digest === undefined ? {} : { approved_migration_digest: args.approved_migration_digest },
|
|
29510
|
-
...args.web_release === undefined ? {} : { web_release: args.web_release }
|
|
29511
|
-
};
|
|
29512
|
-
if (!Check2(scopeSchema, scope) || !Check2(ApplicationDeployRequestSchema, request) || request.configuration_id !== undefined && request.configuration_write !== undefined && request.configuration_id !== request.configuration_write.configuration_id) {
|
|
29513
|
-
return releaseControlFailure(operation, "INVALID_RESPONSE", null);
|
|
29514
|
-
}
|
|
29515
|
-
const expected = { ...scope, request };
|
|
29516
|
-
const identity = {
|
|
29517
|
-
...scope,
|
|
29518
|
-
deployment_id: request.mutation_id,
|
|
29519
|
-
mutation_id: request.mutation_id,
|
|
29520
|
-
release_id: request.release_id
|
|
29521
|
-
};
|
|
29522
|
-
const endpoint = `/v1/projects/${encodeURIComponent(scope.project_ref)}/environments/${encodeURIComponent(scope.environment_id)}/deployments`;
|
|
29523
|
-
const { mutation_id, ...candidate } = request;
|
|
29524
|
-
const result = await http.post(endpoint, {
|
|
29525
|
-
...candidate,
|
|
29526
|
-
deployment_id: mutation_id,
|
|
29527
|
-
application_id: scope.application_id
|
|
29528
|
-
}, { timeoutMs: 120000, maxJsonBytes: 131072, responseTimeoutMs: 30000 });
|
|
29529
|
-
if (result.ok && result.status === 200) {
|
|
29530
|
-
try {
|
|
29531
|
-
return releaseControlSuccess(operation, {
|
|
29532
|
-
...responseReceipt(result.data, expected),
|
|
29533
|
-
deployment_id: mutation_id
|
|
29534
|
-
});
|
|
29535
|
-
} catch {}
|
|
29536
|
-
} else if (!result.ok && !result.transportError && !result.responseReadError && result.status < 500 && result.status !== 408) {
|
|
29537
|
-
return releaseControlMutationFailure(operation, result, identity);
|
|
29538
|
-
}
|
|
29539
|
-
const observed = await http.get(`${endpoint}/${encodeURIComponent(mutation_id)}`, {
|
|
29540
|
-
retry: false,
|
|
29541
|
-
totalTimeoutMs: 30000,
|
|
29542
|
-
maxJsonBytes: 131072
|
|
29543
|
-
});
|
|
29544
|
-
try {
|
|
29545
|
-
if (!observed.ok || observed.status !== 200 || !Check2(statusSchema, observed.data))
|
|
29546
|
-
throw new Error;
|
|
29547
|
-
const state = observed.data;
|
|
29548
|
-
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")
|
|
29549
|
-
throw new Error;
|
|
29550
|
-
const receipt = parseApplicationDeployResult(state.receipt, expected);
|
|
29551
|
-
return releaseControlSuccess(operation, {
|
|
29552
|
-
...receipt,
|
|
29553
|
-
deployment_id: mutation_id,
|
|
29554
|
-
replayed: true,
|
|
29555
|
-
execution_performed: false
|
|
29556
|
-
});
|
|
29557
|
-
} catch {
|
|
29558
|
-
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.transportError ? null : result.status, identity);
|
|
29559
|
-
}
|
|
29560
|
-
}
|
|
29561
29210
|
// package.json
|
|
29562
29211
|
var package_default = {
|
|
29563
29212
|
name: "@supacloud/cli",
|
|
29564
|
-
version: "0.
|
|
29213
|
+
version: "0.95.0",
|
|
29565
29214
|
description: "Project-scoped CLI for SupaCloud users",
|
|
29566
29215
|
type: "module",
|
|
29567
29216
|
main: "./dist/index.js",
|
|
@@ -29613,9 +29262,9 @@ var package_default = {
|
|
|
29613
29262
|
directory: "packages/cli"
|
|
29614
29263
|
},
|
|
29615
29264
|
dependencies: {
|
|
29616
|
-
"@supacloud/compiler": "^0.
|
|
29265
|
+
"@supacloud/compiler": "^0.45.0",
|
|
29617
29266
|
"@supacloud/delivery": "0.16.0",
|
|
29618
|
-
"@supacloud/db": "0.16.
|
|
29267
|
+
"@supacloud/db": "0.16.2",
|
|
29619
29268
|
typebox: "1.3.36"
|
|
29620
29269
|
},
|
|
29621
29270
|
overrides: {
|
|
@@ -29837,8 +29486,6 @@ EXAMPLES
|
|
|
29837
29486
|
${preferredCommand} deploy
|
|
29838
29487
|
${preferredCommand} --env test deploy
|
|
29839
29488
|
${preferredCommand} --env production deploy --confirm-production <project-ref>
|
|
29840
|
-
${preferredCommand} deploy --target web
|
|
29841
|
-
${preferredCommand} deploy --target api
|
|
29842
29489
|
${preferredCommand} dev sync --env test --target functions --function api
|
|
29843
29490
|
${preferredCommand} dev status --env test
|
|
29844
29491
|
${preferredCommand} dev watch --env test --target project
|
|
@@ -30194,8 +29841,7 @@ function createCliTools(context, confirmProduction) {
|
|
|
30194
29841
|
applicationRelease: (args) => tools.app ? tools.app.callback(args) : Promise.resolve({
|
|
30195
29842
|
isError: true,
|
|
30196
29843
|
content: [{ type: "text", text: "Application release support is unavailable in this CLI context" }]
|
|
30197
|
-
})
|
|
30198
|
-
edgeFunctionDeploy: advancedTools.edge_functions?.callback
|
|
29844
|
+
})
|
|
30199
29845
|
})));
|
|
30200
29846
|
assign(captureTools((server) => registerGatewayTools(server, http, {
|
|
30201
29847
|
projectRef: context.projectRef || undefined
|