@rodyssey/cli 0.3.0 → 0.3.1
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 +14 -0
- package/dist/cli.js +224 -55
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,6 +104,20 @@ no identity block stored)`. Re-running `ro auth login -e <env>` refreshes them.
|
|
|
104
104
|
older projects. This includes the Dynamic Worker MCP sample endpoint and the
|
|
105
105
|
shared `mcp/` helper folder; existing local MCP files are left untouched.
|
|
106
106
|
|
|
107
|
+
## Deployment Output
|
|
108
|
+
|
|
109
|
+
`ro app deploy` prints a post-deploy summary after the deploy succeeds:
|
|
110
|
+
|
|
111
|
+
- public Rodyssey app URL, e.g. `https://development-app.rodyssey.ai/webapp/<id>`
|
|
112
|
+
- published asset URL for SPA zip deployments
|
|
113
|
+
- registered Dynamic Worker endpoint URLs
|
|
114
|
+
- MCP server endpoint URLs for `api/mcp.ts`
|
|
115
|
+
- cron job names, schedules, enabled state, and script files
|
|
116
|
+
|
|
117
|
+
SPA deploys register built `dist/api/*` and `dist/cron-jobs/*` scripts after the
|
|
118
|
+
HTML zip has deployed. Fullstack deploys register the same Dynamic Worker
|
|
119
|
+
scripts after `wrangler deploy` and widget manifest sync.
|
|
120
|
+
|
|
107
121
|
## Release
|
|
108
122
|
|
|
109
123
|
Release automation lives in `.github/workflows/release.yml` and uses Changesets.
|
package/dist/cli.js
CHANGED
|
@@ -2071,7 +2071,7 @@ var {
|
|
|
2071
2071
|
// package.json
|
|
2072
2072
|
var package_default = {
|
|
2073
2073
|
name: "@rodyssey/cli",
|
|
2074
|
-
version: "0.3.
|
|
2074
|
+
version: "0.3.1",
|
|
2075
2075
|
description: "Scaffold new projects from airconcepts templates",
|
|
2076
2076
|
repository: {
|
|
2077
2077
|
type: "git",
|
|
@@ -3864,6 +3864,12 @@ var DEPLOY_URLS = {
|
|
|
3864
3864
|
staging: "https://staging-cms.rodyssey.ai/api/webapps/deploy",
|
|
3865
3865
|
production: "https://cms.rodyssey.ai/api/webapps/deploy"
|
|
3866
3866
|
};
|
|
3867
|
+
var WEB_CLIENT_URLS = {
|
|
3868
|
+
local: "http://localhost:5178",
|
|
3869
|
+
development: "https://development-app.rodyssey.ai",
|
|
3870
|
+
staging: "https://staging-app.rodyssey.ai",
|
|
3871
|
+
production: "https://app.rodyssey.ai"
|
|
3872
|
+
};
|
|
3867
3873
|
var BUILD_DIR = "dist";
|
|
3868
3874
|
var ZIP_FILE = "webapp-build.zip";
|
|
3869
3875
|
var FULLSTACK_DEPLOY_ENVS = new Set(["development", "staging", "production"]);
|
|
@@ -3872,9 +3878,204 @@ var MAX_SIZE_PER_BATCH = 30 * 1024 * 1024;
|
|
|
3872
3878
|
function shellQuote(value) {
|
|
3873
3879
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
3874
3880
|
}
|
|
3881
|
+
function isRecord(value) {
|
|
3882
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
3883
|
+
}
|
|
3884
|
+
function pickString2(value) {
|
|
3885
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
3886
|
+
}
|
|
3887
|
+
function pickNumber(value) {
|
|
3888
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
3889
|
+
}
|
|
3875
3890
|
function isFullstackProject() {
|
|
3876
3891
|
return existsSync4("app") && existsSync4("workers/app.ts") && existsSync4("wrangler.jsonc");
|
|
3877
3892
|
}
|
|
3893
|
+
function resolveDeployUrl(env, overrides) {
|
|
3894
|
+
let deployUrl = DEPLOY_URLS[env];
|
|
3895
|
+
if (!deployUrl) {
|
|
3896
|
+
throw new Error(`Unknown environment "${env}". Available: ${Object.keys(DEPLOY_URLS).join(", ")}`);
|
|
3897
|
+
}
|
|
3898
|
+
if (overrides.host || overrides.port) {
|
|
3899
|
+
const url = new URL(deployUrl);
|
|
3900
|
+
if (overrides.host)
|
|
3901
|
+
url.hostname = overrides.host;
|
|
3902
|
+
if (overrides.port)
|
|
3903
|
+
url.port = String(overrides.port);
|
|
3904
|
+
deployUrl = url.toString().replace(/\/$/, "");
|
|
3905
|
+
}
|
|
3906
|
+
return deployUrl;
|
|
3907
|
+
}
|
|
3908
|
+
function resolveScriptsSetupUrl(deployUrl) {
|
|
3909
|
+
return deployUrl.replace("/webapps/deploy", "/webapps/scripts-setup");
|
|
3910
|
+
}
|
|
3911
|
+
function resolveWebClientBaseUrl(env) {
|
|
3912
|
+
return WEB_CLIENT_URLS[env];
|
|
3913
|
+
}
|
|
3914
|
+
function buildPublicWebappUrl(env, webappId) {
|
|
3915
|
+
const baseUrl = resolveWebClientBaseUrl(env);
|
|
3916
|
+
if (!baseUrl)
|
|
3917
|
+
return;
|
|
3918
|
+
const url = new URL(`/webapp/${encodeURIComponent(webappId)}`, baseUrl);
|
|
3919
|
+
return url.toString();
|
|
3920
|
+
}
|
|
3921
|
+
function encodeEndpointPath(endpointPath) {
|
|
3922
|
+
return endpointPath.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
|
|
3923
|
+
}
|
|
3924
|
+
function buildDynamicEndpointUrl(env, webappId, endpointPath) {
|
|
3925
|
+
const baseUrl = resolveWebClientBaseUrl(env);
|
|
3926
|
+
if (!baseUrl)
|
|
3927
|
+
return;
|
|
3928
|
+
const encodedEndpoint = encodeEndpointPath(endpointPath);
|
|
3929
|
+
const url = new URL(`/api/webapps/${encodeURIComponent(webappId)}/endpoints/${encodedEndpoint}`, baseUrl);
|
|
3930
|
+
return url.toString();
|
|
3931
|
+
}
|
|
3932
|
+
function normalizeBuildRelativePath(filePath) {
|
|
3933
|
+
return filePath.substring(BUILD_DIR.length + 1).replace(/\\/g, "/");
|
|
3934
|
+
}
|
|
3935
|
+
function isScriptFile(filePath) {
|
|
3936
|
+
const relativePath = normalizeBuildRelativePath(filePath);
|
|
3937
|
+
if (relativePath === "cron-jobs/cron.config.json")
|
|
3938
|
+
return true;
|
|
3939
|
+
return (relativePath.startsWith("api/") || relativePath.startsWith("cron-jobs/")) && relativePath.endsWith(".js");
|
|
3940
|
+
}
|
|
3941
|
+
function isMcpEndpoint(endpointPath) {
|
|
3942
|
+
const segments = endpointPath.split("/").filter(Boolean);
|
|
3943
|
+
return segments[segments.length - 1]?.toLowerCase() === "mcp";
|
|
3944
|
+
}
|
|
3945
|
+
function resolveCronScriptCode(payload, scriptName) {
|
|
3946
|
+
const scriptNameKey = scriptName.replace(/\.js$/, "");
|
|
3947
|
+
return payload.cron[scriptNameKey] || payload.cron[scriptName];
|
|
3948
|
+
}
|
|
3949
|
+
function readCronConfig(filePath, content) {
|
|
3950
|
+
const parsed = JSON.parse(content);
|
|
3951
|
+
if (!isRecord(parsed)) {
|
|
3952
|
+
throw new Error(`Cron config must be a JSON object: ${filePath}`);
|
|
3953
|
+
}
|
|
3954
|
+
const jobs = parsed.jobs;
|
|
3955
|
+
if (jobs !== undefined && !Array.isArray(jobs)) {
|
|
3956
|
+
throw new Error(`Cron config jobs must be an array: ${filePath}`);
|
|
3957
|
+
}
|
|
3958
|
+
return parsed;
|
|
3959
|
+
}
|
|
3960
|
+
function collectScripts(scriptFiles) {
|
|
3961
|
+
const payload = { api: {}, cron: {}, cronConfig: null };
|
|
3962
|
+
const summary = { apiEndpoints: [], cronJobs: [], mcpEndpoints: [] };
|
|
3963
|
+
for (const filePath of scriptFiles) {
|
|
3964
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
3965
|
+
const relativePath = normalizeBuildRelativePath(filePath);
|
|
3966
|
+
if (relativePath === "cron-jobs/cron.config.json") {
|
|
3967
|
+
payload.cronConfig = readCronConfig(filePath, content);
|
|
3968
|
+
summary.cronJobs = payload.cronConfig.jobs ?? [];
|
|
3969
|
+
} else if (relativePath.startsWith("api/")) {
|
|
3970
|
+
const endpoint = relativePath.substring(4, relativePath.lastIndexOf(".js"));
|
|
3971
|
+
payload.api[endpoint] = content;
|
|
3972
|
+
summary.apiEndpoints.push(endpoint);
|
|
3973
|
+
if (isMcpEndpoint(endpoint)) {
|
|
3974
|
+
summary.mcpEndpoints.push(endpoint);
|
|
3975
|
+
}
|
|
3976
|
+
} else if (relativePath.startsWith("cron-jobs/")) {
|
|
3977
|
+
const scriptName = relativePath.substring(10);
|
|
3978
|
+
payload.cron[scriptName] = content;
|
|
3979
|
+
}
|
|
3980
|
+
}
|
|
3981
|
+
summary.cronJobs = summary.cronJobs.filter((job) => {
|
|
3982
|
+
const hasScriptCode = !!resolveCronScriptCode(payload, job.script);
|
|
3983
|
+
if (!hasScriptCode) {
|
|
3984
|
+
console.warn(`⚠️ Cron job "${job.name}" references missing script "${job.script}" and will not be registered.`);
|
|
3985
|
+
}
|
|
3986
|
+
return hasScriptCode;
|
|
3987
|
+
});
|
|
3988
|
+
return { payload, summary };
|
|
3989
|
+
}
|
|
3990
|
+
function extractDeploymentWebapp(result) {
|
|
3991
|
+
if (!isRecord(result) || !isRecord(result.webapp))
|
|
3992
|
+
return {};
|
|
3993
|
+
return {
|
|
3994
|
+
id: pickString2(result.webapp.id),
|
|
3995
|
+
title: pickString2(result.webapp.title),
|
|
3996
|
+
appUrl: pickString2(result.webapp.appUrl)
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
function printScriptsSetupCounts(result) {
|
|
4000
|
+
if (!isRecord(result))
|
|
4001
|
+
return;
|
|
4002
|
+
const parts = [
|
|
4003
|
+
["API registered", pickNumber(result.apiCreated)],
|
|
4004
|
+
["API deleted", pickNumber(result.apiDeleted)],
|
|
4005
|
+
["Cron registered", pickNumber(result.cronCreated)],
|
|
4006
|
+
["Cron deleted", pickNumber(result.cronDeleted)],
|
|
4007
|
+
["Cache invalidated", pickNumber(result.cacheInvalidated)]
|
|
4008
|
+
].filter((entry) => entry[1] !== undefined).map(([label, count]) => `${label}: ${count}`);
|
|
4009
|
+
if (parts.length > 0) {
|
|
4010
|
+
console.log(` ${parts.join(" · ")}`);
|
|
4011
|
+
}
|
|
4012
|
+
}
|
|
4013
|
+
function printPostDeploySummary(options) {
|
|
4014
|
+
const webapp = extractDeploymentWebapp(options.deploymentResult);
|
|
4015
|
+
const webappId = webapp.id || process.env.WEBAPP_ID;
|
|
4016
|
+
console.log(`
|
|
4017
|
+
\uD83D\uDD17 Deployment URLs`);
|
|
4018
|
+
if (webappId) {
|
|
4019
|
+
const appUrl = buildPublicWebappUrl(options.env, webappId);
|
|
4020
|
+
if (appUrl) {
|
|
4021
|
+
console.log(`App URL: ${appUrl}`);
|
|
4022
|
+
}
|
|
4023
|
+
} else {
|
|
4024
|
+
console.log("App URL: unavailable (WEBAPP_ID was not found)");
|
|
4025
|
+
}
|
|
4026
|
+
if (webapp.appUrl) {
|
|
4027
|
+
console.log(`Published asset URL: ${webapp.appUrl}`);
|
|
4028
|
+
}
|
|
4029
|
+
if (options.scriptsSummary.apiEndpoints.length > 0) {
|
|
4030
|
+
console.log(`
|
|
4031
|
+
\uD83C\uDF10 Dynamic endpoints`);
|
|
4032
|
+
for (const endpoint of options.scriptsSummary.apiEndpoints) {
|
|
4033
|
+
const url = webappId ? buildDynamicEndpointUrl(options.env, webappId, endpoint) : undefined;
|
|
4034
|
+
console.log(`- ${endpoint}${url ? `: ${url}` : ""}`);
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
if (options.scriptsSummary.mcpEndpoints.length > 0) {
|
|
4038
|
+
console.log(`
|
|
4039
|
+
\uD83E\uDDE9 MCP server URLs`);
|
|
4040
|
+
for (const endpoint of options.scriptsSummary.mcpEndpoints) {
|
|
4041
|
+
const url = webappId ? buildDynamicEndpointUrl(options.env, webappId, endpoint) : undefined;
|
|
4042
|
+
console.log(`- ${endpoint}${url ? `: ${url}` : ""}`);
|
|
4043
|
+
}
|
|
4044
|
+
}
|
|
4045
|
+
if (options.scriptsSummary.cronJobs.length > 0) {
|
|
4046
|
+
console.log(`
|
|
4047
|
+
⏱️ Cron jobs`);
|
|
4048
|
+
for (const job of options.scriptsSummary.cronJobs) {
|
|
4049
|
+
const status = job.enabled === false ? "disabled" : "enabled";
|
|
4050
|
+
console.log(`- ${job.name}: ${job.schedule} (${status}, ${job.script})`);
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
async function syncScripts(deployUrl, scriptFiles, stepLabel) {
|
|
4055
|
+
const { payload, summary } = collectScripts(scriptFiles);
|
|
4056
|
+
if (scriptFiles.length === 0) {
|
|
4057
|
+
console.log(`\uD83D\uDCDC ${stepLabel}: No scripts found to sync.`);
|
|
4058
|
+
return { summary, result: undefined };
|
|
4059
|
+
}
|
|
4060
|
+
console.log(`\uD83D\uDCDC ${stepLabel}: Registering ${scriptFiles.length} scripts (APIs & Crons)...`);
|
|
4061
|
+
const scriptsUrl = resolveScriptsSetupUrl(deployUrl);
|
|
4062
|
+
const response = await fetch(scriptsUrl, {
|
|
4063
|
+
method: "POST",
|
|
4064
|
+
headers: {
|
|
4065
|
+
Authorization: `Bearer ${process.env.DEPLOY_TOKEN}`,
|
|
4066
|
+
"Content-Type": "application/json"
|
|
4067
|
+
},
|
|
4068
|
+
body: JSON.stringify(payload)
|
|
4069
|
+
});
|
|
4070
|
+
const result = await readResponsePayload(response);
|
|
4071
|
+
if (!response.ok) {
|
|
4072
|
+
throw new Error(`Scripts setup failed: ${response.status} ${response.statusText}
|
|
4073
|
+
${JSON.stringify(result, null, 2)}`);
|
|
4074
|
+
}
|
|
4075
|
+
console.log("✅ Scripts registered successfully");
|
|
4076
|
+
printScriptsSetupCounts(result);
|
|
4077
|
+
return { summary, result };
|
|
4078
|
+
}
|
|
3878
4079
|
function getAllFiles(dirPath, arrayOfFiles = []) {
|
|
3879
4080
|
if (!existsSync4(dirPath))
|
|
3880
4081
|
return arrayOfFiles;
|
|
@@ -3911,6 +4112,7 @@ async function deployFullstack(env, overrides) {
|
|
|
3911
4112
|
...process.env,
|
|
3912
4113
|
CLOUDFLARE_ENV: env
|
|
3913
4114
|
};
|
|
4115
|
+
const deployUrl = resolveDeployUrl(env, overrides);
|
|
3914
4116
|
console.log(`\uD83D\uDE80 Starting fullstack deployment process for [${env}] environment...
|
|
3915
4117
|
`);
|
|
3916
4118
|
console.log("\uD83D\uDCE6 Step 1: Building the fullstack webapp...");
|
|
@@ -3930,23 +4132,18 @@ async function deployFullstack(env, overrides) {
|
|
|
3930
4132
|
...overrides.port ? ["--port", shellQuote(String(overrides.port))] : []
|
|
3931
4133
|
];
|
|
3932
4134
|
execSync2(`bun run sync-widget-manifest -- ${syncArgs.join(" ")}`, { stdio: "inherit", env: childEnv });
|
|
4135
|
+
console.log();
|
|
4136
|
+
const scriptFiles = getAllFiles(BUILD_DIR).filter(isScriptFile);
|
|
4137
|
+
const scriptsSync = await syncScripts(deployUrl, scriptFiles, "Step 4");
|
|
4138
|
+
printPostDeploySummary({
|
|
4139
|
+
env,
|
|
4140
|
+
scriptsSummary: scriptsSync.summary
|
|
4141
|
+
});
|
|
3933
4142
|
console.log(`
|
|
3934
4143
|
✨ Fullstack deployment successful!`);
|
|
3935
4144
|
}
|
|
3936
4145
|
async function deploySpa(env, overrides) {
|
|
3937
|
-
|
|
3938
|
-
if (!DEPLOY_URL) {
|
|
3939
|
-
console.error(`❌ Unknown environment "${env}". Available: ${Object.keys(DEPLOY_URLS).join(", ")}`);
|
|
3940
|
-
process.exit(1);
|
|
3941
|
-
}
|
|
3942
|
-
if (overrides.host || overrides.port) {
|
|
3943
|
-
const url = new URL(DEPLOY_URL);
|
|
3944
|
-
if (overrides.host)
|
|
3945
|
-
url.hostname = overrides.host;
|
|
3946
|
-
if (overrides.port)
|
|
3947
|
-
url.port = String(overrides.port);
|
|
3948
|
-
DEPLOY_URL = url.toString().replace(/\/$/, "");
|
|
3949
|
-
}
|
|
4146
|
+
const DEPLOY_URL = resolveDeployUrl(env, overrides);
|
|
3950
4147
|
const ASSETS_URL = DEPLOY_URL.replace("/webapps/deploy", "/webapps/assets");
|
|
3951
4148
|
console.log(`\uD83D\uDE80 Starting deployment process for [${env}] environment...
|
|
3952
4149
|
`);
|
|
@@ -3964,7 +4161,7 @@ async function deploySpa(env, overrides) {
|
|
|
3964
4161
|
`);
|
|
3965
4162
|
const allFiles = getAllFiles(BUILD_DIR);
|
|
3966
4163
|
const htmlFiles = allFiles.filter((f) => f.endsWith(".html"));
|
|
3967
|
-
const scriptFiles = allFiles.filter(
|
|
4164
|
+
const scriptFiles = allFiles.filter(isScriptFile);
|
|
3968
4165
|
const heavyFiles = allFiles.filter((f) => !f.endsWith(".html") && !scriptFiles.includes(f));
|
|
3969
4166
|
console.log(`\uD83D\uDCE4 Step 2: Uploading ${heavyFiles.length} heavy assets...`);
|
|
3970
4167
|
if (heavyFiles.length > 0) {
|
|
@@ -4012,42 +4209,7 @@ ${errorText}`);
|
|
|
4012
4209
|
console.log("✅ No heavy assets to upload");
|
|
4013
4210
|
}
|
|
4014
4211
|
console.log();
|
|
4015
|
-
|
|
4016
|
-
console.log(`\uD83D\uDCDC Step 3: Setting up ${scriptFiles.length} scripts (APIs & Crons)...`);
|
|
4017
|
-
const scriptsPayload = { api: {}, cron: {}, cronConfig: null };
|
|
4018
|
-
for (const f of scriptFiles) {
|
|
4019
|
-
const content = readFileSync3(f, "utf-8");
|
|
4020
|
-
const relativePath = f.substring(BUILD_DIR.length + 1).replace(/\\/g, "/");
|
|
4021
|
-
if (relativePath === "cron-jobs/cron.config.json") {
|
|
4022
|
-
scriptsPayload.cronConfig = JSON.parse(content);
|
|
4023
|
-
} else if (relativePath.startsWith("api/")) {
|
|
4024
|
-
const endpoint = relativePath.substring(4, relativePath.lastIndexOf(".js"));
|
|
4025
|
-
scriptsPayload.api[endpoint] = content;
|
|
4026
|
-
} else if (relativePath.startsWith("cron-jobs/")) {
|
|
4027
|
-
const scriptName = relativePath.substring(10);
|
|
4028
|
-
scriptsPayload.cron[scriptName] = content;
|
|
4029
|
-
}
|
|
4030
|
-
}
|
|
4031
|
-
const scriptsUrl = DEPLOY_URL.replace("/webapps/deploy", "/webapps/scripts-setup");
|
|
4032
|
-
const response = await fetch(scriptsUrl, {
|
|
4033
|
-
method: "POST",
|
|
4034
|
-
headers: {
|
|
4035
|
-
Authorization: `Bearer ${process.env.DEPLOY_TOKEN}`,
|
|
4036
|
-
"Content-Type": "application/json"
|
|
4037
|
-
},
|
|
4038
|
-
body: JSON.stringify(scriptsPayload)
|
|
4039
|
-
});
|
|
4040
|
-
if (!response.ok) {
|
|
4041
|
-
const errorText = await response.text();
|
|
4042
|
-
throw new Error(`Scripts setup failed: ${response.status} ${response.statusText}
|
|
4043
|
-
${errorText}`);
|
|
4044
|
-
}
|
|
4045
|
-
console.log(`✅ Scripts synced successfully`);
|
|
4046
|
-
} else {
|
|
4047
|
-
console.log(`\uD83D\uDCDC Step 3: No scripts found to sync.`);
|
|
4048
|
-
}
|
|
4049
|
-
console.log();
|
|
4050
|
-
console.log(`\uD83D\uDDDC️ Step 4: Zipping ${htmlFiles.length} HTML files...`);
|
|
4212
|
+
console.log(`\uD83D\uDDDC️ Step 3: Zipping ${htmlFiles.length} HTML files...`);
|
|
4051
4213
|
if (htmlFiles.length === 0) {
|
|
4052
4214
|
console.warn("⚠️ No HTML files found to zip! Deployment might fail if CMS expects an HTML file.");
|
|
4053
4215
|
}
|
|
@@ -4055,7 +4217,7 @@ ${errorText}`);
|
|
|
4055
4217
|
execSync2(`cd ${BUILD_DIR} && zip ../${ZIP_FILE} ${relativeHtmlFiles.join(" ")}`, { stdio: "inherit" });
|
|
4056
4218
|
console.log(`✅ Created ${ZIP_FILE}
|
|
4057
4219
|
`);
|
|
4058
|
-
console.log("☁️ Step
|
|
4220
|
+
console.log("☁️ Step 4: Deploying HTML zip to server...");
|
|
4059
4221
|
const zipBuffer = readFileSync3(ZIP_FILE);
|
|
4060
4222
|
try {
|
|
4061
4223
|
const response = await fetch(DEPLOY_URL, {
|
|
@@ -4071,10 +4233,17 @@ ${errorText}`);
|
|
|
4071
4233
|
throw new Error(`Deploy failed: ${response.status} ${response.statusText}
|
|
4072
4234
|
${errorText}`);
|
|
4073
4235
|
}
|
|
4074
|
-
const result = await response
|
|
4236
|
+
const result = await readResponsePayload(response);
|
|
4075
4237
|
console.log("✅ Deploy completed");
|
|
4076
4238
|
console.log(`
|
|
4077
4239
|
\uD83D\uDCCB Deployment result:`, result);
|
|
4240
|
+
console.log();
|
|
4241
|
+
const scriptsSync = await syncScripts(DEPLOY_URL, scriptFiles, "Step 5");
|
|
4242
|
+
printPostDeploySummary({
|
|
4243
|
+
env,
|
|
4244
|
+
deploymentResult: result,
|
|
4245
|
+
scriptsSummary: scriptsSync.summary
|
|
4246
|
+
});
|
|
4078
4247
|
} catch (error) {
|
|
4079
4248
|
console.error("❌ Deploy failed:", error);
|
|
4080
4249
|
throw error;
|
|
@@ -4599,7 +4768,7 @@ var PROD_ENV_FILE = ".env.production";
|
|
|
4599
4768
|
function isObject3(value) {
|
|
4600
4769
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
4601
4770
|
}
|
|
4602
|
-
function
|
|
4771
|
+
function pickString3(...values) {
|
|
4603
4772
|
return values.find((value) => typeof value === "string" && value.length > 0);
|
|
4604
4773
|
}
|
|
4605
4774
|
function nestedObject2(value, key) {
|
|
@@ -4610,7 +4779,7 @@ function nestedObject2(value, key) {
|
|
|
4610
4779
|
}
|
|
4611
4780
|
function extractDeployToken2(payload) {
|
|
4612
4781
|
const webapp = nestedObject2(payload, "webapp");
|
|
4613
|
-
return
|
|
4782
|
+
return pickString3(webapp?.deployToken, webapp?.deploymentToken);
|
|
4614
4783
|
}
|
|
4615
4784
|
function unwrapSourceDetails(payload) {
|
|
4616
4785
|
if (!isObject3(payload))
|