@insforge/cli 0.1.51 → 0.1.53-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +322 -28
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { readFileSync as
|
|
5
|
-
import { join as
|
|
4
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
5
|
+
import { join as join12, dirname } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
import * as clack11 from "@clack/prompts";
|
|
@@ -2000,6 +2000,7 @@ ${prompts.map((p) => `\u2022 "${p}"`).join("\n")}`,
|
|
|
2000
2000
|
throw err;
|
|
2001
2001
|
}
|
|
2002
2002
|
} catch (err) {
|
|
2003
|
+
await shutdownAnalytics();
|
|
2003
2004
|
handleError(err, json);
|
|
2004
2005
|
} finally {
|
|
2005
2006
|
await shutdownAnalytics();
|
|
@@ -2167,6 +2168,7 @@ function registerProjectLinkCommand(program2) {
|
|
|
2167
2168
|
return;
|
|
2168
2169
|
} catch (err) {
|
|
2169
2170
|
await reportCliUsage("cli.link_direct", false);
|
|
2171
|
+
await shutdownAnalytics();
|
|
2170
2172
|
handleError(err, json);
|
|
2171
2173
|
}
|
|
2172
2174
|
}
|
|
@@ -2346,6 +2348,7 @@ ${prompts.map((p) => `\u2022 "${p}"`).join("\n")}`,
|
|
|
2346
2348
|
}
|
|
2347
2349
|
} catch (err) {
|
|
2348
2350
|
await reportCliUsage("cli.link", false);
|
|
2351
|
+
await shutdownAnalytics();
|
|
2349
2352
|
handleError(err, json);
|
|
2350
2353
|
} finally {
|
|
2351
2354
|
await shutdownAnalytics();
|
|
@@ -2668,6 +2671,291 @@ function registerDbImportCommand(dbCmd2) {
|
|
|
2668
2671
|
});
|
|
2669
2672
|
}
|
|
2670
2673
|
|
|
2674
|
+
// src/commands/db/migrations.ts
|
|
2675
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
2676
|
+
import { join as join8 } from "path";
|
|
2677
|
+
|
|
2678
|
+
// src/lib/migrations.ts
|
|
2679
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
2680
|
+
import { join as join7 } from "path";
|
|
2681
|
+
var MIGRATION_FILENAME_REGEX = /^([1-9][0-9]*)_([a-z0-9-]+)\.sql$/;
|
|
2682
|
+
function parseMigrationFilename(filename) {
|
|
2683
|
+
const match = MIGRATION_FILENAME_REGEX.exec(filename);
|
|
2684
|
+
if (!match) {
|
|
2685
|
+
return null;
|
|
2686
|
+
}
|
|
2687
|
+
return {
|
|
2688
|
+
filename,
|
|
2689
|
+
sequenceNumber: Number(match[1]),
|
|
2690
|
+
name: match[2]
|
|
2691
|
+
};
|
|
2692
|
+
}
|
|
2693
|
+
function getMigrationsDir(cwd = process.cwd()) {
|
|
2694
|
+
return join7(cwd, ".insforge", "migrations");
|
|
2695
|
+
}
|
|
2696
|
+
function ensureMigrationsDir(cwd = process.cwd()) {
|
|
2697
|
+
const migrationsDir = getMigrationsDir(cwd);
|
|
2698
|
+
if (!existsSync3(migrationsDir)) {
|
|
2699
|
+
mkdirSync2(migrationsDir, { recursive: true });
|
|
2700
|
+
}
|
|
2701
|
+
return migrationsDir;
|
|
2702
|
+
}
|
|
2703
|
+
function listLocalMigrationFilenames(cwd = process.cwd()) {
|
|
2704
|
+
const migrationsDir = getMigrationsDir(cwd);
|
|
2705
|
+
if (!existsSync3(migrationsDir)) {
|
|
2706
|
+
return [];
|
|
2707
|
+
}
|
|
2708
|
+
return readdirSync(migrationsDir).sort((left, right) => left.localeCompare(right));
|
|
2709
|
+
}
|
|
2710
|
+
function parseStrictLocalMigrations(filenames) {
|
|
2711
|
+
const migrations = filenames.map((filename) => {
|
|
2712
|
+
const parsedMigration = parseMigrationFilename(filename);
|
|
2713
|
+
if (!parsedMigration) {
|
|
2714
|
+
throw new CLIError(
|
|
2715
|
+
`Invalid migration filename: ${filename}. Expected <sequence_number>_<migration-name>.sql.`
|
|
2716
|
+
);
|
|
2717
|
+
}
|
|
2718
|
+
return parsedMigration;
|
|
2719
|
+
});
|
|
2720
|
+
assertNoDuplicateMigrationSequences(migrations);
|
|
2721
|
+
return migrations.sort((left, right) => left.sequenceNumber - right.sequenceNumber);
|
|
2722
|
+
}
|
|
2723
|
+
function assertNoDuplicateMigrationSequences(migrations) {
|
|
2724
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2725
|
+
for (const migration of migrations) {
|
|
2726
|
+
if (seen.has(migration.sequenceNumber)) {
|
|
2727
|
+
throw new CLIError(`Duplicate local migration sequence found: ${migration.sequenceNumber}`);
|
|
2728
|
+
}
|
|
2729
|
+
seen.add(migration.sequenceNumber);
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
function getNextLocalMigrationSequence(migrations, latestRemoteSequenceNumber) {
|
|
2733
|
+
const orderedMigrations = [...migrations].sort((left, right) => left.sequenceNumber - right.sequenceNumber);
|
|
2734
|
+
assertNoDuplicateMigrationSequences(orderedMigrations);
|
|
2735
|
+
let expectedSequenceNumber = latestRemoteSequenceNumber + 1;
|
|
2736
|
+
for (const migration of orderedMigrations) {
|
|
2737
|
+
if (migration.sequenceNumber <= latestRemoteSequenceNumber) {
|
|
2738
|
+
continue;
|
|
2739
|
+
}
|
|
2740
|
+
if (migration.sequenceNumber !== expectedSequenceNumber) {
|
|
2741
|
+
throw new CLIError(
|
|
2742
|
+
`Local pending migrations must be contiguous after remote sequence ${latestRemoteSequenceNumber}.`
|
|
2743
|
+
);
|
|
2744
|
+
}
|
|
2745
|
+
expectedSequenceNumber += 1;
|
|
2746
|
+
}
|
|
2747
|
+
return expectedSequenceNumber;
|
|
2748
|
+
}
|
|
2749
|
+
function formatMigrationSql(statements) {
|
|
2750
|
+
return statements.map((statement) => statement.trim().replace(/;\s*$/u, "")).filter(Boolean).join(";\n\n").concat(statements.length > 0 ? ";\n" : "");
|
|
2751
|
+
}
|
|
2752
|
+
function findLocalMigrationBySequence(sequenceNumber, filenames) {
|
|
2753
|
+
const matches = filenames.map((filename) => parseMigrationFilename(filename)).filter(
|
|
2754
|
+
(migration) => migration !== null && migration.sequenceNumber === sequenceNumber
|
|
2755
|
+
);
|
|
2756
|
+
if (matches.length === 0) {
|
|
2757
|
+
throw new CLIError(`Local migration for sequence ${sequenceNumber} not found.`);
|
|
2758
|
+
}
|
|
2759
|
+
if (matches.length > 1) {
|
|
2760
|
+
throw new CLIError(
|
|
2761
|
+
`Multiple local migration files found for sequence ${sequenceNumber}.`
|
|
2762
|
+
);
|
|
2763
|
+
}
|
|
2764
|
+
return matches[0];
|
|
2765
|
+
}
|
|
2766
|
+
function resolveMigrationTarget(target, filenames) {
|
|
2767
|
+
if (/^[1-9][0-9]*$/u.test(target)) {
|
|
2768
|
+
return findLocalMigrationBySequence(Number(target), filenames);
|
|
2769
|
+
}
|
|
2770
|
+
const parsedTarget = parseMigrationFilename(target);
|
|
2771
|
+
if (!parsedTarget) {
|
|
2772
|
+
throw new CLIError(
|
|
2773
|
+
"Migration file names must match <sequence_number>_<migration-name>.sql."
|
|
2774
|
+
);
|
|
2775
|
+
}
|
|
2776
|
+
if (!filenames.includes(target)) {
|
|
2777
|
+
throw new CLIError(`Local migration file not found: ${target}`);
|
|
2778
|
+
}
|
|
2779
|
+
return findLocalMigrationBySequence(parsedTarget.sequenceNumber, filenames);
|
|
2780
|
+
}
|
|
2781
|
+
|
|
2782
|
+
// src/commands/db/migrations.ts
|
|
2783
|
+
function getLatestRemoteSequenceNumber(migrations) {
|
|
2784
|
+
return migrations.reduce(
|
|
2785
|
+
(latestSequenceNumber, migration) => Math.max(latestSequenceNumber, migration.sequenceNumber),
|
|
2786
|
+
0
|
|
2787
|
+
);
|
|
2788
|
+
}
|
|
2789
|
+
function buildMigrationFilename(sequenceNumber, name) {
|
|
2790
|
+
return `${sequenceNumber}_${name}.sql`;
|
|
2791
|
+
}
|
|
2792
|
+
function formatCreatedAt(createdAt) {
|
|
2793
|
+
const date = new Date(createdAt);
|
|
2794
|
+
return Number.isNaN(date.getTime()) ? createdAt : date.toLocaleString();
|
|
2795
|
+
}
|
|
2796
|
+
async function fetchRemoteMigrations() {
|
|
2797
|
+
const res = await ossFetch("/api/database/migrations");
|
|
2798
|
+
const raw = await res.json();
|
|
2799
|
+
return Array.isArray(raw.migrations) ? raw.migrations : [];
|
|
2800
|
+
}
|
|
2801
|
+
function assertValidMigrationName(name) {
|
|
2802
|
+
if (!/^[a-z0-9-]+$/u.test(name)) {
|
|
2803
|
+
throw new CLIError("Migration name must use lowercase letters, numbers, and hyphens only.");
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
function registerDbMigrationsCommand(dbCmd2) {
|
|
2807
|
+
const migrationsCmd = dbCmd2.command("migrations").description("Manage database migration files");
|
|
2808
|
+
migrationsCmd.command("list").description("List applied remote database migrations").action(async (_opts, cmd) => {
|
|
2809
|
+
const { json } = getRootOpts(cmd);
|
|
2810
|
+
try {
|
|
2811
|
+
await requireAuth();
|
|
2812
|
+
const migrations = await fetchRemoteMigrations();
|
|
2813
|
+
if (json) {
|
|
2814
|
+
outputJson({ migrations });
|
|
2815
|
+
} else if (migrations.length === 0) {
|
|
2816
|
+
console.log("No database migrations found.");
|
|
2817
|
+
} else {
|
|
2818
|
+
outputTable(
|
|
2819
|
+
["Sequence", "Name", "Created At"],
|
|
2820
|
+
migrations.map((migration) => [
|
|
2821
|
+
String(migration.sequenceNumber),
|
|
2822
|
+
migration.name,
|
|
2823
|
+
formatCreatedAt(migration.createdAt)
|
|
2824
|
+
])
|
|
2825
|
+
);
|
|
2826
|
+
}
|
|
2827
|
+
await reportCliUsage("cli.db.migrations.list", true);
|
|
2828
|
+
} catch (err) {
|
|
2829
|
+
await reportCliUsage("cli.db.migrations.list", false);
|
|
2830
|
+
handleError(err, json);
|
|
2831
|
+
}
|
|
2832
|
+
});
|
|
2833
|
+
migrationsCmd.command("fetch").description("Fetch applied remote migrations into .insforge/migrations/").action(async (_opts, cmd) => {
|
|
2834
|
+
const { json } = getRootOpts(cmd);
|
|
2835
|
+
try {
|
|
2836
|
+
await requireAuth();
|
|
2837
|
+
const migrations = await fetchRemoteMigrations();
|
|
2838
|
+
const migrationsDir = ensureMigrationsDir();
|
|
2839
|
+
const createdFiles = [];
|
|
2840
|
+
const skippedFiles = [];
|
|
2841
|
+
for (const migration of [...migrations].sort(
|
|
2842
|
+
(left, right) => left.sequenceNumber - right.sequenceNumber
|
|
2843
|
+
)) {
|
|
2844
|
+
const filename = buildMigrationFilename(
|
|
2845
|
+
migration.sequenceNumber,
|
|
2846
|
+
migration.name
|
|
2847
|
+
);
|
|
2848
|
+
const filePath = join8(migrationsDir, filename);
|
|
2849
|
+
if (existsSync4(filePath)) {
|
|
2850
|
+
skippedFiles.push(filename);
|
|
2851
|
+
continue;
|
|
2852
|
+
}
|
|
2853
|
+
writeFileSync3(filePath, formatMigrationSql(migration.statements));
|
|
2854
|
+
createdFiles.push(filename);
|
|
2855
|
+
}
|
|
2856
|
+
if (json) {
|
|
2857
|
+
outputJson({
|
|
2858
|
+
directory: migrationsDir,
|
|
2859
|
+
totalRemoteMigrations: migrations.length,
|
|
2860
|
+
createdFiles,
|
|
2861
|
+
skippedFiles
|
|
2862
|
+
});
|
|
2863
|
+
} else {
|
|
2864
|
+
outputSuccess(
|
|
2865
|
+
`Fetched ${migrations.length} remote migration(s) into ${migrationsDir}.`
|
|
2866
|
+
);
|
|
2867
|
+
console.log(`Created: ${createdFiles.length}`);
|
|
2868
|
+
console.log(`Skipped: ${skippedFiles.length}`);
|
|
2869
|
+
}
|
|
2870
|
+
await reportCliUsage("cli.db.migrations.fetch", true);
|
|
2871
|
+
} catch (err) {
|
|
2872
|
+
await reportCliUsage("cli.db.migrations.fetch", false);
|
|
2873
|
+
handleError(err, json);
|
|
2874
|
+
}
|
|
2875
|
+
});
|
|
2876
|
+
migrationsCmd.command("new <migration-name>").description("Create a new local migration file").action(async (migrationName, _opts, cmd) => {
|
|
2877
|
+
const { json } = getRootOpts(cmd);
|
|
2878
|
+
try {
|
|
2879
|
+
await requireAuth();
|
|
2880
|
+
assertValidMigrationName(migrationName);
|
|
2881
|
+
const migrations = await fetchRemoteMigrations();
|
|
2882
|
+
const latestRemoteSequenceNumber = getLatestRemoteSequenceNumber(migrations);
|
|
2883
|
+
const localMigrations = parseStrictLocalMigrations(listLocalMigrationFilenames());
|
|
2884
|
+
const nextSequenceNumber = getNextLocalMigrationSequence(
|
|
2885
|
+
localMigrations,
|
|
2886
|
+
latestRemoteSequenceNumber
|
|
2887
|
+
);
|
|
2888
|
+
const filename = buildMigrationFilename(nextSequenceNumber, migrationName);
|
|
2889
|
+
const migrationsDir = ensureMigrationsDir();
|
|
2890
|
+
const filePath = join8(migrationsDir, filename);
|
|
2891
|
+
if (existsSync4(filePath)) {
|
|
2892
|
+
throw new CLIError(`Migration file already exists: ${filename}`);
|
|
2893
|
+
}
|
|
2894
|
+
writeFileSync3(filePath, "");
|
|
2895
|
+
if (json) {
|
|
2896
|
+
outputJson({ filename, path: filePath, sequenceNumber: nextSequenceNumber });
|
|
2897
|
+
} else {
|
|
2898
|
+
outputSuccess(`Created migration file ${filename}`);
|
|
2899
|
+
}
|
|
2900
|
+
await reportCliUsage("cli.db.migrations.new", true);
|
|
2901
|
+
} catch (err) {
|
|
2902
|
+
await reportCliUsage("cli.db.migrations.new", false);
|
|
2903
|
+
handleError(err, json);
|
|
2904
|
+
}
|
|
2905
|
+
});
|
|
2906
|
+
migrationsCmd.command("up <target>").description("Apply exactly one local migration file").action(async (target, _opts, cmd) => {
|
|
2907
|
+
const { json } = getRootOpts(cmd);
|
|
2908
|
+
try {
|
|
2909
|
+
await requireAuth();
|
|
2910
|
+
const migrations = await fetchRemoteMigrations();
|
|
2911
|
+
const latestRemoteSequenceNumber = getLatestRemoteSequenceNumber(migrations);
|
|
2912
|
+
const filenames = listLocalMigrationFilenames();
|
|
2913
|
+
const targetMigration = resolveMigrationTarget(target, filenames);
|
|
2914
|
+
if (targetMigration.sequenceNumber <= latestRemoteSequenceNumber) {
|
|
2915
|
+
throw new CLIError(
|
|
2916
|
+
`Migration ${targetMigration.filename} is already applied remotely.`
|
|
2917
|
+
);
|
|
2918
|
+
}
|
|
2919
|
+
if (targetMigration.sequenceNumber !== latestRemoteSequenceNumber + 1) {
|
|
2920
|
+
throw new CLIError(
|
|
2921
|
+
`Migration ${targetMigration.filename} is not the next remote sequence. Expected ${latestRemoteSequenceNumber + 1}.`
|
|
2922
|
+
);
|
|
2923
|
+
}
|
|
2924
|
+
const filePath = join8(getMigrationsDir(), targetMigration.filename);
|
|
2925
|
+
if (!existsSync4(filePath)) {
|
|
2926
|
+
throw new CLIError(`Local migration file not found: ${targetMigration.filename}`);
|
|
2927
|
+
}
|
|
2928
|
+
const sql = readFileSync4(filePath, "utf-8");
|
|
2929
|
+
if (!sql.trim()) {
|
|
2930
|
+
throw new CLIError(`Migration file is empty: ${targetMigration.filename}`);
|
|
2931
|
+
}
|
|
2932
|
+
const body = {
|
|
2933
|
+
name: targetMigration.name,
|
|
2934
|
+
sql
|
|
2935
|
+
};
|
|
2936
|
+
const res = await ossFetch("/api/database/migrations", {
|
|
2937
|
+
method: "POST",
|
|
2938
|
+
body: JSON.stringify(body)
|
|
2939
|
+
});
|
|
2940
|
+
const createdMigration = await res.json();
|
|
2941
|
+
if (createdMigration.sequenceNumber !== targetMigration.sequenceNumber) {
|
|
2942
|
+
throw new CLIError(
|
|
2943
|
+
`Applied migration sequence mismatch. Expected ${targetMigration.sequenceNumber}, received ${createdMigration.sequenceNumber}.`
|
|
2944
|
+
);
|
|
2945
|
+
}
|
|
2946
|
+
if (json) {
|
|
2947
|
+
outputJson(createdMigration);
|
|
2948
|
+
} else {
|
|
2949
|
+
outputSuccess(`Applied migration ${targetMigration.filename}`);
|
|
2950
|
+
}
|
|
2951
|
+
await reportCliUsage("cli.db.migrations.up", true);
|
|
2952
|
+
} catch (err) {
|
|
2953
|
+
await reportCliUsage("cli.db.migrations.up", false);
|
|
2954
|
+
handleError(err, json);
|
|
2955
|
+
}
|
|
2956
|
+
});
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2671
2959
|
// src/commands/records/list.ts
|
|
2672
2960
|
function registerRecordsCommands(recordsCmd2) {
|
|
2673
2961
|
recordsCmd2.command("list <table>").description("List records from a table").option("--select <columns>", "Columns to select (comma-separated)").option("--filter <filter>", 'Filter expression (e.g. "name=eq.John")').option("--order <order>", 'Order by (e.g. "created_at.desc")').option("--limit <n>", "Limit number of records", parseInt).option("--offset <n>", "Offset for pagination", parseInt).action(async (table, opts, cmd) => {
|
|
@@ -2851,21 +3139,21 @@ function registerFunctionsCommands(functionsCmd2) {
|
|
|
2851
3139
|
}
|
|
2852
3140
|
|
|
2853
3141
|
// src/commands/functions/deploy.ts
|
|
2854
|
-
import { readFileSync as
|
|
2855
|
-
import { join as
|
|
3142
|
+
import { readFileSync as readFileSync5, existsSync as existsSync5 } from "fs";
|
|
3143
|
+
import { join as join9 } from "path";
|
|
2856
3144
|
function registerFunctionsDeployCommand(functionsCmd2) {
|
|
2857
3145
|
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) => {
|
|
2858
3146
|
const { json } = getRootOpts(cmd);
|
|
2859
3147
|
try {
|
|
2860
3148
|
await requireAuth();
|
|
2861
|
-
const filePath = opts.file ??
|
|
2862
|
-
if (!
|
|
3149
|
+
const filePath = opts.file ?? join9(process.cwd(), "insforge", "functions", slug, "index.ts");
|
|
3150
|
+
if (!existsSync5(filePath)) {
|
|
2863
3151
|
throw new CLIError(
|
|
2864
3152
|
`Source file not found: ${filePath}
|
|
2865
|
-
Specify --file <path> or create ${
|
|
3153
|
+
Specify --file <path> or create ${join9("insforge", "functions", slug, "index.ts")}`
|
|
2866
3154
|
);
|
|
2867
3155
|
}
|
|
2868
|
-
const code =
|
|
3156
|
+
const code = readFileSync5(filePath, "utf-8");
|
|
2869
3157
|
const name = opts.name ?? slug;
|
|
2870
3158
|
const description = opts.description ?? "";
|
|
2871
3159
|
let exists = false;
|
|
@@ -3052,7 +3340,7 @@ function registerStorageBucketsCommand(storageCmd2) {
|
|
|
3052
3340
|
}
|
|
3053
3341
|
|
|
3054
3342
|
// src/commands/storage/upload.ts
|
|
3055
|
-
import { readFileSync as
|
|
3343
|
+
import { readFileSync as readFileSync6, existsSync as existsSync6 } from "fs";
|
|
3056
3344
|
import { basename as basename5 } from "path";
|
|
3057
3345
|
function registerStorageUploadCommand(storageCmd2) {
|
|
3058
3346
|
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) => {
|
|
@@ -3061,10 +3349,10 @@ function registerStorageUploadCommand(storageCmd2) {
|
|
|
3061
3349
|
await requireAuth();
|
|
3062
3350
|
const config = getProjectConfig();
|
|
3063
3351
|
if (!config) throw new ProjectNotLinkedError();
|
|
3064
|
-
if (!
|
|
3352
|
+
if (!existsSync6(file)) {
|
|
3065
3353
|
throw new CLIError(`File not found: ${file}`);
|
|
3066
3354
|
}
|
|
3067
|
-
const fileContent =
|
|
3355
|
+
const fileContent = readFileSync6(file);
|
|
3068
3356
|
const objectKey = opts.key ?? basename5(file);
|
|
3069
3357
|
const bucketName = opts.bucket;
|
|
3070
3358
|
const formData = new FormData();
|
|
@@ -3095,8 +3383,8 @@ function registerStorageUploadCommand(storageCmd2) {
|
|
|
3095
3383
|
}
|
|
3096
3384
|
|
|
3097
3385
|
// src/commands/storage/download.ts
|
|
3098
|
-
import { writeFileSync as
|
|
3099
|
-
import { join as
|
|
3386
|
+
import { writeFileSync as writeFileSync4 } from "fs";
|
|
3387
|
+
import { join as join10, basename as basename6 } from "path";
|
|
3100
3388
|
function registerStorageDownloadCommand(storageCmd2) {
|
|
3101
3389
|
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) => {
|
|
3102
3390
|
const { json } = getRootOpts(cmd);
|
|
@@ -3116,8 +3404,8 @@ function registerStorageDownloadCommand(storageCmd2) {
|
|
|
3116
3404
|
throw new CLIError(err.error ?? `Download failed: ${res.status}`);
|
|
3117
3405
|
}
|
|
3118
3406
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
3119
|
-
const outputPath = opts.output ??
|
|
3120
|
-
|
|
3407
|
+
const outputPath = opts.output ?? join10(process.cwd(), basename6(objectKey));
|
|
3408
|
+
writeFileSync4(outputPath, buffer);
|
|
3121
3409
|
if (json) {
|
|
3122
3410
|
outputJson({ success: true, path: outputPath, size: buffer.length });
|
|
3123
3411
|
} else {
|
|
@@ -4223,13 +4511,13 @@ function registerComputeLogsCommand(computeCmd2) {
|
|
|
4223
4511
|
}
|
|
4224
4512
|
|
|
4225
4513
|
// src/commands/compute/deploy.ts
|
|
4226
|
-
import { existsSync as
|
|
4227
|
-
import { join as
|
|
4514
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync5, unlinkSync as unlinkSync2, renameSync } from "fs";
|
|
4515
|
+
import { join as join11 } from "path";
|
|
4228
4516
|
import { execSync, spawn } from "child_process";
|
|
4229
4517
|
function parseFlyToml(dir) {
|
|
4230
|
-
const tomlPath =
|
|
4231
|
-
if (!
|
|
4232
|
-
const content =
|
|
4518
|
+
const tomlPath = join11(dir, "fly.toml");
|
|
4519
|
+
if (!existsSync7(tomlPath)) return {};
|
|
4520
|
+
const content = readFileSync7(tomlPath, "utf-8");
|
|
4233
4521
|
const config = {};
|
|
4234
4522
|
const portMatch = content.match(/internal_port\s*=\s*(\d+)/);
|
|
4235
4523
|
if (portMatch) config.internalPort = Number(portMatch[1]);
|
|
@@ -4299,8 +4587,8 @@ function registerComputeDeployCommand(computeCmd2) {
|
|
|
4299
4587
|
checkFlyctl();
|
|
4300
4588
|
const flyToken = getFlyToken();
|
|
4301
4589
|
const dir = directory ?? process.cwd();
|
|
4302
|
-
const dockerfilePath =
|
|
4303
|
-
if (!
|
|
4590
|
+
const dockerfilePath = join11(dir, "Dockerfile");
|
|
4591
|
+
if (!existsSync7(dockerfilePath)) {
|
|
4304
4592
|
throw new CLIError(`No Dockerfile found in ${dir}`);
|
|
4305
4593
|
}
|
|
4306
4594
|
const flyTomlDefaults = parseFlyToml(dir);
|
|
@@ -4345,15 +4633,15 @@ function registerComputeDeployCommand(computeCmd2) {
|
|
|
4345
4633
|
serviceId = service.id;
|
|
4346
4634
|
flyAppId = service.flyAppId;
|
|
4347
4635
|
}
|
|
4348
|
-
const existingTomlPath =
|
|
4349
|
-
const backupTomlPath =
|
|
4636
|
+
const existingTomlPath = join11(dir, "fly.toml");
|
|
4637
|
+
const backupTomlPath = join11(dir, "fly.toml.insforge-backup");
|
|
4350
4638
|
let hadExistingToml = false;
|
|
4351
|
-
if (
|
|
4639
|
+
if (existsSync7(existingTomlPath)) {
|
|
4352
4640
|
hadExistingToml = true;
|
|
4353
4641
|
renameSync(existingTomlPath, backupTomlPath);
|
|
4354
4642
|
}
|
|
4355
4643
|
const tomlContent = generateFlyToml(flyAppId, { port, memory, cpu, region });
|
|
4356
|
-
|
|
4644
|
+
writeFileSync5(existingTomlPath, tomlContent);
|
|
4357
4645
|
try {
|
|
4358
4646
|
if (!json) outputInfo("Building and deploying (this may take a few minutes)...");
|
|
4359
4647
|
await new Promise((resolve4, reject) => {
|
|
@@ -4647,6 +4935,7 @@ function registerDiagnoseMetricsCommand(diagnoseCmd2) {
|
|
|
4647
4935
|
await reportCliUsage("cli.diagnose.metrics", true);
|
|
4648
4936
|
} catch (err) {
|
|
4649
4937
|
await reportCliUsage("cli.diagnose.metrics", false);
|
|
4938
|
+
await shutdownAnalytics();
|
|
4650
4939
|
handleError(err, json);
|
|
4651
4940
|
} finally {
|
|
4652
4941
|
await shutdownAnalytics();
|
|
@@ -4714,6 +5003,7 @@ function registerDiagnoseAdvisorCommand(diagnoseCmd2) {
|
|
|
4714
5003
|
await reportCliUsage("cli.diagnose.advisor", true);
|
|
4715
5004
|
} catch (err) {
|
|
4716
5005
|
await reportCliUsage("cli.diagnose.advisor", false);
|
|
5006
|
+
await shutdownAnalytics();
|
|
4717
5007
|
handleError(err, json);
|
|
4718
5008
|
} finally {
|
|
4719
5009
|
await shutdownAnalytics();
|
|
@@ -4903,6 +5193,7 @@ function registerDiagnoseDbCommand(diagnoseCmd2) {
|
|
|
4903
5193
|
await reportCliUsage("cli.diagnose.db", true);
|
|
4904
5194
|
} catch (err) {
|
|
4905
5195
|
await reportCliUsage("cli.diagnose.db", false);
|
|
5196
|
+
await shutdownAnalytics();
|
|
4906
5197
|
handleError(err, json);
|
|
4907
5198
|
} finally {
|
|
4908
5199
|
await shutdownAnalytics();
|
|
@@ -4993,6 +5284,7 @@ function registerDiagnoseLogsCommand(diagnoseCmd2) {
|
|
|
4993
5284
|
await reportCliUsage("cli.diagnose.logs", true);
|
|
4994
5285
|
} catch (err) {
|
|
4995
5286
|
await reportCliUsage("cli.diagnose.logs", false);
|
|
5287
|
+
await shutdownAnalytics();
|
|
4996
5288
|
handleError(err, json);
|
|
4997
5289
|
} finally {
|
|
4998
5290
|
await shutdownAnalytics();
|
|
@@ -5074,7 +5366,7 @@ function registerDiagnoseCommands(diagnoseCmd2) {
|
|
|
5074
5366
|
const s = !json ? clack10.spinner() : null;
|
|
5075
5367
|
s?.start("Collecting diagnostic data...");
|
|
5076
5368
|
const data2 = await collectDiagnosticData(projectId, ossMode, apiUrl);
|
|
5077
|
-
const cliVersion = "0.1.
|
|
5369
|
+
const cliVersion = "0.1.53-dev.0";
|
|
5078
5370
|
s?.stop("Data collected");
|
|
5079
5371
|
if (!json) {
|
|
5080
5372
|
console.log(`
|
|
@@ -5284,6 +5576,7 @@ function registerDiagnoseCommands(diagnoseCmd2) {
|
|
|
5284
5576
|
await reportCliUsage(usageEvent, true);
|
|
5285
5577
|
} catch (err) {
|
|
5286
5578
|
await reportCliUsage(usageEvent, false);
|
|
5579
|
+
await shutdownAnalytics();
|
|
5287
5580
|
handleError(err, json);
|
|
5288
5581
|
} finally {
|
|
5289
5582
|
await shutdownAnalytics();
|
|
@@ -5302,7 +5595,7 @@ function formatBytesCompact(bytes) {
|
|
|
5302
5595
|
|
|
5303
5596
|
// src/index.ts
|
|
5304
5597
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5305
|
-
var pkg = JSON.parse(
|
|
5598
|
+
var pkg = JSON.parse(readFileSync8(join12(__dirname, "../package.json"), "utf-8"));
|
|
5306
5599
|
var INSFORGE_LOGO = `
|
|
5307
5600
|
\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
|
|
5308
5601
|
\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
|
|
@@ -5336,6 +5629,7 @@ registerDbTriggersCommand(dbCmd);
|
|
|
5336
5629
|
registerDbRpcCommand(dbCmd);
|
|
5337
5630
|
registerDbExportCommand(dbCmd);
|
|
5338
5631
|
registerDbImportCommand(dbCmd);
|
|
5632
|
+
registerDbMigrationsCommand(dbCmd);
|
|
5339
5633
|
var recordsCmd = program.command("records", { hidden: true }).description("CRUD operations on table records");
|
|
5340
5634
|
registerRecordsCommands(recordsCmd);
|
|
5341
5635
|
registerRecordsCreateCommand(recordsCmd);
|