@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 CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { readFileSync as readFileSync7 } from "fs";
5
- import { join as join10, dirname } from "path";
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 readFileSync4, existsSync as existsSync3 } from "fs";
2855
- import { join as join7 } from "path";
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 ?? join7(process.cwd(), "insforge", "functions", slug, "index.ts");
2862
- if (!existsSync3(filePath)) {
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 ${join7("insforge", "functions", slug, "index.ts")}`
3153
+ Specify --file <path> or create ${join9("insforge", "functions", slug, "index.ts")}`
2866
3154
  );
2867
3155
  }
2868
- const code = readFileSync4(filePath, "utf-8");
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 readFileSync5, existsSync as existsSync4 } from "fs";
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 (!existsSync4(file)) {
3352
+ if (!existsSync6(file)) {
3065
3353
  throw new CLIError(`File not found: ${file}`);
3066
3354
  }
3067
- const fileContent = readFileSync5(file);
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 writeFileSync3 } from "fs";
3099
- import { join as join8, basename as basename6 } from "path";
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 ?? join8(process.cwd(), basename6(objectKey));
3120
- writeFileSync3(outputPath, buffer);
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 existsSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2, renameSync } from "fs";
4227
- import { join as join9 } from "path";
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 = join9(dir, "fly.toml");
4231
- if (!existsSync5(tomlPath)) return {};
4232
- const content = readFileSync6(tomlPath, "utf-8");
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 = join9(dir, "Dockerfile");
4303
- if (!existsSync5(dockerfilePath)) {
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 = join9(dir, "fly.toml");
4349
- const backupTomlPath = join9(dir, "fly.toml.insforge-backup");
4636
+ const existingTomlPath = join11(dir, "fly.toml");
4637
+ const backupTomlPath = join11(dir, "fly.toml.insforge-backup");
4350
4638
  let hadExistingToml = false;
4351
- if (existsSync5(existingTomlPath)) {
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
- writeFileSync4(existingTomlPath, tomlContent);
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.51";
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(readFileSync7(join10(__dirname, "../package.json"), "utf-8"));
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);