@insforge/cli 0.1.81 → 0.1.82
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 +63 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { readFileSync as readFileSync12 } from "fs";
|
|
5
|
-
import { join as
|
|
5
|
+
import { join as join14, dirname as dirname2 } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
import * as clack18 from "@clack/prompts";
|
|
@@ -2629,6 +2629,7 @@ var execAsync2 = promisify3(exec2);
|
|
|
2629
2629
|
var execFileAsync2 = promisify3(execFile2);
|
|
2630
2630
|
var SAFE_REPO_PATTERN2 = /^(https?:\/\/|git@)[A-Za-z0-9._:/@~+-]+(\.git)?$/;
|
|
2631
2631
|
var SAFE_BRANCH_PATTERN2 = /^[A-Za-z0-9._/-]+$/;
|
|
2632
|
+
var SAFE_MARKETPLACE_SLUG = /^[a-z0-9][a-z0-9-]{0,99}$/;
|
|
2632
2633
|
async function waitForProjectActive(projectId, apiUrl, timeoutMs = 12e4) {
|
|
2633
2634
|
const start = Date.now();
|
|
2634
2635
|
while (Date.now() - start < timeoutMs) {
|
|
@@ -2737,9 +2738,18 @@ async function copyDir(src, dest) {
|
|
|
2737
2738
|
}
|
|
2738
2739
|
}
|
|
2739
2740
|
function registerCreateCommand(program2) {
|
|
2740
|
-
program2.command("create").description("Create a new InsForge project").option("--name <name>", "Project name").option("--org-id <id>", "Organization ID").option("--region <region>", "Deployment region (us-east, us-west, eu-central, ap-southeast)").option("--template <template>", "Template to use: react, nextjs, chatbot, crm, e-commerce, todo, or empty").option("--auth <provider>", "Wire a third-party auth provider into the chosen template (currently: better-auth)").action(async (opts, cmd) => {
|
|
2741
|
+
program2.command("create").description("Create a new InsForge project").option("--name <name>", "Project name").option("--org-id <id>", "Organization ID").option("--region <region>", "Deployment region (us-east, us-west, eu-central, ap-southeast)").option("--template <template>", "Template to use: react, nextjs, chatbot, crm, e-commerce, todo, or empty").option("--marketplace <slug>", "Install a marketplace template by slug (browse: https://insforge.dev/templates)").option("--auth <provider>", "Wire a third-party auth provider into the chosen template (currently: better-auth)").action(async (opts, cmd) => {
|
|
2741
2742
|
const { json, apiUrl } = getRootOpts(cmd);
|
|
2742
2743
|
try {
|
|
2744
|
+
if (opts.marketplace && opts.template) {
|
|
2745
|
+
throw new CLIError("--marketplace and --template are mutually exclusive");
|
|
2746
|
+
}
|
|
2747
|
+
if (opts.marketplace && !SAFE_MARKETPLACE_SLUG.test(opts.marketplace)) {
|
|
2748
|
+
throw new CLIError(
|
|
2749
|
+
`Invalid --marketplace slug "${opts.marketplace}". Slugs must match ${SAFE_MARKETPLACE_SLUG}.
|
|
2750
|
+
Browse available templates: https://insforge.dev/templates`
|
|
2751
|
+
);
|
|
2752
|
+
}
|
|
2743
2753
|
await requireAuth(apiUrl, false);
|
|
2744
2754
|
if (!json) {
|
|
2745
2755
|
await animateBanner();
|
|
@@ -2796,6 +2806,9 @@ function registerCreateCommand(program2) {
|
|
|
2796
2806
|
if (template && !validTemplates.includes(template)) {
|
|
2797
2807
|
throw new CLIError(`Invalid template "${template}". Valid options: ${validTemplates.join(", ")}`);
|
|
2798
2808
|
}
|
|
2809
|
+
if (opts.marketplace) {
|
|
2810
|
+
template = opts.marketplace;
|
|
2811
|
+
}
|
|
2799
2812
|
if (!template) {
|
|
2800
2813
|
if (json) {
|
|
2801
2814
|
template = "empty";
|
|
@@ -2886,7 +2899,19 @@ function registerCreateCommand(program2) {
|
|
|
2886
2899
|
projectLinked = true;
|
|
2887
2900
|
s?.stop(`Project "${project.name}" created and linked`);
|
|
2888
2901
|
const githubTemplates = ["chatbot", "crm", "e-commerce", "nextjs", "react", "todo"];
|
|
2889
|
-
if (
|
|
2902
|
+
if (opts.marketplace) {
|
|
2903
|
+
const downloaded = await downloadGitHubTemplate(
|
|
2904
|
+
opts.marketplace,
|
|
2905
|
+
projectConfig,
|
|
2906
|
+
json
|
|
2907
|
+
);
|
|
2908
|
+
if (downloaded) {
|
|
2909
|
+
void reportMarketplaceDownload(
|
|
2910
|
+
opts.marketplace,
|
|
2911
|
+
apiUrl ?? "https://api.insforge.dev"
|
|
2912
|
+
);
|
|
2913
|
+
}
|
|
2914
|
+
} else if (githubTemplates.includes(template)) {
|
|
2890
2915
|
await downloadGitHubTemplate(template, projectConfig, json);
|
|
2891
2916
|
} else if (hasTemplate) {
|
|
2892
2917
|
await downloadTemplate(template, projectConfig, projectName, json, apiUrl);
|
|
@@ -3151,6 +3176,7 @@ async function downloadGitHubTemplate(templateName, projectConfig, json) {
|
|
|
3151
3176
|
}
|
|
3152
3177
|
}
|
|
3153
3178
|
}
|
|
3179
|
+
return true;
|
|
3154
3180
|
} catch (err) {
|
|
3155
3181
|
s?.stop(`${templateName} template download failed`);
|
|
3156
3182
|
const msg = `Failed to download ${templateName} template: ${err.message}`;
|
|
@@ -3160,11 +3186,25 @@ async function downloadGitHubTemplate(templateName, projectConfig, json) {
|
|
|
3160
3186
|
clack12.log.warn(msg);
|
|
3161
3187
|
clack12.log.info("You can manually clone from: https://github.com/InsForge/insforge-templates");
|
|
3162
3188
|
}
|
|
3189
|
+
return false;
|
|
3163
3190
|
} finally {
|
|
3164
3191
|
await fs4.rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
3165
3192
|
});
|
|
3166
3193
|
}
|
|
3167
3194
|
}
|
|
3195
|
+
async function reportMarketplaceDownload(slug, apiUrl) {
|
|
3196
|
+
try {
|
|
3197
|
+
const res = await fetch(`${apiUrl}/templates/v1/${encodeURIComponent(slug)}/downloads`, {
|
|
3198
|
+
method: "POST",
|
|
3199
|
+
headers: { "Content-Type": "application/json" },
|
|
3200
|
+
body: "{}"
|
|
3201
|
+
});
|
|
3202
|
+
if (!res.ok) {
|
|
3203
|
+
return;
|
|
3204
|
+
}
|
|
3205
|
+
} catch {
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3168
3208
|
|
|
3169
3209
|
// src/commands/projects/link.ts
|
|
3170
3210
|
var execAsync3 = promisify4(exec3);
|
|
@@ -4554,19 +4594,21 @@ function registerFunctionsCommands(functionsCmd2) {
|
|
|
4554
4594
|
|
|
4555
4595
|
// src/commands/functions/deploy.ts
|
|
4556
4596
|
import { readFileSync as readFileSync5, existsSync as existsSync6 } from "fs";
|
|
4557
|
-
|
|
4597
|
+
function resolveDeployFilePath(opts) {
|
|
4598
|
+
if (!opts.file) {
|
|
4599
|
+
throw new CLIError("Missing required option: --file <path>");
|
|
4600
|
+
}
|
|
4601
|
+
if (!existsSync6(opts.file)) {
|
|
4602
|
+
throw new CLIError(`Source file not found: ${opts.file}`);
|
|
4603
|
+
}
|
|
4604
|
+
return opts.file;
|
|
4605
|
+
}
|
|
4558
4606
|
function registerFunctionsDeployCommand(functionsCmd2) {
|
|
4559
4607
|
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) => {
|
|
4560
4608
|
const { json } = getRootOpts(cmd);
|
|
4561
4609
|
try {
|
|
4562
4610
|
await requireAuth();
|
|
4563
|
-
const filePath = opts
|
|
4564
|
-
if (!existsSync6(filePath)) {
|
|
4565
|
-
throw new CLIError(
|
|
4566
|
-
`Source file not found: ${filePath}
|
|
4567
|
-
Specify --file <path> or create ${join10("insforge", "functions", slug, "index.ts")}`
|
|
4568
|
-
);
|
|
4569
|
-
}
|
|
4611
|
+
const filePath = resolveDeployFilePath(opts);
|
|
4570
4612
|
const code = readFileSync5(filePath, "utf-8");
|
|
4571
4613
|
const name = opts.name ?? slug;
|
|
4572
4614
|
const description = opts.description ?? "";
|
|
@@ -4798,7 +4840,7 @@ function registerStorageUploadCommand(storageCmd2) {
|
|
|
4798
4840
|
|
|
4799
4841
|
// src/commands/storage/download.ts
|
|
4800
4842
|
import { writeFileSync as writeFileSync5 } from "fs";
|
|
4801
|
-
import { join as
|
|
4843
|
+
import { join as join10, basename as basename7 } from "path";
|
|
4802
4844
|
function registerStorageDownloadCommand(storageCmd2) {
|
|
4803
4845
|
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) => {
|
|
4804
4846
|
const { json } = getRootOpts(cmd);
|
|
@@ -4818,7 +4860,7 @@ function registerStorageDownloadCommand(storageCmd2) {
|
|
|
4818
4860
|
throw new CLIError(err.error ?? `Download failed: ${res.status}`);
|
|
4819
4861
|
}
|
|
4820
4862
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
4821
|
-
const outputPath = opts.output ??
|
|
4863
|
+
const outputPath = opts.output ?? join10(process.cwd(), basename7(objectKey));
|
|
4822
4864
|
writeFileSync5(outputPath, buffer);
|
|
4823
4865
|
if (json) {
|
|
4824
4866
|
outputJson({ success: true, path: outputPath, size: buffer.length });
|
|
@@ -5950,7 +5992,7 @@ function registerComputeEventsCommand(computeCmd2) {
|
|
|
5950
5992
|
|
|
5951
5993
|
// src/commands/compute/deploy.ts
|
|
5952
5994
|
import { existsSync as existsSync9 } from "fs";
|
|
5953
|
-
import { join as
|
|
5995
|
+
import { join as join12, resolve as resolve4 } from "path";
|
|
5954
5996
|
|
|
5955
5997
|
// src/lib/env-file.ts
|
|
5956
5998
|
import { readFileSync as readFileSync7 } from "fs";
|
|
@@ -5995,7 +6037,7 @@ function parseEnvFile(path6) {
|
|
|
5995
6037
|
// src/lib/flyctl.ts
|
|
5996
6038
|
import { spawn, spawnSync } from "child_process";
|
|
5997
6039
|
import { existsSync as existsSync8, writeFileSync as writeFileSync6, unlinkSync as unlinkSync3 } from "fs";
|
|
5998
|
-
import { join as
|
|
6040
|
+
import { join as join11 } from "path";
|
|
5999
6041
|
function ensureFlyctlAvailable() {
|
|
6000
6042
|
const r = spawnSync("flyctl", ["version"], {
|
|
6001
6043
|
encoding: "utf8",
|
|
@@ -6008,7 +6050,7 @@ function ensureFlyctlAvailable() {
|
|
|
6008
6050
|
}
|
|
6009
6051
|
}
|
|
6010
6052
|
function ensureFlyTomlStub(opts) {
|
|
6011
|
-
const path6 =
|
|
6053
|
+
const path6 = join11(opts.dir, "fly.toml");
|
|
6012
6054
|
if (existsSync8(path6)) {
|
|
6013
6055
|
return () => {
|
|
6014
6056
|
};
|
|
@@ -6196,7 +6238,7 @@ function registerComputeDeployCommand(computeCmd2) {
|
|
|
6196
6238
|
return;
|
|
6197
6239
|
}
|
|
6198
6240
|
const absDir = resolve4(dir);
|
|
6199
|
-
const dockerfilePath =
|
|
6241
|
+
const dockerfilePath = join12(absDir, "Dockerfile");
|
|
6200
6242
|
if (!existsSync9(dockerfilePath)) {
|
|
6201
6243
|
throw new CLIError(
|
|
6202
6244
|
`No Dockerfile at ${dockerfilePath}.
|
|
@@ -6976,7 +7018,7 @@ function registerDiagnoseCommands(diagnoseCmd2) {
|
|
|
6976
7018
|
const s = !json ? clack15.spinner() : null;
|
|
6977
7019
|
s?.start("Collecting diagnostic data...");
|
|
6978
7020
|
const data2 = await collectDiagnosticData(projectId, ossMode, apiUrl);
|
|
6979
|
-
const cliVersion = "0.1.
|
|
7021
|
+
const cliVersion = "0.1.82";
|
|
6980
7022
|
s?.stop("Data collected");
|
|
6981
7023
|
if (!json) {
|
|
6982
7024
|
console.log(`
|
|
@@ -9742,7 +9784,7 @@ function registerConfigCommand(program2) {
|
|
|
9742
9784
|
|
|
9743
9785
|
// src/commands/ai/setup.ts
|
|
9744
9786
|
import { appendFileSync as appendFileSync2, existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
|
|
9745
|
-
import { isAbsolute, join as
|
|
9787
|
+
import { isAbsolute, join as join13, relative as relative3, resolve as resolve8 } from "path";
|
|
9746
9788
|
import * as clack17 from "@clack/prompts";
|
|
9747
9789
|
import pc7 from "picocolors";
|
|
9748
9790
|
|
|
@@ -9918,7 +9960,7 @@ function ensureLocalEnvIgnored(cwd, envFile) {
|
|
|
9918
9960
|
if (!relEnvPath || relEnvPath.startsWith("..") || isAbsolute(relEnvPath)) {
|
|
9919
9961
|
return false;
|
|
9920
9962
|
}
|
|
9921
|
-
const gitignorePath =
|
|
9963
|
+
const gitignorePath = join13(cwd, ".gitignore");
|
|
9922
9964
|
const existing = existsSync12(gitignorePath) ? readFileSync11(gitignorePath, "utf-8") : "";
|
|
9923
9965
|
const lines = new Set(existing.split(/\r?\n/).map((line) => line.trim()));
|
|
9924
9966
|
const envBasename = envFile.replace(/\\/g, "/").split("/").pop() ?? envFile;
|
|
@@ -9940,7 +9982,7 @@ function registerAiCommands(aiCmd2) {
|
|
|
9940
9982
|
|
|
9941
9983
|
// src/index.ts
|
|
9942
9984
|
var __dirname = dirname2(fileURLToPath(import.meta.url));
|
|
9943
|
-
var pkg = JSON.parse(readFileSync12(
|
|
9985
|
+
var pkg = JSON.parse(readFileSync12(join14(__dirname, "../package.json"), "utf-8"));
|
|
9944
9986
|
var INSFORGE_LOGO = `
|
|
9945
9987
|
\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
|
|
9946
9988
|
\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
|