realitydb 0.2.0 → 0.3.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.
Files changed (2) hide show
  1. package/dist/index.js +619 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6150,6 +6150,13 @@ async function truncateTables(pool, tableNames, cascade) {
6150
6150
  };
6151
6151
  }
6152
6152
 
6153
+ // ../../packages/db/dist/readTable.js
6154
+ async function readTableRows(pool, tableName, columns) {
6155
+ const quotedColumns = columns.map((c) => `"${c}"`).join(", ");
6156
+ const result = await pool.query(`SELECT ${quotedColumns} FROM "${tableName}"`);
6157
+ return result.rows;
6158
+ }
6159
+
6153
6160
  // ../../packages/schema/dist/normalizer.js
6154
6161
  function normalizeSchema(raw) {
6155
6162
  const primaryKeyMap = /* @__PURE__ */ new Map();
@@ -6340,6 +6347,85 @@ async function introspectDatabase(pool, schemaName = "public") {
6340
6347
  return schema;
6341
6348
  }
6342
6349
 
6350
+ // ../../packages/schema/dist/generateDDL.js
6351
+ function generateCreateTableDDL(schema) {
6352
+ const orderedNames = orderByDependency(schema.tables, schema.foreignKeys);
6353
+ const tableMap = /* @__PURE__ */ new Map();
6354
+ for (const table of schema.tables) {
6355
+ tableMap.set(table.name, table);
6356
+ }
6357
+ const fksBySource = /* @__PURE__ */ new Map();
6358
+ for (const fk of schema.foreignKeys) {
6359
+ const existing = fksBySource.get(fk.sourceTable) ?? [];
6360
+ existing.push(fk);
6361
+ fksBySource.set(fk.sourceTable, existing);
6362
+ }
6363
+ const statements = [];
6364
+ for (const tableName of orderedNames) {
6365
+ const table = tableMap.get(tableName);
6366
+ if (!table)
6367
+ continue;
6368
+ const columnDefs = table.columns.sort((a, b) => a.ordinalPosition - b.ordinalPosition).map((col) => formatColumnDef(col));
6369
+ if (table.primaryKey) {
6370
+ columnDefs.push(` PRIMARY KEY ("${table.primaryKey.columnName}")`);
6371
+ }
6372
+ const tableFks = fksBySource.get(tableName) ?? [];
6373
+ for (const fk of tableFks) {
6374
+ columnDefs.push(` FOREIGN KEY ("${fk.sourceColumn}") REFERENCES "${fk.targetTable}" ("${fk.targetColumn}")`);
6375
+ }
6376
+ statements.push(`CREATE TABLE "${tableName}" (
6377
+ ${columnDefs.join(",\n")}
6378
+ );`);
6379
+ }
6380
+ return statements.join("\n\n") + "\n";
6381
+ }
6382
+ function formatColumnDef(col) {
6383
+ let typeName = col.dataType.toUpperCase();
6384
+ if (col.maxLength && (typeName === "CHARACTER VARYING" || typeName === "VARCHAR")) {
6385
+ typeName = `VARCHAR(${col.maxLength})`;
6386
+ }
6387
+ let def = ` "${col.name}" ${typeName}`;
6388
+ if (!col.isNullable) {
6389
+ def += " NOT NULL";
6390
+ }
6391
+ if (col.hasDefault && col.defaultValue !== null) {
6392
+ def += ` DEFAULT ${col.defaultValue}`;
6393
+ }
6394
+ return def;
6395
+ }
6396
+ function orderByDependency(tables, foreignKeys) {
6397
+ const tableNames = new Set(tables.map((t) => t.name));
6398
+ const deps = /* @__PURE__ */ new Map();
6399
+ for (const name of tableNames) {
6400
+ deps.set(name, /* @__PURE__ */ new Set());
6401
+ }
6402
+ for (const fk of foreignKeys) {
6403
+ if (fk.sourceTable !== fk.targetTable && tableNames.has(fk.targetTable)) {
6404
+ deps.get(fk.sourceTable).add(fk.targetTable);
6405
+ }
6406
+ }
6407
+ const result = [];
6408
+ const visited = /* @__PURE__ */ new Set();
6409
+ const visiting = /* @__PURE__ */ new Set();
6410
+ function visit(name) {
6411
+ if (visited.has(name))
6412
+ return;
6413
+ if (visiting.has(name))
6414
+ return;
6415
+ visiting.add(name);
6416
+ for (const dep of deps.get(name) ?? []) {
6417
+ visit(dep);
6418
+ }
6419
+ visiting.delete(name);
6420
+ visited.add(name);
6421
+ result.push(name);
6422
+ }
6423
+ for (const name of tableNames) {
6424
+ visit(name);
6425
+ }
6426
+ return result;
6427
+ }
6428
+
6343
6429
  // ../../packages/core/dist/scanPipeline.js
6344
6430
  async function scanDatabase(config) {
6345
6431
  const pool = createPostgresClient(config.database.connectionString);
@@ -6628,6 +6714,198 @@ function packDatasetToGenerated(pack) {
6628
6714
  };
6629
6715
  }
6630
6716
 
6717
+ // ../../packages/core/dist/capturePipeline.js
6718
+ function maskConnection(connectionString) {
6719
+ try {
6720
+ const url = new URL(connectionString);
6721
+ if (url.password) {
6722
+ url.password = "****";
6723
+ }
6724
+ return url.toString();
6725
+ } catch {
6726
+ return connectionString.replace(/:([^@/]+)@/, ":****@");
6727
+ }
6728
+ }
6729
+ async function captureDatabase(config, options) {
6730
+ const start = performance.now();
6731
+ const pool = createPostgresClient(config.database.connectionString);
6732
+ try {
6733
+ await testConnection(pool);
6734
+ const schema = await introspectDatabase(pool);
6735
+ const graph = buildDependencyGraph(schema.foreignKeys);
6736
+ const sorted = topologicalSort(graph);
6737
+ const graphOrder = sorted.order;
6738
+ const allTableNames = schema.tables.map((t) => t.name);
6739
+ const tableOrder = [
6740
+ ...graphOrder,
6741
+ ...allTableNames.filter((t) => !graphOrder.includes(t))
6742
+ ];
6743
+ let tablesToCapture;
6744
+ if (options.tables && options.tables.length > 0) {
6745
+ let addDeps2 = function(tableName) {
6746
+ if (allDeps.has(tableName))
6747
+ return;
6748
+ allDeps.add(tableName);
6749
+ for (const fk of schema.foreignKeys) {
6750
+ if (fk.sourceTable === tableName && fk.sourceTable !== fk.targetTable) {
6751
+ addDeps2(fk.targetTable);
6752
+ }
6753
+ }
6754
+ };
6755
+ var addDeps = addDeps2;
6756
+ const requested = new Set(options.tables);
6757
+ const allDeps = /* @__PURE__ */ new Set();
6758
+ for (const t of requested) {
6759
+ addDeps2(t);
6760
+ }
6761
+ tablesToCapture = tableOrder.filter((t) => allDeps.has(t));
6762
+ } else {
6763
+ tablesToCapture = tableOrder;
6764
+ }
6765
+ const capturedTableSet = new Set(tablesToCapture);
6766
+ const filteredTables = schema.tables.filter((t) => capturedTableSet.has(t.name));
6767
+ const filteredFKs = schema.foreignKeys.filter((fk) => capturedTableSet.has(fk.sourceTable) && capturedTableSet.has(fk.targetTable));
6768
+ const filteredSchema = {
6769
+ ...schema,
6770
+ tables: filteredTables,
6771
+ foreignKeys: filteredFKs,
6772
+ tableCount: filteredTables.length,
6773
+ foreignKeyCount: filteredFKs.length
6774
+ };
6775
+ const ddl = generateCreateTableDDL(filteredSchema);
6776
+ const packDataset = { tables: {} };
6777
+ const tableDetails = [];
6778
+ let totalRows = 0;
6779
+ for (const tableName of tablesToCapture) {
6780
+ const tableSchema = filteredTables.find((t) => t.name === tableName);
6781
+ if (!tableSchema)
6782
+ continue;
6783
+ const columns = tableSchema.columns.map((c) => c.name);
6784
+ const rows = await readTableRows(pool, tableName, columns);
6785
+ const rowCount = rows.length;
6786
+ packDataset.tables[tableName] = {
6787
+ columns,
6788
+ rows,
6789
+ rowCount
6790
+ };
6791
+ tableDetails.push({ name: tableName, rowCount });
6792
+ totalRows += rowCount;
6793
+ }
6794
+ const packSchema = {
6795
+ tables: filteredTables.map((t) => ({
6796
+ name: t.name,
6797
+ columns: t.columns.map((c) => ({
6798
+ name: c.name,
6799
+ dataType: c.dataType,
6800
+ nullable: c.isNullable,
6801
+ maxLength: c.maxLength
6802
+ })),
6803
+ primaryKey: t.primaryKey?.columnName
6804
+ })),
6805
+ foreignKeys: filteredFKs.map((fk) => ({
6806
+ sourceTable: fk.sourceTable,
6807
+ sourceColumn: fk.sourceColumn,
6808
+ targetTable: fk.targetTable,
6809
+ targetColumn: fk.targetColumn
6810
+ }))
6811
+ };
6812
+ const plan = {
6813
+ version: "1.0",
6814
+ planId: `capture-${options.name}-${Date.now()}`,
6815
+ tables: [],
6816
+ tableOrder: tablesToCapture,
6817
+ config: {
6818
+ targetDatabase: "postgres",
6819
+ defaultRowCount: 0,
6820
+ batchSize: config.seed?.batchSize ?? 1e3,
6821
+ environment: "dev"
6822
+ },
6823
+ reproducibility: {
6824
+ randomSeed: 0,
6825
+ strategyVersion: "0.3.0"
6826
+ }
6827
+ };
6828
+ const masked = maskConnection(config.database.connectionString);
6829
+ const pack = {
6830
+ format: "databox-reality-pack",
6831
+ version: "1.0",
6832
+ metadata: {
6833
+ name: options.name,
6834
+ description: options.description,
6835
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
6836
+ seed: 0,
6837
+ totalRows,
6838
+ tableCount: tablesToCapture.length,
6839
+ ddl,
6840
+ capturedFrom: masked
6841
+ },
6842
+ schema: packSchema,
6843
+ plan,
6844
+ dataset: packDataset
6845
+ };
6846
+ const outputDir = options.outputDir ?? ".";
6847
+ const filePath = await saveRealityPack(pack, outputDir);
6848
+ const durationMs = Math.round(performance.now() - start);
6849
+ return {
6850
+ pack,
6851
+ filePath,
6852
+ totalRows,
6853
+ tableCount: tablesToCapture.length,
6854
+ durationMs,
6855
+ tableDetails
6856
+ };
6857
+ } finally {
6858
+ await closeConnection(pool);
6859
+ }
6860
+ }
6861
+
6862
+ // ../../packages/core/dist/sharePipeline.js
6863
+ var import_promises6 = require("fs/promises");
6864
+ function formatSize(bytes) {
6865
+ if (bytes < 1024)
6866
+ return `${bytes} B`;
6867
+ const kb = Math.round(bytes / 1024);
6868
+ if (kb < 1024)
6869
+ return `${kb} KB`;
6870
+ const mb = (bytes / (1024 * 1024)).toFixed(1);
6871
+ return `${mb} MB`;
6872
+ }
6873
+ async function shareRealityPack(filePath, options) {
6874
+ const pack = await loadRealityPack(filePath);
6875
+ const fileStat = await (0, import_promises6.stat)(filePath);
6876
+ const size = formatSize(fileStat.size);
6877
+ const method = options?.method ?? "file";
6878
+ if (method === "gist") {
6879
+ const token = process.env.GITHUB_TOKEN;
6880
+ if (!token) {
6881
+ return {
6882
+ method: "file",
6883
+ location: filePath,
6884
+ packName: pack.metadata.name,
6885
+ size,
6886
+ tableCount: pack.metadata.tableCount,
6887
+ totalRows: pack.metadata.totalRows
6888
+ };
6889
+ }
6890
+ return {
6891
+ method: "file",
6892
+ location: filePath,
6893
+ packName: pack.metadata.name,
6894
+ size,
6895
+ tableCount: pack.metadata.tableCount,
6896
+ totalRows: pack.metadata.totalRows
6897
+ };
6898
+ }
6899
+ return {
6900
+ method: "file",
6901
+ location: filePath,
6902
+ packName: pack.metadata.name,
6903
+ size,
6904
+ tableCount: pack.metadata.tableCount,
6905
+ totalRows: pack.metadata.totalRows
6906
+ };
6907
+ }
6908
+
6631
6909
  // src/utils.ts
6632
6910
  function maskConnectionString(connectionString) {
6633
6911
  try {
@@ -6642,7 +6920,7 @@ function maskConnectionString(connectionString) {
6642
6920
  }
6643
6921
 
6644
6922
  // src/commands/scan.ts
6645
- var VERSION2 = "0.2.0";
6923
+ var VERSION2 = "0.3.0";
6646
6924
  async function scanCommand(options) {
6647
6925
  const start = performance.now();
6648
6926
  try {
@@ -6733,7 +7011,7 @@ async function scanCommand(options) {
6733
7011
  }
6734
7012
 
6735
7013
  // src/commands/seed.ts
6736
- var VERSION3 = "0.2.0";
7014
+ var VERSION3 = "0.3.0";
6737
7015
  async function seedCommand(options) {
6738
7016
  const start = performance.now();
6739
7017
  try {
@@ -6911,7 +7189,7 @@ async function seedCommand(options) {
6911
7189
  }
6912
7190
 
6913
7191
  // src/commands/reset.ts
6914
- var VERSION4 = "0.2.0";
7192
+ var VERSION4 = "0.3.0";
6915
7193
  async function resetCommand(options) {
6916
7194
  const start = performance.now();
6917
7195
  if (!options.ci && !options.confirm) {
@@ -6981,7 +7259,7 @@ async function resetCommand(options) {
6981
7259
  }
6982
7260
 
6983
7261
  // src/commands/export.ts
6984
- var VERSION5 = "0.2.0";
7262
+ var VERSION5 = "0.3.0";
6985
7263
  async function exportCommand(options) {
6986
7264
  const start = performance.now();
6987
7265
  try {
@@ -7174,7 +7452,7 @@ function scenariosCommand() {
7174
7452
  }
7175
7453
 
7176
7454
  // src/commands/pack.ts
7177
- var import_promises6 = require("fs/promises");
7455
+ var import_promises7 = require("fs/promises");
7178
7456
  async function packExportCommand(options) {
7179
7457
  try {
7180
7458
  const config = await loadConfig();
@@ -7251,7 +7529,7 @@ async function packExportCommand(options) {
7251
7529
  scenarios: options.scenario,
7252
7530
  scenarioIntensity
7253
7531
  });
7254
- const fileStat = await (0, import_promises6.stat)(result.filePath);
7532
+ const fileStat = await (0, import_promises7.stat)(result.filePath);
7255
7533
  const sizeKb = Math.round(fileStat.size / 1024);
7256
7534
  console.log("");
7257
7535
  console.log(`Tables: ${result.pack.metadata.tableCount}`);
@@ -7331,11 +7609,330 @@ async function packImportCommand(filePath, options) {
7331
7609
  }
7332
7610
  }
7333
7611
 
7612
+ // src/commands/capture.ts
7613
+ var import_promises8 = require("fs/promises");
7614
+ var VERSION6 = "0.3.0";
7615
+ async function captureCommand(options) {
7616
+ const start = performance.now();
7617
+ try {
7618
+ if (!options.name) {
7619
+ const msg = "Missing required --name flag.";
7620
+ if (options.ci) {
7621
+ console.log(formatCIOutput({
7622
+ success: false,
7623
+ command: "capture",
7624
+ version: VERSION6,
7625
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7626
+ durationMs: 0,
7627
+ error: msg
7628
+ }));
7629
+ process.exit(1);
7630
+ }
7631
+ console.error(`[realitydb] ${msg}`);
7632
+ console.error("Usage: realitydb capture --name <name>");
7633
+ process.exit(1);
7634
+ }
7635
+ const config = await loadConfig();
7636
+ const masked = maskConnectionString(config.database.connectionString);
7637
+ const tables = options.tables ? options.tables.split(",").map((t) => t.trim()).filter((t) => t.length > 0) : void 0;
7638
+ if (!options.ci) {
7639
+ console.log("");
7640
+ console.log("RealityDB Capture");
7641
+ console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
7642
+ console.log(`Database: ${masked}`);
7643
+ console.log(`Name: ${options.name}`);
7644
+ if (tables) {
7645
+ console.log(`Tables: ${tables.join(", ")}`);
7646
+ }
7647
+ console.log("");
7648
+ console.log("Capturing...");
7649
+ }
7650
+ const result = await captureDatabase(config, {
7651
+ name: options.name,
7652
+ description: options.description,
7653
+ tables,
7654
+ outputDir: options.output
7655
+ });
7656
+ const durationMs = Math.round(performance.now() - start);
7657
+ if (options.ci) {
7658
+ console.log(formatCIOutput({
7659
+ success: true,
7660
+ command: "capture",
7661
+ version: VERSION6,
7662
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7663
+ durationMs,
7664
+ data: {
7665
+ database: masked,
7666
+ name: options.name,
7667
+ filePath: result.filePath,
7668
+ tableCount: result.tableCount,
7669
+ totalRows: result.totalRows,
7670
+ tables: result.tableDetails.map((t) => ({
7671
+ name: t.name,
7672
+ rowCount: t.rowCount
7673
+ })),
7674
+ ddlIncluded: true
7675
+ }
7676
+ }));
7677
+ return;
7678
+ }
7679
+ for (const table of result.tableDetails) {
7680
+ console.log(` ${table.name}: ${table.rowCount} rows`);
7681
+ }
7682
+ const fileStat = await (0, import_promises8.stat)(result.filePath);
7683
+ const sizeKb = Math.round(fileStat.size / 1024);
7684
+ console.log("");
7685
+ console.log(`Captured: ${result.filePath} (${sizeKb} KB)`);
7686
+ console.log("Schema DDL included. Share this file to reproduce the environment.");
7687
+ console.log("");
7688
+ } catch (err) {
7689
+ const message = err instanceof Error ? err.message : String(err);
7690
+ if (options.ci) {
7691
+ console.log(formatCIOutput({
7692
+ success: false,
7693
+ command: "capture",
7694
+ version: VERSION6,
7695
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7696
+ durationMs: Math.round(performance.now() - start),
7697
+ error: message
7698
+ }));
7699
+ process.exit(1);
7700
+ }
7701
+ if (message.includes("Config file not found")) {
7702
+ console.error(`[realitydb] ${message}`);
7703
+ } else if (message.includes("connection") || message.includes("ECONNREFUSED")) {
7704
+ console.error(`[realitydb] Capture failed: ${message}`);
7705
+ console.error("Hint: Check that your database is running (e.g. Docker)");
7706
+ } else {
7707
+ console.error(`[realitydb] Capture failed: ${message}`);
7708
+ }
7709
+ process.exit(1);
7710
+ }
7711
+ }
7712
+
7713
+ // src/commands/share.ts
7714
+ var VERSION7 = "0.3.0";
7715
+ async function shareCommand(filePath, options) {
7716
+ const start = performance.now();
7717
+ try {
7718
+ if (!filePath) {
7719
+ const msg = "Missing file path argument.";
7720
+ if (options.ci) {
7721
+ console.log(formatCIOutput({
7722
+ success: false,
7723
+ command: "share",
7724
+ version: VERSION7,
7725
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7726
+ durationMs: 0,
7727
+ error: msg
7728
+ }));
7729
+ process.exit(1);
7730
+ }
7731
+ console.error(`[realitydb] ${msg}`);
7732
+ console.error("Usage: realitydb share <file>");
7733
+ process.exit(1);
7734
+ }
7735
+ const result = await shareRealityPack(filePath);
7736
+ const durationMs = Math.round(performance.now() - start);
7737
+ if (options.ci) {
7738
+ console.log(formatCIOutput({
7739
+ success: true,
7740
+ command: "share",
7741
+ version: VERSION7,
7742
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7743
+ durationMs,
7744
+ data: {
7745
+ method: result.method,
7746
+ location: result.location,
7747
+ packName: result.packName,
7748
+ size: result.size,
7749
+ tableCount: result.tableCount,
7750
+ totalRows: result.totalRows
7751
+ }
7752
+ }));
7753
+ return;
7754
+ }
7755
+ console.log("");
7756
+ console.log("RealityDB Share");
7757
+ console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
7758
+ console.log(`Pack: ${result.packName} (${result.tableCount} tables, ${result.totalRows} rows, ${result.size})`);
7759
+ console.log("");
7760
+ console.log("Share this file:");
7761
+ console.log(` File: ${result.location}`);
7762
+ console.log(` Size: ${result.size}`);
7763
+ console.log("");
7764
+ console.log("The receiver can load it with:");
7765
+ console.log(` realitydb load ${result.location} --confirm`);
7766
+ console.log("");
7767
+ console.log("Tip: To create the schema first, the receiver can run:");
7768
+ console.log(` realitydb load ${result.location} --show-ddl`);
7769
+ console.log("");
7770
+ } catch (err) {
7771
+ const message = err instanceof Error ? err.message : String(err);
7772
+ if (options.ci) {
7773
+ console.log(formatCIOutput({
7774
+ success: false,
7775
+ command: "share",
7776
+ version: VERSION7,
7777
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7778
+ durationMs: Math.round(performance.now() - start),
7779
+ error: message
7780
+ }));
7781
+ process.exit(1);
7782
+ }
7783
+ console.error(`[realitydb] Share failed: ${message}`);
7784
+ process.exit(1);
7785
+ }
7786
+ }
7787
+
7788
+ // src/commands/load.ts
7789
+ var VERSION8 = "0.3.0";
7790
+ async function loadCommand(filePath, options) {
7791
+ const start = performance.now();
7792
+ try {
7793
+ if (!filePath) {
7794
+ const msg = "Missing file path argument.";
7795
+ if (options.ci) {
7796
+ console.log(formatCIOutput({
7797
+ success: false,
7798
+ command: "load",
7799
+ version: VERSION8,
7800
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7801
+ durationMs: 0,
7802
+ error: msg
7803
+ }));
7804
+ process.exit(1);
7805
+ }
7806
+ console.error(`[realitydb] ${msg}`);
7807
+ console.error("Usage: realitydb load <file> --confirm");
7808
+ process.exit(1);
7809
+ }
7810
+ const pack = await loadRealityPack(filePath);
7811
+ if (options.showDdl) {
7812
+ const ddl = pack.metadata.ddl;
7813
+ if (options.ci) {
7814
+ console.log(formatCIOutput({
7815
+ success: true,
7816
+ command: "load",
7817
+ version: VERSION8,
7818
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7819
+ durationMs: Math.round(performance.now() - start),
7820
+ data: {
7821
+ packName: pack.metadata.name,
7822
+ ddlAvailable: !!ddl,
7823
+ ddl: ddl ?? null
7824
+ }
7825
+ }));
7826
+ return;
7827
+ }
7828
+ if (ddl) {
7829
+ console.log("");
7830
+ console.log("Schema DDL (run this SQL to create tables):");
7831
+ console.log("");
7832
+ console.log(ddl);
7833
+ } else {
7834
+ console.log("");
7835
+ console.log("No DDL available in this Reality Pack.");
7836
+ console.log("This pack was created with pack export (generated data), not capture.");
7837
+ console.log("");
7838
+ }
7839
+ return;
7840
+ }
7841
+ const config = await loadConfig();
7842
+ const masked = maskConnectionString(config.database.connectionString);
7843
+ if (!options.ci) {
7844
+ console.log("");
7845
+ console.log("RealityDB Load");
7846
+ console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
7847
+ console.log(`Database: ${masked}`);
7848
+ console.log(`Pack: ${pack.metadata.name} (v${pack.version})`);
7849
+ if (pack.metadata.templateName) {
7850
+ console.log(`Template: ${pack.metadata.templateName}`);
7851
+ }
7852
+ console.log(`Tables: ${pack.metadata.tableCount}`);
7853
+ console.log(`Total rows: ${pack.metadata.totalRows}`);
7854
+ const ddl = pack.metadata.ddl;
7855
+ if (ddl) {
7856
+ console.log("Schema DDL: included");
7857
+ }
7858
+ console.log("");
7859
+ }
7860
+ if (!options.ci && !options.confirm) {
7861
+ console.error("[realitydb] Load requires --confirm flag.");
7862
+ console.error("Hint: This will insert data into your database. Use --confirm to proceed.");
7863
+ console.error("");
7864
+ console.error("To view the schema DDL first:");
7865
+ console.error(` realitydb load ${filePath} --show-ddl`);
7866
+ process.exit(1);
7867
+ }
7868
+ if (!options.ci) {
7869
+ console.log("Loading...");
7870
+ }
7871
+ const result = await importPack(config, filePath);
7872
+ const durationMs = Math.round(performance.now() - start);
7873
+ if (options.ci) {
7874
+ console.log(formatCIOutput({
7875
+ success: true,
7876
+ command: "load",
7877
+ version: VERSION8,
7878
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7879
+ durationMs,
7880
+ data: {
7881
+ database: masked,
7882
+ packName: pack.metadata.name,
7883
+ totalRows: result.totalRows,
7884
+ tables: result.insertResult.tables.map((t) => ({
7885
+ name: t.tableName,
7886
+ rowsInserted: t.rowsInserted,
7887
+ durationMs: t.durationMs
7888
+ }))
7889
+ }
7890
+ }));
7891
+ return;
7892
+ }
7893
+ for (const tableResult of result.insertResult.tables) {
7894
+ console.log(
7895
+ ` ${tableResult.tableName}: ${tableResult.rowsInserted} rows loaded`
7896
+ );
7897
+ }
7898
+ const totalTime = (result.durationMs / 1e3).toFixed(1);
7899
+ console.log("");
7900
+ console.log(`Load complete. ${result.totalRows} rows in ${totalTime}s`);
7901
+ console.log("");
7902
+ } catch (err) {
7903
+ const message = err instanceof Error ? err.message : String(err);
7904
+ if (options.ci) {
7905
+ console.log(formatCIOutput({
7906
+ success: false,
7907
+ command: "load",
7908
+ version: VERSION8,
7909
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7910
+ durationMs: Math.round(performance.now() - start),
7911
+ error: message
7912
+ }));
7913
+ process.exit(1);
7914
+ }
7915
+ if (message.includes("Config file not found")) {
7916
+ console.error(`[realitydb] ${message}`);
7917
+ } else if (message.includes("Cannot import Reality Pack")) {
7918
+ console.error(`[realitydb] ${message}`);
7919
+ const ddlHint = "Tip: Use --show-ddl to get the schema creation SQL.";
7920
+ console.error(ddlHint);
7921
+ } else if (message.includes("connection") || message.includes("ECONNREFUSED")) {
7922
+ console.error(`[realitydb] Load failed: ${message}`);
7923
+ console.error("Hint: Check that your database is running (e.g. Docker)");
7924
+ } else {
7925
+ console.error(`[realitydb] Load failed: ${message}`);
7926
+ }
7927
+ process.exit(1);
7928
+ }
7929
+ }
7930
+
7334
7931
  // src/cli.ts
7335
- var VERSION6 = "0.2.0";
7932
+ var VERSION9 = "0.3.0";
7336
7933
  function run(argv) {
7337
7934
  const program2 = new Command();
7338
- program2.name("realitydb").description("RealityDB \u2014 Developer Reality Platform").version(VERSION6).option("--config <path>", "Path to config file").option("--ci", "CI mode: JSON output, no prompts, proper exit codes", false).option("--verbose", "Enable verbose output", false);
7935
+ program2.name("realitydb").description("RealityDB \u2014 Developer Reality Platform").version(VERSION9).option("--config <path>", "Path to config file").option("--ci", "CI mode: JSON output, no prompts, proper exit codes", false).option("--verbose", "Enable verbose output", false);
7339
7936
  program2.command("scan").description("Scan database schema").action(async () => {
7340
7937
  const opts = program2.opts();
7341
7938
  await scanCommand({ ci: opts.ci });
@@ -7354,16 +7951,28 @@ function run(argv) {
7354
7951
  });
7355
7952
  program2.command("templates").description("List available domain templates").action(templatesCommand);
7356
7953
  program2.command("scenarios").description("List available scenarios").action(scenariosCommand);
7954
+ program2.command("capture").description("Capture live database state into a Reality Pack").requiredOption("--name <name>", "Name for the captured pack").option("--description <desc>", "Pack description").option("--tables <tables>", "Comma-separated list of tables to capture").option("--output <dir>", "Output directory", ".").action(async (cmdOpts) => {
7955
+ const opts = program2.opts();
7956
+ await captureCommand({ ...cmdOpts, ci: opts.ci });
7957
+ });
7958
+ program2.command("share <file>").description("Share a Reality Pack file").action(async (filePath) => {
7959
+ const opts = program2.opts();
7960
+ await shareCommand(filePath, { ci: opts.ci });
7961
+ });
7962
+ program2.command("load <file>").description("Load a Reality Pack into the database").option("--confirm", "Confirm import operation").option("--show-ddl", "Show schema DDL without importing").action(async (filePath, cmdOpts) => {
7963
+ const opts = program2.opts();
7964
+ await loadCommand(filePath, { ...cmdOpts, ci: opts.ci });
7965
+ });
7357
7966
  const pack = program2.command("pack").description("Reality Pack operations");
7358
7967
  pack.command("export").description("Export environment as Reality Pack").option("--name <name>", "Pack name").option("--description <desc>", "Pack description").option("--output <dir>", "Output directory", ".").option("--records <count>", "Number of records per table").option("--seed <number>", "Random seed for reproducibility").option("--template <name>", "Template to use").option("--timeline <duration>", 'Timeline duration (e.g., "12-months", "1-year")').option("--scenario <names>", "Scenarios to apply (comma-separated)").option("--scenario-intensity <level>", "Scenario intensity (low|medium|high)", "medium").action(packExportCommand);
7359
7968
  pack.command("import <file>").description("Import Reality Pack into database").option("--confirm", "Confirm import operation").action(packImportCommand);
7360
7969
  program2.action(() => {
7361
7970
  const opts = program2.opts();
7362
7971
  if (opts.ci) {
7363
- console.log(JSON.stringify({ name: "realitydb", version: VERSION6 }));
7972
+ console.log(JSON.stringify({ name: "realitydb", version: VERSION9 }));
7364
7973
  } else {
7365
7974
  console.log("");
7366
- console.log(`RealityDB v${VERSION6} \u2014 Developer Reality Platform`);
7975
+ console.log(`RealityDB v${VERSION9} \u2014 Developer Reality Platform`);
7367
7976
  console.log("Run `realitydb --help` for available commands.");
7368
7977
  console.log("");
7369
7978
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "realitydb",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Developer Reality Platform - realistic database environments from your schema",
5
5
  "license": "MIT",
6
6
  "keywords": [