@insforge/cli 0.1.7 → 0.1.9
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 +135 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import {
|
|
5
|
-
import { join as
|
|
4
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
5
|
+
import { join as join6, dirname } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { Command } from "commander";
|
|
8
|
-
|
|
9
|
-
// src/commands/login.ts
|
|
10
|
-
import * as clack3 from "@clack/prompts";
|
|
8
|
+
import * as clack13 from "@clack/prompts";
|
|
11
9
|
|
|
12
10
|
// src/lib/config.ts
|
|
13
11
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
@@ -86,6 +84,9 @@ function getAccessToken() {
|
|
|
86
84
|
return process.env.INSFORGE_ACCESS_TOKEN ?? getCredentials()?.access_token ?? null;
|
|
87
85
|
}
|
|
88
86
|
|
|
87
|
+
// src/commands/login.ts
|
|
88
|
+
import * as clack3 from "@clack/prompts";
|
|
89
|
+
|
|
89
90
|
// src/lib/errors.ts
|
|
90
91
|
var CLIError = class extends Error {
|
|
91
92
|
constructor(message, exitCode = 1, code) {
|
|
@@ -102,7 +103,7 @@ var AuthError = class extends CLIError {
|
|
|
102
103
|
};
|
|
103
104
|
var ProjectNotLinkedError = class extends CLIError {
|
|
104
105
|
constructor() {
|
|
105
|
-
super("No project linked. Run `insforge
|
|
106
|
+
super("No project linked. Run `insforge link` first.", 3, "PROJECT_NOT_LINKED");
|
|
106
107
|
}
|
|
107
108
|
};
|
|
108
109
|
function handleError(err, json) {
|
|
@@ -317,7 +318,19 @@ async function requireAuth(apiUrl) {
|
|
|
317
318
|
const creds = getCredentials();
|
|
318
319
|
if (creds && creds.access_token) return creds;
|
|
319
320
|
clack2.log.info("You need to log in to continue.");
|
|
320
|
-
|
|
321
|
+
for (; ; ) {
|
|
322
|
+
try {
|
|
323
|
+
return await performOAuthLogin(apiUrl);
|
|
324
|
+
} catch (err) {
|
|
325
|
+
if (!process.stdout.isTTY) throw err;
|
|
326
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
327
|
+
clack2.log.error(`Login failed: ${msg}`);
|
|
328
|
+
const retry = await clack2.confirm({ message: "Would you like to try again?" });
|
|
329
|
+
if (clack2.isCancel(retry) || !retry) {
|
|
330
|
+
throw new AuthError("Authentication required. Run `insforge login` to authenticate.");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
321
334
|
}
|
|
322
335
|
async function refreshAccessToken(apiUrl) {
|
|
323
336
|
const creds = getCredentials();
|
|
@@ -649,9 +662,38 @@ import * as clack6 from "@clack/prompts";
|
|
|
649
662
|
|
|
650
663
|
// src/lib/skills.ts
|
|
651
664
|
import { exec } from "child_process";
|
|
665
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, appendFileSync } from "fs";
|
|
666
|
+
import { join as join2 } from "path";
|
|
652
667
|
import { promisify } from "util";
|
|
653
668
|
import * as clack5 from "@clack/prompts";
|
|
654
669
|
var execAsync = promisify(exec);
|
|
670
|
+
var GITIGNORE_ENTRIES = [
|
|
671
|
+
".insforge",
|
|
672
|
+
".agent",
|
|
673
|
+
".agents",
|
|
674
|
+
".augment",
|
|
675
|
+
".claude",
|
|
676
|
+
".cline",
|
|
677
|
+
".github/copilot*",
|
|
678
|
+
".kilocode",
|
|
679
|
+
".qoder",
|
|
680
|
+
".qwen",
|
|
681
|
+
".roo",
|
|
682
|
+
".trae",
|
|
683
|
+
".windsurf"
|
|
684
|
+
];
|
|
685
|
+
function updateGitignore() {
|
|
686
|
+
const gitignorePath = join2(process.cwd(), ".gitignore");
|
|
687
|
+
const existing = existsSync2(gitignorePath) ? readFileSync2(gitignorePath, "utf-8") : "";
|
|
688
|
+
const lines = new Set(existing.split("\n").map((l) => l.trim()));
|
|
689
|
+
const missing = GITIGNORE_ENTRIES.filter((entry) => !lines.has(entry));
|
|
690
|
+
if (!missing.length) return;
|
|
691
|
+
const block = `
|
|
692
|
+
# InsForge & AI agent skills
|
|
693
|
+
${missing.join("\n")}
|
|
694
|
+
`;
|
|
695
|
+
appendFileSync(gitignorePath, block);
|
|
696
|
+
}
|
|
655
697
|
async function installSkills(json) {
|
|
656
698
|
try {
|
|
657
699
|
if (!json) clack5.log.info("Installing InsForge agent skills...");
|
|
@@ -663,6 +705,10 @@ async function installSkills(json) {
|
|
|
663
705
|
} catch {
|
|
664
706
|
if (!json) clack5.log.warn("Failed to install agent skills. You can run manually: npx skills add insforge/agent-skills");
|
|
665
707
|
}
|
|
708
|
+
try {
|
|
709
|
+
updateGitignore();
|
|
710
|
+
} catch {
|
|
711
|
+
}
|
|
666
712
|
}
|
|
667
713
|
|
|
668
714
|
// src/commands/projects/link.ts
|
|
@@ -1089,7 +1135,7 @@ function registerDbExportCommand(dbCmd2) {
|
|
|
1089
1135
|
}
|
|
1090
1136
|
|
|
1091
1137
|
// src/commands/db/import.ts
|
|
1092
|
-
import { readFileSync as
|
|
1138
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
1093
1139
|
import { basename } from "path";
|
|
1094
1140
|
function registerDbImportCommand(dbCmd2) {
|
|
1095
1141
|
dbCmd2.command("import <file>").description("Import database from a local SQL file").option("--truncate", "Truncate existing tables before import").action(async (file, opts, cmd) => {
|
|
@@ -1098,7 +1144,7 @@ function registerDbImportCommand(dbCmd2) {
|
|
|
1098
1144
|
await requireAuth();
|
|
1099
1145
|
const config = getProjectConfig();
|
|
1100
1146
|
if (!config) throw new ProjectNotLinkedError();
|
|
1101
|
-
const fileContent =
|
|
1147
|
+
const fileContent = readFileSync3(file);
|
|
1102
1148
|
const fileName = basename(file);
|
|
1103
1149
|
const formData = new FormData();
|
|
1104
1150
|
formData.append("file", new Blob([fileContent]), fileName);
|
|
@@ -1309,21 +1355,21 @@ function registerFunctionsCommands(functionsCmd2) {
|
|
|
1309
1355
|
}
|
|
1310
1356
|
|
|
1311
1357
|
// src/commands/functions/deploy.ts
|
|
1312
|
-
import { readFileSync as
|
|
1313
|
-
import { join as
|
|
1358
|
+
import { readFileSync as readFileSync4, existsSync as existsSync3 } from "fs";
|
|
1359
|
+
import { join as join3 } from "path";
|
|
1314
1360
|
function registerFunctionsDeployCommand(functionsCmd2) {
|
|
1315
1361
|
functionsCmd2.command("deploy <slug>").description("Deploy an edge function (create or update)").option("--file <path>", "Path to the function source file").option("--name <name>", "Function display name").option("--description <desc>", "Function description").action(async (slug, opts, cmd) => {
|
|
1316
1362
|
const { json } = getRootOpts(cmd);
|
|
1317
1363
|
try {
|
|
1318
1364
|
await requireAuth();
|
|
1319
|
-
const filePath = opts.file ??
|
|
1320
|
-
if (!
|
|
1365
|
+
const filePath = opts.file ?? join3(process.cwd(), "insforge", "functions", slug, "index.ts");
|
|
1366
|
+
if (!existsSync3(filePath)) {
|
|
1321
1367
|
throw new CLIError(
|
|
1322
1368
|
`Source file not found: ${filePath}
|
|
1323
|
-
Specify --file <path> or create ${
|
|
1369
|
+
Specify --file <path> or create ${join3("insforge", "functions", slug, "index.ts")}`
|
|
1324
1370
|
);
|
|
1325
1371
|
}
|
|
1326
|
-
const code =
|
|
1372
|
+
const code = readFileSync4(filePath, "utf-8");
|
|
1327
1373
|
const name = opts.name ?? slug;
|
|
1328
1374
|
const description = opts.description ?? "";
|
|
1329
1375
|
let exists = false;
|
|
@@ -1464,7 +1510,7 @@ function registerStorageBucketsCommand(storageCmd2) {
|
|
|
1464
1510
|
}
|
|
1465
1511
|
|
|
1466
1512
|
// src/commands/storage/upload.ts
|
|
1467
|
-
import { readFileSync as
|
|
1513
|
+
import { readFileSync as readFileSync5, existsSync as existsSync4 } from "fs";
|
|
1468
1514
|
import { basename as basename2 } from "path";
|
|
1469
1515
|
function registerStorageUploadCommand(storageCmd2) {
|
|
1470
1516
|
storageCmd2.command("upload <file>").description("Upload a file to a storage bucket").requiredOption("--bucket <name>", "Target bucket name").option("--key <objectKey>", "Object key (defaults to filename)").action(async (file, opts, cmd) => {
|
|
@@ -1473,10 +1519,10 @@ function registerStorageUploadCommand(storageCmd2) {
|
|
|
1473
1519
|
await requireAuth();
|
|
1474
1520
|
const config = getProjectConfig();
|
|
1475
1521
|
if (!config) throw new ProjectNotLinkedError();
|
|
1476
|
-
if (!
|
|
1522
|
+
if (!existsSync4(file)) {
|
|
1477
1523
|
throw new CLIError(`File not found: ${file}`);
|
|
1478
1524
|
}
|
|
1479
|
-
const fileContent =
|
|
1525
|
+
const fileContent = readFileSync5(file);
|
|
1480
1526
|
const objectKey = opts.key ?? basename2(file);
|
|
1481
1527
|
const bucketName = opts.bucket;
|
|
1482
1528
|
const formData = new FormData();
|
|
@@ -1508,7 +1554,7 @@ function registerStorageUploadCommand(storageCmd2) {
|
|
|
1508
1554
|
|
|
1509
1555
|
// src/commands/storage/download.ts
|
|
1510
1556
|
import { writeFileSync as writeFileSync3 } from "fs";
|
|
1511
|
-
import { join as
|
|
1557
|
+
import { join as join4, basename as basename3 } from "path";
|
|
1512
1558
|
function registerStorageDownloadCommand(storageCmd2) {
|
|
1513
1559
|
storageCmd2.command("download <objectKey>").description("Download a file from a storage bucket").requiredOption("--bucket <name>", "Source bucket name").option("--output <path>", "Output file path (defaults to current directory)").action(async (objectKey, opts, cmd) => {
|
|
1514
1560
|
const { json } = getRootOpts(cmd);
|
|
@@ -1528,7 +1574,7 @@ function registerStorageDownloadCommand(storageCmd2) {
|
|
|
1528
1574
|
throw new CLIError(err.error ?? `Download failed: ${res.status}`);
|
|
1529
1575
|
}
|
|
1530
1576
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
1531
|
-
const outputPath = opts.output ??
|
|
1577
|
+
const outputPath = opts.output ?? join4(process.cwd(), basename3(objectKey));
|
|
1532
1578
|
writeFileSync3(outputPath, buffer);
|
|
1533
1579
|
if (json) {
|
|
1534
1580
|
outputJson({ success: true, path: outputPath, size: buffer.length });
|
|
@@ -1572,10 +1618,10 @@ function registerStorageDeleteBucketCommand(storageCmd2) {
|
|
|
1572
1618
|
try {
|
|
1573
1619
|
await requireAuth();
|
|
1574
1620
|
if (!yes && !json) {
|
|
1575
|
-
const
|
|
1621
|
+
const confirm7 = await clack7.confirm({
|
|
1576
1622
|
message: `Delete bucket "${name}" and all its objects? This cannot be undone.`
|
|
1577
1623
|
});
|
|
1578
|
-
if (!
|
|
1624
|
+
if (!confirm7 || clack7.isCancel(confirm7)) {
|
|
1579
1625
|
process.exit(0);
|
|
1580
1626
|
}
|
|
1581
1627
|
}
|
|
@@ -2416,10 +2462,10 @@ function registerSecretsDeleteCommand(secretsCmd2) {
|
|
|
2416
2462
|
try {
|
|
2417
2463
|
await requireAuth();
|
|
2418
2464
|
if (!yes && !json) {
|
|
2419
|
-
const
|
|
2465
|
+
const confirm7 = await clack11.confirm({
|
|
2420
2466
|
message: `Delete secret "${key}"? This cannot be undone.`
|
|
2421
2467
|
});
|
|
2422
|
-
if (!
|
|
2468
|
+
if (!confirm7 || clack11.isCancel(confirm7)) {
|
|
2423
2469
|
process.exit(0);
|
|
2424
2470
|
}
|
|
2425
2471
|
}
|
|
@@ -2598,10 +2644,10 @@ function registerSchedulesDeleteCommand(schedulesCmd2) {
|
|
|
2598
2644
|
try {
|
|
2599
2645
|
await requireAuth();
|
|
2600
2646
|
if (!yes && !json) {
|
|
2601
|
-
const
|
|
2647
|
+
const confirm7 = await clack12.confirm({
|
|
2602
2648
|
message: `Delete schedule "${id}"? This cannot be undone.`
|
|
2603
2649
|
});
|
|
2604
|
-
if (!
|
|
2650
|
+
if (!confirm7 || clack12.isCancel(confirm7)) {
|
|
2605
2651
|
process.exit(0);
|
|
2606
2652
|
}
|
|
2607
2653
|
}
|
|
@@ -2701,7 +2747,7 @@ function registerLogsCommand(program2) {
|
|
|
2701
2747
|
|
|
2702
2748
|
// src/index.ts
|
|
2703
2749
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
2704
|
-
var pkg = JSON.parse(
|
|
2750
|
+
var pkg = JSON.parse(readFileSync6(join6(__dirname, "../package.json"), "utf-8"));
|
|
2705
2751
|
var INSFORGE_LOGO = `
|
|
2706
2752
|
\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
2707
2753
|
\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
|
|
@@ -2710,15 +2756,6 @@ var INSFORGE_LOGO = `
|
|
|
2710
2756
|
\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
2711
2757
|
\u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
2712
2758
|
`;
|
|
2713
|
-
function showLogoOnFirstRun() {
|
|
2714
|
-
if (process.argv.includes("--json")) return;
|
|
2715
|
-
const localDir = join5(process.cwd(), ".insforge");
|
|
2716
|
-
if (existsSync4(localDir)) return;
|
|
2717
|
-
console.log(INSFORGE_LOGO);
|
|
2718
|
-
console.log(" Welcome to InsForge CLI! Run `insforge login` to get started.\n");
|
|
2719
|
-
mkdirSync2(localDir, { recursive: true });
|
|
2720
|
-
}
|
|
2721
|
-
showLogoOnFirstRun();
|
|
2722
2759
|
var program = new Command();
|
|
2723
2760
|
program.name("insforge").description("InsForge CLI - Command line tool for InsForge platform").version(pkg.version);
|
|
2724
2761
|
program.option("--json", "Output in JSON format").option("--api-url <url>", "Override Platform API URL").option("-y, --yes", "Skip confirmation prompts");
|
|
@@ -2780,5 +2817,66 @@ registerSchedulesCreateCommand(schedulesCmd);
|
|
|
2780
2817
|
registerSchedulesUpdateCommand(schedulesCmd);
|
|
2781
2818
|
registerSchedulesDeleteCommand(schedulesCmd);
|
|
2782
2819
|
registerSchedulesLogsCommand(schedulesCmd);
|
|
2783
|
-
|
|
2820
|
+
if (process.argv.length <= 2 && process.stdout.isTTY) {
|
|
2821
|
+
await showInteractiveMenu();
|
|
2822
|
+
} else {
|
|
2823
|
+
program.parse();
|
|
2824
|
+
}
|
|
2825
|
+
async function showInteractiveMenu() {
|
|
2826
|
+
let isLoggedIn = false;
|
|
2827
|
+
let isLinked = false;
|
|
2828
|
+
try {
|
|
2829
|
+
isLoggedIn = !!getCredentials()?.access_token;
|
|
2830
|
+
} catch {
|
|
2831
|
+
}
|
|
2832
|
+
try {
|
|
2833
|
+
isLinked = !!getProjectConfig()?.project_id;
|
|
2834
|
+
} catch {
|
|
2835
|
+
}
|
|
2836
|
+
console.log(INSFORGE_LOGO);
|
|
2837
|
+
clack13.intro(`InsForge CLI v${pkg.version}`);
|
|
2838
|
+
const options = [];
|
|
2839
|
+
if (!isLoggedIn) {
|
|
2840
|
+
options.push({ value: "login", label: "Log in to InsForge" });
|
|
2841
|
+
}
|
|
2842
|
+
options.push(
|
|
2843
|
+
{ value: "create", label: "Create a new project", hint: isLoggedIn ? void 0 : "requires login" },
|
|
2844
|
+
{ value: "link", label: "Link an existing project", hint: isLoggedIn ? void 0 : "requires login" }
|
|
2845
|
+
);
|
|
2846
|
+
if (isLinked) {
|
|
2847
|
+
options.push({ value: "deploy", label: "Deploy your project" });
|
|
2848
|
+
}
|
|
2849
|
+
options.push(
|
|
2850
|
+
{ value: "docs", label: "View documentation" },
|
|
2851
|
+
{ value: "help", label: "Show all commands" }
|
|
2852
|
+
);
|
|
2853
|
+
const action = await clack13.select({
|
|
2854
|
+
message: "What would you like to do?",
|
|
2855
|
+
options
|
|
2856
|
+
});
|
|
2857
|
+
if (clack13.isCancel(action)) {
|
|
2858
|
+
clack13.cancel("Bye!");
|
|
2859
|
+
process.exit(0);
|
|
2860
|
+
}
|
|
2861
|
+
switch (action) {
|
|
2862
|
+
case "login":
|
|
2863
|
+
await program.parseAsync(["node", "insforge", "login"]);
|
|
2864
|
+
break;
|
|
2865
|
+
case "create":
|
|
2866
|
+
await program.parseAsync(["node", "insforge", "create"]);
|
|
2867
|
+
break;
|
|
2868
|
+
case "link":
|
|
2869
|
+
await program.parseAsync(["node", "insforge", "link"]);
|
|
2870
|
+
break;
|
|
2871
|
+
case "deploy":
|
|
2872
|
+
await program.parseAsync(["node", "insforge", "deployments", "deploy"]);
|
|
2873
|
+
break;
|
|
2874
|
+
case "docs":
|
|
2875
|
+
await program.parseAsync(["node", "insforge", "docs"]);
|
|
2876
|
+
break;
|
|
2877
|
+
case "help":
|
|
2878
|
+
program.help();
|
|
2879
|
+
break;
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2784
2882
|
//# sourceMappingURL=index.js.map
|