@insforge/cli 0.1.68 → 0.1.70
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/dist/index.js +176 -152
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { readFileSync as readFileSync8 } from "fs";
|
|
|
5
5
|
import { join as join14, dirname as dirname2 } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { Command } from "commander";
|
|
8
|
-
import * as
|
|
8
|
+
import * as clack16 from "@clack/prompts";
|
|
9
9
|
|
|
10
10
|
// src/lib/prompts.ts
|
|
11
11
|
import * as readline from "readline";
|
|
@@ -232,7 +232,11 @@ function getProjectConfig() {
|
|
|
232
232
|
return null;
|
|
233
233
|
}
|
|
234
234
|
const raw = readFileSync(file, "utf-8");
|
|
235
|
-
|
|
235
|
+
const config = JSON.parse(raw);
|
|
236
|
+
if (config.oss_host && !/^https?:\/\//.test(config.oss_host) && config.appkey && config.region) {
|
|
237
|
+
config.oss_host = buildOssHost(config.appkey, config.region);
|
|
238
|
+
}
|
|
239
|
+
return config;
|
|
236
240
|
}
|
|
237
241
|
function saveProjectConfig(config) {
|
|
238
242
|
const dir = getLocalConfigDir();
|
|
@@ -241,6 +245,9 @@ function saveProjectConfig(config) {
|
|
|
241
245
|
}
|
|
242
246
|
writeFileSync(getLocalConfigFile(), JSON.stringify(config, null, 2), { mode: 384 });
|
|
243
247
|
}
|
|
248
|
+
function buildOssHost(appkey, region) {
|
|
249
|
+
return `https://${appkey}.${region}.insforge.app`;
|
|
250
|
+
}
|
|
244
251
|
function getPlatformApiUrl(override) {
|
|
245
252
|
return process.env.INSFORGE_API_URL ?? override ?? getGlobalConfig().platform_api_url ?? DEFAULT_PLATFORM_URL;
|
|
246
253
|
}
|
|
@@ -1160,6 +1167,9 @@ function registerProjectsCommands(projectsCmd2) {
|
|
|
1160
1167
|
});
|
|
1161
1168
|
}
|
|
1162
1169
|
|
|
1170
|
+
// src/commands/branch/create.ts
|
|
1171
|
+
import * as clack5 from "@clack/prompts";
|
|
1172
|
+
|
|
1163
1173
|
// src/lib/analytics.ts
|
|
1164
1174
|
import { PostHog } from "posthog-node";
|
|
1165
1175
|
var POSTHOG_API_KEY = "phc_ueV1ii62wdBTkH7E70ugyeqHIHu8dFDdjs0qq3TZhJz";
|
|
@@ -1261,7 +1271,7 @@ async function runBranchSwitch(input) {
|
|
|
1261
1271
|
copyFileSync(projectFile, parentBackup);
|
|
1262
1272
|
}
|
|
1263
1273
|
const apiKey = await getProjectApiKey(target.id, input.apiUrl);
|
|
1264
|
-
const ossHost =
|
|
1274
|
+
const ossHost = buildOssHost(target.appkey, target.region);
|
|
1265
1275
|
const branched_from = current.branched_from ?? {
|
|
1266
1276
|
project_id: current.project_id,
|
|
1267
1277
|
project_name: current.project_name
|
|
@@ -1319,22 +1329,42 @@ function registerBranchCreateCommand(branch) {
|
|
|
1319
1329
|
throw new CLIError(`Invalid --mode: ${opts.mode} (must be "full" or "schema-only")`);
|
|
1320
1330
|
}
|
|
1321
1331
|
const mode = opts.mode;
|
|
1322
|
-
const
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1332
|
+
const spinner9 = !json ? clack5.spinner() : null;
|
|
1333
|
+
let ready;
|
|
1334
|
+
let provisioned = false;
|
|
1335
|
+
try {
|
|
1336
|
+
spinner9?.start(`Creating branch '${name}'...`);
|
|
1337
|
+
const created = await createBranchApi(project.project_id, { mode, name }, apiUrl);
|
|
1338
|
+
captureEvent(project.project_id, "cli_branch_create", {
|
|
1339
|
+
mode,
|
|
1340
|
+
parent_project_id: project.project_id
|
|
1341
|
+
});
|
|
1342
|
+
spinner9?.message(`Branch '${name}' created (appkey: ${created.appkey}). Provisioning...`);
|
|
1343
|
+
ready = await pollUntilReady(created.id, apiUrl, spinner9);
|
|
1344
|
+
provisioned = ready.branch_state === "ready";
|
|
1345
|
+
if (provisioned && opts.switch) {
|
|
1346
|
+
spinner9?.message("Branch ready. Switching context...");
|
|
1347
|
+
await runBranchSwitch({ name, apiUrl, json, silent: true });
|
|
1348
|
+
spinner9?.stop(`Branch '${name}' is ready and active`);
|
|
1349
|
+
} else if (provisioned) {
|
|
1350
|
+
spinner9?.stop(`Branch '${name}' is ready`);
|
|
1351
|
+
} else {
|
|
1352
|
+
spinner9?.stop(`Branch '${name}' is in '${ready.branch_state}' state`);
|
|
1353
|
+
}
|
|
1354
|
+
} catch (err) {
|
|
1355
|
+
if (provisioned) {
|
|
1356
|
+
spinner9?.stop(
|
|
1357
|
+
`Branch '${name}' is ready, but switching context failed \u2014 run \`insforge branch switch ${name}\` to retry`,
|
|
1358
|
+
1
|
|
1359
|
+
);
|
|
1360
|
+
} else {
|
|
1361
|
+
spinner9?.stop(`Branch '${name}' creation failed`, 1);
|
|
1362
|
+
}
|
|
1363
|
+
throw err;
|
|
1333
1364
|
}
|
|
1334
1365
|
if (json) {
|
|
1335
1366
|
outputJson({ branch: ready });
|
|
1336
1367
|
} else if (ready.branch_state === "ready") {
|
|
1337
|
-
outputSuccess(`Branch '${name}' is ready.`);
|
|
1338
1368
|
if (opts.switch) {
|
|
1339
1369
|
outputInfo(
|
|
1340
1370
|
"\u26A0 Re-source your dev server env (.env) to pick up the new INSFORGE_URL / ANON_KEY."
|
|
@@ -1352,7 +1382,7 @@ function registerBranchCreateCommand(branch) {
|
|
|
1352
1382
|
}
|
|
1353
1383
|
});
|
|
1354
1384
|
}
|
|
1355
|
-
async function pollUntilReady(branchId, apiUrl,
|
|
1385
|
+
async function pollUntilReady(branchId, apiUrl, spinner9) {
|
|
1356
1386
|
const start = Date.now();
|
|
1357
1387
|
let lastState = "";
|
|
1358
1388
|
while (Date.now() - start < POLL_TIMEOUT_MS) {
|
|
@@ -1361,8 +1391,8 @@ async function pollUntilReady(branchId, apiUrl, showProgress) {
|
|
|
1361
1391
|
if (branch2.branch_state === "deleted" || branch2.branch_state === "conflicted") {
|
|
1362
1392
|
throw new CLIError(`Branch creation failed (state: ${branch2.branch_state})`);
|
|
1363
1393
|
}
|
|
1364
|
-
if (
|
|
1365
|
-
|
|
1394
|
+
if (spinner9 && branch2.branch_state !== lastState) {
|
|
1395
|
+
spinner9.message(`Provisioning branch (state: ${branch2.branch_state})...`);
|
|
1366
1396
|
lastState = branch2.branch_state;
|
|
1367
1397
|
}
|
|
1368
1398
|
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
@@ -1414,10 +1444,10 @@ function registerBranchListCommand(branch) {
|
|
|
1414
1444
|
|
|
1415
1445
|
// src/commands/branch/merge.ts
|
|
1416
1446
|
import { writeFileSync as writeFileSync2 } from "fs";
|
|
1417
|
-
import * as
|
|
1447
|
+
import * as clack6 from "@clack/prompts";
|
|
1418
1448
|
function registerBranchMergeCommand(branch) {
|
|
1419
|
-
branch.command("merge <name>").description("Merge a branch back to its parent project").option("--dry-run", "Compute the diff and print rendered SQL; do not apply").option("
|
|
1420
|
-
const { json, apiUrl } = getRootOpts(cmd);
|
|
1449
|
+
branch.command("merge <name>").description("Merge a branch back to its parent project").option("--dry-run", "Compute the diff and print rendered SQL; do not apply").option("--save-sql <path>", "Write rendered SQL preview to a file").action(async (name, opts, cmd) => {
|
|
1450
|
+
const { json, apiUrl, yes } = getRootOpts(cmd);
|
|
1421
1451
|
try {
|
|
1422
1452
|
await requireAuth(apiUrl);
|
|
1423
1453
|
const project = getProjectConfig();
|
|
@@ -1469,12 +1499,12 @@ function registerBranchMergeCommand(branch) {
|
|
|
1469
1499
|
}
|
|
1470
1500
|
return;
|
|
1471
1501
|
}
|
|
1472
|
-
if (!
|
|
1502
|
+
if (!yes && !json) {
|
|
1473
1503
|
const parentLabel = project.branched_from?.project_name ?? project.project_name;
|
|
1474
|
-
const confirmed = await
|
|
1504
|
+
const confirmed = await clack6.confirm({
|
|
1475
1505
|
message: `Apply this merge to parent project '${parentLabel}'?`
|
|
1476
1506
|
});
|
|
1477
|
-
if (
|
|
1507
|
+
if (clack6.isCancel(confirmed) || !confirmed) {
|
|
1478
1508
|
outputInfo("Merge cancelled.");
|
|
1479
1509
|
return;
|
|
1480
1510
|
}
|
|
@@ -1519,12 +1549,12 @@ function registerBranchMergeCommand(branch) {
|
|
|
1519
1549
|
}
|
|
1520
1550
|
|
|
1521
1551
|
// src/commands/branch/reset.ts
|
|
1522
|
-
import * as
|
|
1552
|
+
import * as clack7 from "@clack/prompts";
|
|
1523
1553
|
var POLL_INTERVAL_MS2 = 3e3;
|
|
1524
1554
|
var POLL_TIMEOUT_MS2 = 5 * 60 * 1e3;
|
|
1525
1555
|
function registerBranchResetCommand(branch) {
|
|
1526
|
-
branch.command("reset <name>").description("Reset a branch's database back to T0 (the parent snapshot at branch creation)").
|
|
1527
|
-
const { json, apiUrl } = getRootOpts(cmd);
|
|
1556
|
+
branch.command("reset <name>").description("Reset a branch's database back to T0 (the parent snapshot at branch creation)").action(async (name, _opts, cmd) => {
|
|
1557
|
+
const { json, apiUrl, yes } = getRootOpts(cmd);
|
|
1528
1558
|
try {
|
|
1529
1559
|
await requireAuth(apiUrl);
|
|
1530
1560
|
const project = getProjectConfig();
|
|
@@ -1539,11 +1569,11 @@ function registerBranchResetCommand(branch) {
|
|
|
1539
1569
|
);
|
|
1540
1570
|
}
|
|
1541
1571
|
const entryState = target.branch_state;
|
|
1542
|
-
if (!
|
|
1543
|
-
const confirmed = await
|
|
1572
|
+
if (!yes && !json) {
|
|
1573
|
+
const confirmed = await clack7.confirm({
|
|
1544
1574
|
message: `Reset branch '${name}' back to T0? This wipes all schema/data/policy/function/migration changes made on the branch since creation.` + (entryState === "merged" ? " (Branch is currently merged \u2014 reset will reopen it for further work.)" : "")
|
|
1545
1575
|
});
|
|
1546
|
-
if (
|
|
1576
|
+
if (clack7.isCancel(confirmed) || !confirmed) {
|
|
1547
1577
|
outputInfo("Cancelled.");
|
|
1548
1578
|
return;
|
|
1549
1579
|
}
|
|
@@ -1599,10 +1629,10 @@ async function pollUntilReady2(branchId, apiUrl, showProgress, startingState) {
|
|
|
1599
1629
|
}
|
|
1600
1630
|
|
|
1601
1631
|
// src/commands/branch/delete.ts
|
|
1602
|
-
import * as
|
|
1632
|
+
import * as clack8 from "@clack/prompts";
|
|
1603
1633
|
function registerBranchDeleteCommand(branch) {
|
|
1604
|
-
branch.command("delete <name>").description("Delete a branch").
|
|
1605
|
-
const { json, apiUrl } = getRootOpts(cmd);
|
|
1634
|
+
branch.command("delete <name>").description("Delete a branch").action(async (name, _opts, cmd) => {
|
|
1635
|
+
const { json, apiUrl, yes } = getRootOpts(cmd);
|
|
1606
1636
|
try {
|
|
1607
1637
|
await requireAuth(apiUrl);
|
|
1608
1638
|
const project = getProjectConfig();
|
|
@@ -1611,11 +1641,11 @@ function registerBranchDeleteCommand(branch) {
|
|
|
1611
1641
|
const branches = await listBranchesApi(parentId, apiUrl);
|
|
1612
1642
|
const target = branches.find((b) => b.name === name);
|
|
1613
1643
|
if (!target) throw new CLIError(`Branch '${name}' not found.`);
|
|
1614
|
-
if (!
|
|
1615
|
-
const confirmed = await
|
|
1644
|
+
if (!yes && !json) {
|
|
1645
|
+
const confirmed = await clack8.confirm({
|
|
1616
1646
|
message: `Delete branch '${name}'? This terminates its EC2 instance.`
|
|
1617
1647
|
});
|
|
1618
|
-
if (
|
|
1648
|
+
if (clack8.isCancel(confirmed) || !confirmed) {
|
|
1619
1649
|
outputInfo("Cancelled.");
|
|
1620
1650
|
return;
|
|
1621
1651
|
}
|
|
@@ -1662,7 +1692,7 @@ import { exec as exec3 } from "child_process";
|
|
|
1662
1692
|
import { promisify as promisify4 } from "util";
|
|
1663
1693
|
import * as fs5 from "fs/promises";
|
|
1664
1694
|
import * as path5 from "path";
|
|
1665
|
-
import * as
|
|
1695
|
+
import * as clack13 from "@clack/prompts";
|
|
1666
1696
|
import pc2 from "picocolors";
|
|
1667
1697
|
|
|
1668
1698
|
// src/lib/skills.ts
|
|
@@ -1670,7 +1700,7 @@ import { exec } from "child_process";
|
|
|
1670
1700
|
import { existsSync as existsSync3, readFileSync as readFileSync2, appendFileSync } from "fs";
|
|
1671
1701
|
import { join as join2 } from "path";
|
|
1672
1702
|
import { promisify } from "util";
|
|
1673
|
-
import * as
|
|
1703
|
+
import * as clack9 from "@clack/prompts";
|
|
1674
1704
|
var execAsync = promisify(exec);
|
|
1675
1705
|
var SKILL_INSTALL_TIMEOUT_MS = 6e4;
|
|
1676
1706
|
function describeExecError(err) {
|
|
@@ -1723,29 +1753,29 @@ ${missing.join("\n")}
|
|
|
1723
1753
|
}
|
|
1724
1754
|
async function installSkills(json) {
|
|
1725
1755
|
try {
|
|
1726
|
-
if (!json)
|
|
1756
|
+
if (!json) clack9.log.info("Installing InsForge agent skills (global)...");
|
|
1727
1757
|
await execAsync("npx skills add insforge/agent-skills -g -y -a antigravity -a augment -a claude-code -a cline -a codex -a cursor -a gemini-cli -a github-copilot -a kilo -a qoder -a qwen-code -a roo -a trae -a windsurf", {
|
|
1728
1758
|
cwd: process.cwd(),
|
|
1729
1759
|
timeout: SKILL_INSTALL_TIMEOUT_MS
|
|
1730
1760
|
});
|
|
1731
|
-
if (!json)
|
|
1761
|
+
if (!json) clack9.log.success("InsForge agent skills installed.");
|
|
1732
1762
|
} catch (err) {
|
|
1733
1763
|
if (!json) {
|
|
1734
|
-
|
|
1735
|
-
|
|
1764
|
+
clack9.log.warn(`Could not install agent skills: ${describeExecError(err)}`);
|
|
1765
|
+
clack9.log.info("Run `npx skills add insforge/agent-skills` once resolved to see the full output.");
|
|
1736
1766
|
}
|
|
1737
1767
|
}
|
|
1738
1768
|
try {
|
|
1739
|
-
if (!json)
|
|
1769
|
+
if (!json) clack9.log.info("Installing find-skills (global)...");
|
|
1740
1770
|
await execAsync("npx skills add https://github.com/vercel-labs/skills --skill find-skills -g -y", {
|
|
1741
1771
|
cwd: process.cwd(),
|
|
1742
1772
|
timeout: SKILL_INSTALL_TIMEOUT_MS
|
|
1743
1773
|
});
|
|
1744
|
-
if (!json)
|
|
1774
|
+
if (!json) clack9.log.success("find-skills installed.");
|
|
1745
1775
|
} catch (err) {
|
|
1746
1776
|
if (!json) {
|
|
1747
|
-
|
|
1748
|
-
|
|
1777
|
+
clack9.log.warn(`Could not install find-skills: ${describeExecError(err)}`);
|
|
1778
|
+
clack9.log.info("Run `npx skills add https://github.com/vercel-labs/skills --skill find-skills` once resolved.");
|
|
1749
1779
|
}
|
|
1750
1780
|
}
|
|
1751
1781
|
try {
|
|
@@ -1801,7 +1831,7 @@ import { tmpdir } from "os";
|
|
|
1801
1831
|
import { execFile } from "child_process";
|
|
1802
1832
|
import { promisify as promisify2 } from "util";
|
|
1803
1833
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
1804
|
-
import * as
|
|
1834
|
+
import * as clack10 from "@clack/prompts";
|
|
1805
1835
|
|
|
1806
1836
|
// src/lib/api/oss.ts
|
|
1807
1837
|
function requireProjectConfig() {
|
|
@@ -2008,7 +2038,7 @@ async function applyAuthProvider(provider, cwd, projectConfig, json) {
|
|
|
2008
2038
|
if (!VALID_AUTH_PROVIDERS.includes(provider)) {
|
|
2009
2039
|
throw new Error(`Unknown auth provider: ${provider}`);
|
|
2010
2040
|
}
|
|
2011
|
-
const fetchSpinner = !json ?
|
|
2041
|
+
const fetchSpinner = !json ? clack10.spinner() : null;
|
|
2012
2042
|
fetchSpinner?.start(`Fetching ${provider} scaffold from templates repo...`);
|
|
2013
2043
|
const { dir: providerDir, cleanup } = await fetchProviderTree(provider);
|
|
2014
2044
|
fetchSpinner?.stop(`${provider} scaffold ready`);
|
|
@@ -2107,15 +2137,15 @@ async function applyAuthProvider(provider, cwd, projectConfig, json) {
|
|
|
2107
2137
|
result.envKeysRefreshed = Array.from(/* @__PURE__ */ new Set([...result.envKeysRefreshed, ...refreshed]));
|
|
2108
2138
|
}
|
|
2109
2139
|
if (!jwtSecret && !json) {
|
|
2110
|
-
|
|
2140
|
+
clack10.log.warn("Could not auto-fill JWT_SECRET \u2014 run `npx @insforge/cli secrets get JWT_SECRET` and paste it into .env.local.");
|
|
2111
2141
|
}
|
|
2112
2142
|
if (result.envKeysSkipped.length > 0 && !json) {
|
|
2113
|
-
|
|
2143
|
+
clack10.log.warn(
|
|
2114
2144
|
`Kept your existing values for: ${result.envKeysSkipped.join(", ")}. If any of these need the auth-provider's defaults, see .env.example for reference.`
|
|
2115
2145
|
);
|
|
2116
2146
|
}
|
|
2117
2147
|
if (result.envKeysRefreshed.length > 0 && !json) {
|
|
2118
|
-
|
|
2148
|
+
clack10.log.info(
|
|
2119
2149
|
`Refreshed stale platform defaults: ${result.envKeysRefreshed.join(", ")}. Your value matched the manifest's default, so we replaced it with the live one.`
|
|
2120
2150
|
);
|
|
2121
2151
|
}
|
|
@@ -2131,7 +2161,7 @@ import { tmpdir as tmpdir2 } from "os";
|
|
|
2131
2161
|
import { promisify as promisify3 } from "util";
|
|
2132
2162
|
import * as fs4 from "fs/promises";
|
|
2133
2163
|
import * as path4 from "path";
|
|
2134
|
-
import * as
|
|
2164
|
+
import * as clack12 from "@clack/prompts";
|
|
2135
2165
|
|
|
2136
2166
|
// src/lib/env.ts
|
|
2137
2167
|
import * as fs2 from "fs/promises";
|
|
@@ -2166,7 +2196,7 @@ import * as path3 from "path";
|
|
|
2166
2196
|
import * as fs3 from "fs/promises";
|
|
2167
2197
|
import { createReadStream } from "fs";
|
|
2168
2198
|
import { createHash as createHash2 } from "crypto";
|
|
2169
|
-
import * as
|
|
2199
|
+
import * as clack11 from "@clack/prompts";
|
|
2170
2200
|
import archiver from "archiver";
|
|
2171
2201
|
var POLL_INTERVAL_MS3 = 5e3;
|
|
2172
2202
|
var POLL_TIMEOUT_MS3 = 3e5;
|
|
@@ -2346,8 +2376,8 @@ async function startDirectDeployment(deploymentId, startBody) {
|
|
|
2346
2376
|
});
|
|
2347
2377
|
await response.json();
|
|
2348
2378
|
}
|
|
2349
|
-
async function pollDeployment(deploymentId,
|
|
2350
|
-
|
|
2379
|
+
async function pollDeployment(deploymentId, spinner9, syncBeforeRead) {
|
|
2380
|
+
spinner9?.message("Building and deploying...");
|
|
2351
2381
|
const startTime = Date.now();
|
|
2352
2382
|
let deployment = null;
|
|
2353
2383
|
while (Date.now() - startTime < POLL_TIMEOUT_MS3) {
|
|
@@ -2363,13 +2393,13 @@ async function pollDeployment(deploymentId, spinner8, syncBeforeRead) {
|
|
|
2363
2393
|
break;
|
|
2364
2394
|
}
|
|
2365
2395
|
if (status === "ERROR" || status === "CANCELED") {
|
|
2366
|
-
|
|
2396
|
+
spinner9?.stop("Deployment failed");
|
|
2367
2397
|
throw new CLIError(
|
|
2368
2398
|
getDeploymentError(deployment.metadata) ?? `Deployment failed with status: ${deployment.status}`
|
|
2369
2399
|
);
|
|
2370
2400
|
}
|
|
2371
2401
|
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
2372
|
-
|
|
2402
|
+
spinner9?.message(`Building and deploying... (${elapsed}s, status: ${deployment.status})`);
|
|
2373
2403
|
} catch (err) {
|
|
2374
2404
|
if (err instanceof CLIError) throw err;
|
|
2375
2405
|
}
|
|
@@ -2379,20 +2409,20 @@ async function pollDeployment(deploymentId, spinner8, syncBeforeRead) {
|
|
|
2379
2409
|
return { deploymentId, deployment, isReady, liveUrl };
|
|
2380
2410
|
}
|
|
2381
2411
|
async function deployProjectDirect(opts, config) {
|
|
2382
|
-
const { sourceDir, startBody = {}, spinner:
|
|
2383
|
-
|
|
2412
|
+
const { sourceDir, startBody = {}, spinner: spinner9 } = opts;
|
|
2413
|
+
spinner9?.start("Scanning source files...");
|
|
2384
2414
|
const localFiles = await collectDeploymentFiles(sourceDir);
|
|
2385
2415
|
if (localFiles.length === 0) {
|
|
2386
2416
|
throw new CLIError("No deployable files found in the source directory.");
|
|
2387
2417
|
}
|
|
2388
|
-
|
|
2418
|
+
spinner9?.message("Creating deployment...");
|
|
2389
2419
|
const createResult = await createDirectDeploymentSession(
|
|
2390
2420
|
config,
|
|
2391
2421
|
localFiles.map(({ path: relativePath, sha, size }) => ({ path: relativePath, sha, size }))
|
|
2392
2422
|
);
|
|
2393
2423
|
const localFileByPath = new Map(localFiles.map((file) => [file.path, file]));
|
|
2394
2424
|
const pendingFiles = createResult.files.filter((file) => !file.uploadedAt);
|
|
2395
|
-
|
|
2425
|
+
spinner9?.message(`Uploading ${pendingFiles.length} file${pendingFiles.length === 1 ? "" : "s"}...`);
|
|
2396
2426
|
await runWithConcurrency(pendingFiles, DIRECT_UPLOAD_CONCURRENCY, async (manifestFile) => {
|
|
2397
2427
|
const localFile = localFileByPath.get(manifestFile.path);
|
|
2398
2428
|
if (!localFile) {
|
|
@@ -2403,18 +2433,18 @@ async function deployProjectDirect(opts, config) {
|
|
|
2403
2433
|
}
|
|
2404
2434
|
await uploadDirectDeploymentFile(createResult.id, manifestFile, localFile);
|
|
2405
2435
|
});
|
|
2406
|
-
|
|
2436
|
+
spinner9?.message("Starting deployment...");
|
|
2407
2437
|
await startDirectDeployment(createResult.id, startBody);
|
|
2408
|
-
return await pollDeployment(createResult.id,
|
|
2438
|
+
return await pollDeployment(createResult.id, spinner9, !isInsforgeCloudOssHost(config.oss_host));
|
|
2409
2439
|
}
|
|
2410
2440
|
async function deployProjectLegacy(opts) {
|
|
2411
|
-
const { sourceDir, startBody = {}, spinner:
|
|
2412
|
-
|
|
2441
|
+
const { sourceDir, startBody = {}, spinner: spinner9 } = opts;
|
|
2442
|
+
spinner9?.message("Creating deployment...");
|
|
2413
2443
|
const createRes = await ossFetch("/api/deployments", { method: "POST" });
|
|
2414
2444
|
const { id: deploymentId, uploadUrl, uploadFields } = await createRes.json();
|
|
2415
|
-
|
|
2445
|
+
spinner9?.message("Compressing source files...");
|
|
2416
2446
|
const zipBuffer = await createZipBuffer(sourceDir);
|
|
2417
|
-
|
|
2447
|
+
spinner9?.message("Uploading...");
|
|
2418
2448
|
const formData = new FormData();
|
|
2419
2449
|
for (const [key, value] of Object.entries(uploadFields)) {
|
|
2420
2450
|
formData.append(key, value);
|
|
@@ -2425,13 +2455,13 @@ async function deployProjectLegacy(opts) {
|
|
|
2425
2455
|
const uploadErr = await uploadRes.text();
|
|
2426
2456
|
throw new CLIError(`Failed to upload: ${uploadErr}`);
|
|
2427
2457
|
}
|
|
2428
|
-
|
|
2458
|
+
spinner9?.message("Starting deployment...");
|
|
2429
2459
|
const startRes = await ossFetch(`/api/deployments/${deploymentId}/start`, {
|
|
2430
2460
|
method: "POST",
|
|
2431
2461
|
body: JSON.stringify(startBody)
|
|
2432
2462
|
});
|
|
2433
2463
|
await startRes.json();
|
|
2434
|
-
return await pollDeployment(deploymentId,
|
|
2464
|
+
return await pollDeployment(deploymentId, spinner9, false);
|
|
2435
2465
|
}
|
|
2436
2466
|
async function deployProject(opts) {
|
|
2437
2467
|
const config = getProjectConfig();
|
|
@@ -2466,7 +2496,7 @@ function registerDeploymentsDeployCommand(deploymentsCmd2) {
|
|
|
2466
2496
|
`"${dirName}" is an excluded directory and cannot be used as a deploy source. Please specify your project root or output directory instead.`
|
|
2467
2497
|
);
|
|
2468
2498
|
}
|
|
2469
|
-
const
|
|
2499
|
+
const spinner9 = !json ? clack11.spinner() : null;
|
|
2470
2500
|
const startBody = {};
|
|
2471
2501
|
if (opts.env) {
|
|
2472
2502
|
try {
|
|
@@ -2492,19 +2522,19 @@ function registerDeploymentsDeployCommand(deploymentsCmd2) {
|
|
|
2492
2522
|
throw new CLIError("Invalid --meta JSON.");
|
|
2493
2523
|
}
|
|
2494
2524
|
}
|
|
2495
|
-
const result = await deployProject({ sourceDir, startBody, spinner:
|
|
2525
|
+
const result = await deployProject({ sourceDir, startBody, spinner: spinner9 });
|
|
2496
2526
|
if (result.isReady) {
|
|
2497
|
-
|
|
2527
|
+
spinner9?.stop("Deployment complete");
|
|
2498
2528
|
if (json) {
|
|
2499
2529
|
outputJson(result.deployment);
|
|
2500
2530
|
} else {
|
|
2501
2531
|
if (result.liveUrl) {
|
|
2502
|
-
|
|
2532
|
+
clack11.log.success(`Live at: ${result.liveUrl}`);
|
|
2503
2533
|
}
|
|
2504
|
-
|
|
2534
|
+
clack11.log.info(`Deployment ID: ${result.deploymentId}`);
|
|
2505
2535
|
}
|
|
2506
2536
|
} else {
|
|
2507
|
-
|
|
2537
|
+
spinner9?.stop("Deployment is still building");
|
|
2508
2538
|
if (json) {
|
|
2509
2539
|
outputJson({
|
|
2510
2540
|
id: result.deploymentId,
|
|
@@ -2512,9 +2542,9 @@ function registerDeploymentsDeployCommand(deploymentsCmd2) {
|
|
|
2512
2542
|
timedOut: true
|
|
2513
2543
|
});
|
|
2514
2544
|
} else {
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2545
|
+
clack11.log.info(`Deployment ID: ${result.deploymentId}`);
|
|
2546
|
+
clack11.log.warn("Deployment did not finish within 5 minutes.");
|
|
2547
|
+
clack11.log.info(`Check status with: npx @insforge/cli deployments status ${result.deploymentId}`);
|
|
2518
2548
|
}
|
|
2519
2549
|
}
|
|
2520
2550
|
await reportCliUsage("cli.deployments.deploy", true);
|
|
@@ -2530,9 +2560,6 @@ var execAsync2 = promisify3(exec2);
|
|
|
2530
2560
|
var execFileAsync2 = promisify3(execFile2);
|
|
2531
2561
|
var SAFE_REPO_PATTERN2 = /^(https?:\/\/|git@)[A-Za-z0-9._:/@~+-]+(\.git)?$/;
|
|
2532
2562
|
var SAFE_BRANCH_PATTERN2 = /^[A-Za-z0-9._/-]+$/;
|
|
2533
|
-
function buildOssHost(appkey, region) {
|
|
2534
|
-
return `https://${appkey}.${region}.insforge.app`;
|
|
2535
|
-
}
|
|
2536
2563
|
async function waitForProjectActive(projectId, apiUrl, timeoutMs = 12e4) {
|
|
2537
2564
|
const start = Date.now();
|
|
2538
2565
|
while (Date.now() - start < timeoutMs) {
|
|
@@ -2647,7 +2674,7 @@ function registerCreateCommand(program2) {
|
|
|
2647
2674
|
await requireAuth(apiUrl, false);
|
|
2648
2675
|
if (!json) {
|
|
2649
2676
|
await animateBanner();
|
|
2650
|
-
|
|
2677
|
+
clack12.intro("Let's build something great");
|
|
2651
2678
|
}
|
|
2652
2679
|
let orgId = opts.orgId;
|
|
2653
2680
|
if (!orgId) {
|
|
@@ -2657,7 +2684,7 @@ function registerCreateCommand(program2) {
|
|
|
2657
2684
|
}
|
|
2658
2685
|
if (orgs.length === 1) {
|
|
2659
2686
|
orgId = orgs[0].id;
|
|
2660
|
-
if (!json)
|
|
2687
|
+
if (!json) clack12.log.info(`Using organization: ${orgs[0].name}`);
|
|
2661
2688
|
} else {
|
|
2662
2689
|
if (json) {
|
|
2663
2690
|
throw new CLIError("Multiple organizations found. Specify --org-id.");
|
|
@@ -2770,7 +2797,7 @@ function registerCreateCommand(program2) {
|
|
|
2770
2797
|
process.chdir(projectDir);
|
|
2771
2798
|
}
|
|
2772
2799
|
let projectLinked = false;
|
|
2773
|
-
const s = !json ?
|
|
2800
|
+
const s = !json ? clack12.spinner() : null;
|
|
2774
2801
|
try {
|
|
2775
2802
|
s?.start("Creating project...");
|
|
2776
2803
|
const project = await createProject(orgId, projectName, opts.region, apiUrl);
|
|
@@ -2798,7 +2825,7 @@ function registerCreateCommand(program2) {
|
|
|
2798
2825
|
try {
|
|
2799
2826
|
const anonKey = await getAnonKey();
|
|
2800
2827
|
if (!anonKey) {
|
|
2801
|
-
if (!json)
|
|
2828
|
+
if (!json) clack12.log.warn("Could not retrieve anon key. You can add it to .env.local manually.");
|
|
2802
2829
|
} else {
|
|
2803
2830
|
const envPath = path4.join(process.cwd(), ".env.local");
|
|
2804
2831
|
const envContent = [
|
|
@@ -2809,16 +2836,16 @@ function registerCreateCommand(program2) {
|
|
|
2809
2836
|
].join("\n");
|
|
2810
2837
|
await fs4.writeFile(envPath, envContent, { flag: "wx" });
|
|
2811
2838
|
if (!json) {
|
|
2812
|
-
|
|
2839
|
+
clack12.log.success("Created .env.local with your InsForge credentials");
|
|
2813
2840
|
}
|
|
2814
2841
|
}
|
|
2815
2842
|
} catch (err) {
|
|
2816
2843
|
const error = err;
|
|
2817
2844
|
if (!json) {
|
|
2818
2845
|
if (error.code === "EEXIST") {
|
|
2819
|
-
|
|
2846
|
+
clack12.log.warn(".env.local already exists; skipping InsForge key seeding.");
|
|
2820
2847
|
} else {
|
|
2821
|
-
|
|
2848
|
+
clack12.log.warn(`Failed to create .env.local: ${error.message}`);
|
|
2822
2849
|
}
|
|
2823
2850
|
}
|
|
2824
2851
|
}
|
|
@@ -2827,12 +2854,12 @@ function registerCreateCommand(program2) {
|
|
|
2827
2854
|
try {
|
|
2828
2855
|
const result = await applyAuthProvider(opts.auth, process.cwd(), projectConfig, json);
|
|
2829
2856
|
if (!json) {
|
|
2830
|
-
|
|
2857
|
+
clack12.log.success(`Wired in ${opts.auth}: ${result.written.length} new, ${result.overwritten.length} replaced`);
|
|
2831
2858
|
}
|
|
2832
2859
|
} catch (err) {
|
|
2833
2860
|
const msg = `Failed to apply --auth ${opts.auth}: ${err.message}`;
|
|
2834
2861
|
if (json) console.error(JSON.stringify({ warning: msg }));
|
|
2835
|
-
else
|
|
2862
|
+
else clack12.log.warn(msg);
|
|
2836
2863
|
}
|
|
2837
2864
|
}
|
|
2838
2865
|
await installSkills(json);
|
|
@@ -2840,7 +2867,7 @@ function registerCreateCommand(program2) {
|
|
|
2840
2867
|
await reportCliUsage("cli.create", true, 6);
|
|
2841
2868
|
const templateDownloaded = hasTemplate ? await fs4.stat(path4.join(process.cwd(), "package.json")).catch(() => null) : null;
|
|
2842
2869
|
if (templateDownloaded) {
|
|
2843
|
-
const installSpinner = !json ?
|
|
2870
|
+
const installSpinner = !json ? clack12.spinner() : null;
|
|
2844
2871
|
installSpinner?.start("Installing dependencies...");
|
|
2845
2872
|
try {
|
|
2846
2873
|
await execAsync2("npm install", { cwd: process.cwd(), maxBuffer: 10 * 1024 * 1024 });
|
|
@@ -2848,8 +2875,8 @@ function registerCreateCommand(program2) {
|
|
|
2848
2875
|
} catch (err) {
|
|
2849
2876
|
installSpinner?.stop("Failed to install dependencies");
|
|
2850
2877
|
if (!json) {
|
|
2851
|
-
|
|
2852
|
-
|
|
2878
|
+
clack12.log.warn(`npm install failed: ${err.message}`);
|
|
2879
|
+
clack12.log.info("Run `npm install` manually to install dependencies.");
|
|
2853
2880
|
}
|
|
2854
2881
|
}
|
|
2855
2882
|
}
|
|
@@ -2865,7 +2892,7 @@ function registerCreateCommand(program2) {
|
|
|
2865
2892
|
if (envVars.length > 0) {
|
|
2866
2893
|
startBody.envVars = envVars;
|
|
2867
2894
|
}
|
|
2868
|
-
const deploySpinner =
|
|
2895
|
+
const deploySpinner = clack12.spinner();
|
|
2869
2896
|
const result = await deployProject({
|
|
2870
2897
|
sourceDir: process.cwd(),
|
|
2871
2898
|
startBody,
|
|
@@ -2876,12 +2903,12 @@ function registerCreateCommand(program2) {
|
|
|
2876
2903
|
liveUrl = result.liveUrl;
|
|
2877
2904
|
} else {
|
|
2878
2905
|
deploySpinner.stop("Deployment is still building");
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2906
|
+
clack12.log.info(`Deployment ID: ${result.deploymentId}`);
|
|
2907
|
+
clack12.log.warn("Deployment did not finish within 2 minutes.");
|
|
2908
|
+
clack12.log.info(`Check status with: npx @insforge/cli deployments status ${result.deploymentId}`);
|
|
2882
2909
|
}
|
|
2883
2910
|
} catch (err) {
|
|
2884
|
-
|
|
2911
|
+
clack12.log.warn(`Deploy failed: ${err.message}`);
|
|
2885
2912
|
}
|
|
2886
2913
|
}
|
|
2887
2914
|
}
|
|
@@ -2898,33 +2925,33 @@ function registerCreateCommand(program2) {
|
|
|
2898
2925
|
}
|
|
2899
2926
|
});
|
|
2900
2927
|
} else {
|
|
2901
|
-
|
|
2928
|
+
clack12.log.step(`Dashboard: ${dashboardUrl}`);
|
|
2902
2929
|
if (liveUrl) {
|
|
2903
|
-
|
|
2930
|
+
clack12.log.success(`Live site: ${liveUrl}`);
|
|
2904
2931
|
}
|
|
2905
2932
|
if (templateDownloaded) {
|
|
2906
2933
|
const steps = [
|
|
2907
2934
|
`cd ${dirName}`,
|
|
2908
2935
|
"npm run dev"
|
|
2909
2936
|
];
|
|
2910
|
-
|
|
2911
|
-
|
|
2937
|
+
clack12.note(steps.join("\n"), "Next steps");
|
|
2938
|
+
clack12.note("Open your coding agent (Claude Code, Codex, Cursor, etc.) to add new features.", "Keep building");
|
|
2912
2939
|
} else if (hasTemplate && !templateDownloaded) {
|
|
2913
|
-
|
|
2940
|
+
clack12.log.warn("Template download failed. You can retry or set up manually.");
|
|
2914
2941
|
} else {
|
|
2915
2942
|
const prompts = [
|
|
2916
2943
|
"Build a todo app with Google OAuth sign-in",
|
|
2917
2944
|
"Build an Instagram clone where users can upload photos, like, and comment",
|
|
2918
2945
|
"Build an AI chatbot with conversation history"
|
|
2919
2946
|
];
|
|
2920
|
-
|
|
2947
|
+
clack12.note(
|
|
2921
2948
|
`Open your coding agent (Claude Code, Codex, Cursor, etc.) and try:
|
|
2922
2949
|
|
|
2923
2950
|
${prompts.map((p) => `\u2022 "${p}"`).join("\n")}`,
|
|
2924
2951
|
"Start building"
|
|
2925
2952
|
);
|
|
2926
2953
|
}
|
|
2927
|
-
|
|
2954
|
+
clack12.outro("Done!");
|
|
2928
2955
|
}
|
|
2929
2956
|
} catch (err) {
|
|
2930
2957
|
if (!projectLinked && hasTemplate && projectDir !== originalCwd) {
|
|
@@ -2943,7 +2970,7 @@ ${prompts.map((p) => `\u2022 "${p}"`).join("\n")}`,
|
|
|
2943
2970
|
});
|
|
2944
2971
|
}
|
|
2945
2972
|
async function downloadTemplate(framework, projectConfig, projectName, json, _apiUrl) {
|
|
2946
|
-
const s = !json ?
|
|
2973
|
+
const s = !json ? clack12.spinner() : null;
|
|
2947
2974
|
s?.start("Downloading template...");
|
|
2948
2975
|
try {
|
|
2949
2976
|
const anonKey = await getAnonKey();
|
|
@@ -2974,13 +3001,13 @@ async function downloadTemplate(framework, projectConfig, projectName, json, _ap
|
|
|
2974
3001
|
} catch (err) {
|
|
2975
3002
|
s?.stop("Template download failed");
|
|
2976
3003
|
if (!json) {
|
|
2977
|
-
|
|
2978
|
-
|
|
3004
|
+
clack12.log.warn(`Failed to download template: ${err.message}`);
|
|
3005
|
+
clack12.log.info("You can manually set up the template later.");
|
|
2979
3006
|
}
|
|
2980
3007
|
}
|
|
2981
3008
|
}
|
|
2982
3009
|
async function downloadGitHubTemplate(templateName, projectConfig, json) {
|
|
2983
|
-
const s = !json ?
|
|
3010
|
+
const s = !json ? clack12.spinner() : null;
|
|
2984
3011
|
s?.start(`Downloading ${templateName} template...`);
|
|
2985
3012
|
const tempDir = path4.join(tmpdir2(), `insforge-template-${Date.now()}`);
|
|
2986
3013
|
try {
|
|
@@ -3029,7 +3056,7 @@ async function downloadGitHubTemplate(templateName, projectConfig, json) {
|
|
|
3029
3056
|
await fs4.writeFile(envLocalPath, envFinal, { flag: "wx" });
|
|
3030
3057
|
} catch (e) {
|
|
3031
3058
|
if (e.code === "EEXIST") {
|
|
3032
|
-
if (!json)
|
|
3059
|
+
if (!json) clack12.log.warn(".env.local already exists; skipping env seeding.");
|
|
3033
3060
|
} else {
|
|
3034
3061
|
throw e;
|
|
3035
3062
|
}
|
|
@@ -3039,7 +3066,7 @@ async function downloadGitHubTemplate(templateName, projectConfig, json) {
|
|
|
3039
3066
|
const migrationPath = path4.join(cwd, "migrations", "db_init.sql");
|
|
3040
3067
|
const migrationExists = await fs4.stat(migrationPath).catch(() => null);
|
|
3041
3068
|
if (migrationExists) {
|
|
3042
|
-
const dbSpinner = !json ?
|
|
3069
|
+
const dbSpinner = !json ? clack12.spinner() : null;
|
|
3043
3070
|
dbSpinner?.start("Running database migrations...");
|
|
3044
3071
|
try {
|
|
3045
3072
|
const sql = await fs4.readFile(migrationPath, "utf-8");
|
|
@@ -3048,8 +3075,8 @@ async function downloadGitHubTemplate(templateName, projectConfig, json) {
|
|
|
3048
3075
|
} catch (err) {
|
|
3049
3076
|
dbSpinner?.stop("Database migration failed");
|
|
3050
3077
|
if (!json) {
|
|
3051
|
-
|
|
3052
|
-
|
|
3078
|
+
clack12.log.warn(`Migration failed: ${err.message}`);
|
|
3079
|
+
clack12.log.info('You can run the migration manually: npx @insforge/cli db query --unrestricted "$(cat migrations/db_init.sql)"');
|
|
3053
3080
|
} else {
|
|
3054
3081
|
throw err;
|
|
3055
3082
|
}
|
|
@@ -3061,8 +3088,8 @@ async function downloadGitHubTemplate(templateName, projectConfig, json) {
|
|
|
3061
3088
|
if (json) {
|
|
3062
3089
|
console.error(JSON.stringify({ warning: msg }));
|
|
3063
3090
|
} else {
|
|
3064
|
-
|
|
3065
|
-
|
|
3091
|
+
clack12.log.warn(msg);
|
|
3092
|
+
clack12.log.info("You can manually clone from: https://github.com/InsForge/insforge-templates");
|
|
3066
3093
|
}
|
|
3067
3094
|
} finally {
|
|
3068
3095
|
await fs4.rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
@@ -3072,19 +3099,16 @@ async function downloadGitHubTemplate(templateName, projectConfig, json) {
|
|
|
3072
3099
|
|
|
3073
3100
|
// src/commands/projects/link.ts
|
|
3074
3101
|
var execAsync3 = promisify4(exec3);
|
|
3075
|
-
function buildOssHost2(appkey, region) {
|
|
3076
|
-
return `https://${appkey}.${region}.insforge.app`;
|
|
3077
|
-
}
|
|
3078
3102
|
async function runNpmInstall(startMessage = "Installing dependencies...") {
|
|
3079
|
-
const
|
|
3080
|
-
|
|
3103
|
+
const spinner9 = clack13.spinner();
|
|
3104
|
+
spinner9.start(startMessage);
|
|
3081
3105
|
try {
|
|
3082
3106
|
await execAsync3("npm install", { cwd: process.cwd(), maxBuffer: 10 * 1024 * 1024 });
|
|
3083
|
-
|
|
3107
|
+
spinner9.stop("Dependencies installed");
|
|
3084
3108
|
} catch (err) {
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3109
|
+
spinner9.stop("Failed to install dependencies");
|
|
3110
|
+
clack13.log.warn(`npm install failed: ${err.message}`);
|
|
3111
|
+
clack13.log.info("Run `npm install` manually to install dependencies.");
|
|
3088
3112
|
}
|
|
3089
3113
|
}
|
|
3090
3114
|
function registerProjectLinkCommand(program2) {
|
|
@@ -3163,11 +3187,11 @@ function registerProjectLinkCommand(program2) {
|
|
|
3163
3187
|
if (opts.auth) {
|
|
3164
3188
|
try {
|
|
3165
3189
|
const result = await applyAuthProvider(opts.auth, process.cwd(), projectConfig2, json);
|
|
3166
|
-
if (!json)
|
|
3190
|
+
if (!json) clack13.log.success(`Wired in ${opts.auth}: ${result.written.length} new, ${result.overwritten.length} replaced`);
|
|
3167
3191
|
} catch (err) {
|
|
3168
3192
|
const msg = `Failed to apply --auth ${opts.auth}: ${err.message}`;
|
|
3169
3193
|
if (json) console.error(JSON.stringify({ warning: msg }));
|
|
3170
|
-
else
|
|
3194
|
+
else clack13.log.warn(msg);
|
|
3171
3195
|
}
|
|
3172
3196
|
}
|
|
3173
3197
|
if (templateDownloaded && !json) {
|
|
@@ -3190,9 +3214,9 @@ function registerProjectLinkCommand(program2) {
|
|
|
3190
3214
|
`${pc2.bold("1.")} ${runCommand}`,
|
|
3191
3215
|
`${pc2.bold("2.")} Open ${pc2.cyan("Claude Code")} or ${pc2.cyan("Cursor")} and prompt your agent to add more features`
|
|
3192
3216
|
];
|
|
3193
|
-
|
|
3217
|
+
clack13.note(steps.join("\n"), "What's next");
|
|
3194
3218
|
} else {
|
|
3195
|
-
|
|
3219
|
+
clack13.log.warn("Template download failed. You can retry or set up manually.");
|
|
3196
3220
|
}
|
|
3197
3221
|
}
|
|
3198
3222
|
return;
|
|
@@ -3207,16 +3231,16 @@ function registerProjectLinkCommand(program2) {
|
|
|
3207
3231
|
try {
|
|
3208
3232
|
const result = await applyAuthProvider(opts.auth, process.cwd(), projectConfig2, json);
|
|
3209
3233
|
if (!json) {
|
|
3210
|
-
|
|
3234
|
+
clack13.log.success(`Wired in ${opts.auth}: ${result.written.length} new, ${result.overwritten.length} replaced`);
|
|
3211
3235
|
}
|
|
3212
3236
|
if (result.packageJsonPatched && !json) {
|
|
3213
3237
|
await runNpmInstall("Installing new dependencies...");
|
|
3214
3238
|
}
|
|
3215
|
-
if (!json)
|
|
3239
|
+
if (!json) clack13.note(result.nextSteps, "What's next");
|
|
3216
3240
|
} catch (err) {
|
|
3217
3241
|
const msg = `Failed to apply --auth ${opts.auth}: ${err.message}`;
|
|
3218
3242
|
if (json) console.error(JSON.stringify({ warning: msg }));
|
|
3219
|
-
else
|
|
3243
|
+
else clack13.log.warn(msg);
|
|
3220
3244
|
}
|
|
3221
3245
|
}
|
|
3222
3246
|
trackCommand("link", "oss-org", { direct: true });
|
|
@@ -3246,7 +3270,7 @@ function registerProjectLinkCommand(program2) {
|
|
|
3246
3270
|
}
|
|
3247
3271
|
if (orgs.length === 1) {
|
|
3248
3272
|
orgId = orgs[0].id;
|
|
3249
|
-
if (!json)
|
|
3273
|
+
if (!json) clack13.log.info(`Using organization: ${orgs[0].name}`);
|
|
3250
3274
|
} else {
|
|
3251
3275
|
if (json) {
|
|
3252
3276
|
throw new CLIError("Multiple organizations found. Specify --org-id.");
|
|
@@ -3308,7 +3332,7 @@ function registerProjectLinkCommand(program2) {
|
|
|
3308
3332
|
appkey: project.appkey,
|
|
3309
3333
|
region: project.region,
|
|
3310
3334
|
api_key: apiKey,
|
|
3311
|
-
oss_host:
|
|
3335
|
+
oss_host: buildOssHost(project.appkey, project.region)
|
|
3312
3336
|
};
|
|
3313
3337
|
if (!opts.template) {
|
|
3314
3338
|
saveProjectConfig(projectConfig);
|
|
@@ -3357,11 +3381,11 @@ function registerProjectLinkCommand(program2) {
|
|
|
3357
3381
|
if (opts.auth) {
|
|
3358
3382
|
try {
|
|
3359
3383
|
const result = await applyAuthProvider(opts.auth, process.cwd(), projectConfig, json);
|
|
3360
|
-
if (!json)
|
|
3384
|
+
if (!json) clack13.log.success(`Wired in ${opts.auth}: ${result.written.length} new, ${result.overwritten.length} replaced`);
|
|
3361
3385
|
} catch (err) {
|
|
3362
3386
|
const msg = `Failed to apply --auth ${opts.auth}: ${err.message}`;
|
|
3363
3387
|
if (json) console.error(JSON.stringify({ warning: msg }));
|
|
3364
|
-
else
|
|
3388
|
+
else clack13.log.warn(msg);
|
|
3365
3389
|
}
|
|
3366
3390
|
}
|
|
3367
3391
|
if (templateDownloaded && !json) {
|
|
@@ -3371,16 +3395,16 @@ function registerProjectLinkCommand(program2) {
|
|
|
3371
3395
|
await reportCliUsage("cli.link", true, 6, projectConfig);
|
|
3372
3396
|
if (!json) {
|
|
3373
3397
|
const dashboardUrl = `${getFrontendUrl()}/dashboard/project/${project.id}`;
|
|
3374
|
-
|
|
3398
|
+
clack13.log.step(`Dashboard: ${pc2.underline(dashboardUrl)}`);
|
|
3375
3399
|
if (templateDownloaded) {
|
|
3376
3400
|
const runCommand = `${pc2.cyan("cd")} ${pc2.green(dirName)} ${pc2.dim("&&")} ${pc2.cyan("npm run dev")}`;
|
|
3377
3401
|
const steps = [
|
|
3378
3402
|
`${pc2.bold("1.")} ${runCommand}`,
|
|
3379
3403
|
`${pc2.bold("2.")} Open ${pc2.cyan("Claude Code")} or ${pc2.cyan("Cursor")} and prompt your agent to add more features`
|
|
3380
3404
|
];
|
|
3381
|
-
|
|
3405
|
+
clack13.note(steps.join("\n"), "What's next");
|
|
3382
3406
|
} else {
|
|
3383
|
-
|
|
3407
|
+
clack13.log.warn("Template download failed. You can retry or set up manually.");
|
|
3384
3408
|
}
|
|
3385
3409
|
}
|
|
3386
3410
|
} else {
|
|
@@ -3388,29 +3412,29 @@ function registerProjectLinkCommand(program2) {
|
|
|
3388
3412
|
try {
|
|
3389
3413
|
const result = await applyAuthProvider(opts.auth, process.cwd(), projectConfig, json);
|
|
3390
3414
|
if (!json) {
|
|
3391
|
-
|
|
3415
|
+
clack13.log.success(`Wired in ${opts.auth}: ${result.written.length} new, ${result.overwritten.length} replaced`);
|
|
3392
3416
|
}
|
|
3393
3417
|
if (result.packageJsonPatched && !json) {
|
|
3394
3418
|
await runNpmInstall("Installing new dependencies...");
|
|
3395
3419
|
}
|
|
3396
|
-
if (!json)
|
|
3420
|
+
if (!json) clack13.note(result.nextSteps, "What's next");
|
|
3397
3421
|
} catch (err) {
|
|
3398
3422
|
const msg = `Failed to apply --auth ${opts.auth}: ${err.message}`;
|
|
3399
3423
|
if (json) console.error(JSON.stringify({ warning: msg }));
|
|
3400
|
-
else
|
|
3424
|
+
else clack13.log.warn(msg);
|
|
3401
3425
|
}
|
|
3402
3426
|
}
|
|
3403
3427
|
await installSkills(json);
|
|
3404
3428
|
await reportCliUsage("cli.link", true, 6, projectConfig);
|
|
3405
3429
|
if (!json) {
|
|
3406
3430
|
const dashboardUrl = `${getFrontendUrl()}/dashboard/project/${project.id}`;
|
|
3407
|
-
|
|
3431
|
+
clack13.log.step(`Dashboard: ${dashboardUrl}`);
|
|
3408
3432
|
const prompts = [
|
|
3409
3433
|
"Build a todo app with Google OAuth sign-in",
|
|
3410
3434
|
"Build an Instagram clone where users can upload photos, like, and comment",
|
|
3411
3435
|
"Build an AI chatbot with conversation history and deploy it to a live URL"
|
|
3412
3436
|
];
|
|
3413
|
-
|
|
3437
|
+
clack13.note(
|
|
3414
3438
|
`Open your coding agent (Claude Code, Codex, Cursor, etc.) and try:
|
|
3415
3439
|
|
|
3416
3440
|
${prompts.map((p) => `\u2022 "${p}"`).join("\n")}`,
|
|
@@ -4545,7 +4569,7 @@ function registerFunctionsCodeCommand(functionsCmd2) {
|
|
|
4545
4569
|
}
|
|
4546
4570
|
|
|
4547
4571
|
// src/commands/functions/delete.ts
|
|
4548
|
-
import * as
|
|
4572
|
+
import * as clack14 from "@clack/prompts";
|
|
4549
4573
|
function registerFunctionsDeleteCommand(functionsCmd2) {
|
|
4550
4574
|
functionsCmd2.command("delete <slug>").description("Delete an edge function").action(async (slug, _opts, cmd) => {
|
|
4551
4575
|
const { json, yes } = getRootOpts(cmd);
|
|
@@ -4556,7 +4580,7 @@ function registerFunctionsDeleteCommand(functionsCmd2) {
|
|
|
4556
4580
|
message: `Delete function "${slug}"? This cannot be undone.`
|
|
4557
4581
|
});
|
|
4558
4582
|
if (isCancel2(confirmed) || !confirmed) {
|
|
4559
|
-
|
|
4583
|
+
clack14.log.info("Cancelled.");
|
|
4560
4584
|
return;
|
|
4561
4585
|
}
|
|
4562
4586
|
}
|
|
@@ -6285,7 +6309,7 @@ function formatSize2(gb) {
|
|
|
6285
6309
|
|
|
6286
6310
|
// src/commands/diagnose/index.ts
|
|
6287
6311
|
import * as os from "os";
|
|
6288
|
-
import * as
|
|
6312
|
+
import * as clack15 from "@clack/prompts";
|
|
6289
6313
|
|
|
6290
6314
|
// src/commands/diagnose/metrics.ts
|
|
6291
6315
|
var METRIC_LABELS = {
|
|
@@ -6826,10 +6850,10 @@ function registerDiagnoseCommands(diagnoseCmd2) {
|
|
|
6826
6850
|
if (question.length === 0 || question.length > 2e3) {
|
|
6827
6851
|
throw new CLIError("Question must be between 1 and 2000 characters.");
|
|
6828
6852
|
}
|
|
6829
|
-
const s = !json ?
|
|
6853
|
+
const s = !json ? clack15.spinner() : null;
|
|
6830
6854
|
s?.start("Collecting diagnostic data...");
|
|
6831
6855
|
const data2 = await collectDiagnosticData(projectId, ossMode, apiUrl);
|
|
6832
|
-
const cliVersion = "0.1.
|
|
6856
|
+
const cliVersion = "0.1.70";
|
|
6833
6857
|
s?.stop("Data collected");
|
|
6834
6858
|
if (!json) {
|
|
6835
6859
|
console.log(`
|
|
@@ -6962,9 +6986,9 @@ function registerDiagnoseCommands(diagnoseCmd2) {
|
|
|
6962
6986
|
void 0,
|
|
6963
6987
|
apiUrl
|
|
6964
6988
|
);
|
|
6965
|
-
|
|
6989
|
+
clack15.log.success("Thanks for your feedback!");
|
|
6966
6990
|
} catch {
|
|
6967
|
-
|
|
6991
|
+
clack15.log.warn("Failed to submit rating.");
|
|
6968
6992
|
}
|
|
6969
6993
|
}
|
|
6970
6994
|
}
|
|
@@ -8300,7 +8324,7 @@ async function showInteractiveMenu() {
|
|
|
8300
8324
|
} catch {
|
|
8301
8325
|
}
|
|
8302
8326
|
console.log(INSFORGE_LOGO);
|
|
8303
|
-
|
|
8327
|
+
clack16.intro(`InsForge CLI v${pkg.version}`);
|
|
8304
8328
|
const options = [];
|
|
8305
8329
|
if (!isLoggedIn) {
|
|
8306
8330
|
options.push({ value: "login", label: "Log in to InsForge" });
|
|
@@ -8321,7 +8345,7 @@ async function showInteractiveMenu() {
|
|
|
8321
8345
|
options
|
|
8322
8346
|
});
|
|
8323
8347
|
if (isCancel2(action)) {
|
|
8324
|
-
|
|
8348
|
+
clack16.cancel("Bye!");
|
|
8325
8349
|
process.exit(0);
|
|
8326
8350
|
}
|
|
8327
8351
|
switch (action) {
|