realitydb 1.4.2 → 1.4.4
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 +107 -95
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -10478,27 +10478,27 @@ var saasLifecycle = {
|
|
|
10478
10478
|
{
|
|
10479
10479
|
name: "trial",
|
|
10480
10480
|
weight: 0.12,
|
|
10481
|
-
columnValues: {}
|
|
10481
|
+
columnValues: { status: "active" }
|
|
10482
10482
|
},
|
|
10483
10483
|
{
|
|
10484
10484
|
name: "active",
|
|
10485
10485
|
weight: 0.65,
|
|
10486
|
-
columnValues: {}
|
|
10486
|
+
columnValues: { status: "active" }
|
|
10487
10487
|
},
|
|
10488
10488
|
{
|
|
10489
10489
|
name: "churned",
|
|
10490
10490
|
weight: 0.1,
|
|
10491
|
-
columnValues: {}
|
|
10491
|
+
columnValues: { status: "inactive" }
|
|
10492
10492
|
},
|
|
10493
10493
|
{
|
|
10494
10494
|
name: "past_due",
|
|
10495
10495
|
weight: 0.08,
|
|
10496
|
-
columnValues: {}
|
|
10496
|
+
columnValues: { status: "active" }
|
|
10497
10497
|
},
|
|
10498
10498
|
{
|
|
10499
10499
|
name: "paused",
|
|
10500
10500
|
weight: 0.05,
|
|
10501
|
-
columnValues: {}
|
|
10501
|
+
columnValues: { status: "inactive" }
|
|
10502
10502
|
}
|
|
10503
10503
|
],
|
|
10504
10504
|
transitions: [
|
|
@@ -10510,7 +10510,7 @@ var saasLifecycle = {
|
|
|
10510
10510
|
{
|
|
10511
10511
|
table: "subscriptions",
|
|
10512
10512
|
action: "create",
|
|
10513
|
-
values: { status: "active"
|
|
10513
|
+
values: { status: "active" }
|
|
10514
10514
|
},
|
|
10515
10515
|
{
|
|
10516
10516
|
table: "payments",
|
|
@@ -10613,20 +10613,6 @@ var saasLifecycle = {
|
|
|
10613
10613
|
}
|
|
10614
10614
|
],
|
|
10615
10615
|
correlations: [
|
|
10616
|
-
{
|
|
10617
|
-
description: "Enterprise plan users have 2x more payments (longer tenure)",
|
|
10618
|
-
condition: {
|
|
10619
|
-
table: "subscriptions",
|
|
10620
|
-
column: "plan",
|
|
10621
|
-
operator: "eq",
|
|
10622
|
-
value: "Enterprise"
|
|
10623
|
-
},
|
|
10624
|
-
effect: {
|
|
10625
|
-
table: "payments",
|
|
10626
|
-
column: "amount_cents",
|
|
10627
|
-
multiplier: 2
|
|
10628
|
-
}
|
|
10629
|
-
},
|
|
10630
10616
|
{
|
|
10631
10617
|
description: "Churned users always have a failed payment before cancel",
|
|
10632
10618
|
condition: {
|
|
@@ -11731,53 +11717,13 @@ async function seedDatabase(config, options) {
|
|
|
11731
11717
|
throw new Error(`Generation plan validation failed:
|
|
11732
11718
|
${validation.errors.join("\n")}`);
|
|
11733
11719
|
}
|
|
11734
|
-
let dataset;
|
|
11735
11720
|
const lifecycleUsed = !!options?.lifecycle;
|
|
11721
|
+
let dataset = timelineConfig ? generateTimelineDataset(plan, timelineConfig) : generateDataset(plan);
|
|
11736
11722
|
if (options?.lifecycle && options?.template) {
|
|
11737
11723
|
const lifecycle = resolveLifecycle(options.template);
|
|
11738
11724
|
if (lifecycle) {
|
|
11739
|
-
|
|
11740
|
-
const entityCount = effectiveConfig.seed.defaultRecords;
|
|
11741
|
-
const simResult = simulateLifecycles(lifecycle, entityCount, random);
|
|
11742
|
-
const correlatedResult = applyCorrelations(simResult, lifecycle.correlations, random);
|
|
11743
|
-
const schemaColumnLookup = /* @__PURE__ */ new Map();
|
|
11744
|
-
for (const table of schema.tables) {
|
|
11745
|
-
schemaColumnLookup.set(table.name, new Set(table.columns.map((c) => c.name)));
|
|
11746
|
-
}
|
|
11747
|
-
const tables = /* @__PURE__ */ new Map();
|
|
11748
|
-
let totalRows = 0;
|
|
11749
|
-
for (const [tableName, rows] of correlatedResult.tables) {
|
|
11750
|
-
const validColumns = schemaColumnLookup.get(tableName);
|
|
11751
|
-
const filteredRows = validColumns ? rows.map((row) => {
|
|
11752
|
-
const filtered = {};
|
|
11753
|
-
for (const [col, val] of Object.entries(row)) {
|
|
11754
|
-
if (validColumns.has(col)) {
|
|
11755
|
-
filtered[col] = val;
|
|
11756
|
-
} else {
|
|
11757
|
-
console.warn(`[lifecycle] Skipping column '${col}' on table '${tableName}' \u2014 column does not exist`);
|
|
11758
|
-
}
|
|
11759
|
-
}
|
|
11760
|
-
return filtered;
|
|
11761
|
-
}) : rows;
|
|
11762
|
-
tables.set(tableName, {
|
|
11763
|
-
tableName,
|
|
11764
|
-
columns: filteredRows.length > 0 ? Object.keys(filteredRows[0]) : [],
|
|
11765
|
-
rows: filteredRows,
|
|
11766
|
-
rowCount: filteredRows.length
|
|
11767
|
-
});
|
|
11768
|
-
totalRows += filteredRows.length;
|
|
11769
|
-
}
|
|
11770
|
-
dataset = {
|
|
11771
|
-
tables,
|
|
11772
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11773
|
-
seed: plan.reproducibility.randomSeed,
|
|
11774
|
-
totalRows
|
|
11775
|
-
};
|
|
11776
|
-
} else {
|
|
11777
|
-
dataset = timelineConfig ? generateTimelineDataset(plan, timelineConfig) : generateDataset(plan);
|
|
11725
|
+
dataset = applyLifecycleOverlay(dataset, lifecycle, plan, schema);
|
|
11778
11726
|
}
|
|
11779
|
-
} else {
|
|
11780
|
-
dataset = timelineConfig ? generateTimelineDataset(plan, timelineConfig) : generateDataset(plan);
|
|
11781
11727
|
}
|
|
11782
11728
|
let scenariosApplied;
|
|
11783
11729
|
let scenarioReportData;
|
|
@@ -11819,6 +11765,66 @@ ${validation.errors.join("\n")}`);
|
|
|
11819
11765
|
await closeConnection(pool);
|
|
11820
11766
|
}
|
|
11821
11767
|
}
|
|
11768
|
+
function applyLifecycleOverlay(dataset, lifecycle, plan, schema) {
|
|
11769
|
+
const random = createSeededRandom(plan.reproducibility.randomSeed);
|
|
11770
|
+
const rootTable = dataset.tables.get(lifecycle.rootTable);
|
|
11771
|
+
const entityCount = rootTable?.rowCount ?? plan.tables[0]?.rowCount ?? 0;
|
|
11772
|
+
const simResult = simulateLifecycles(lifecycle, entityCount, random);
|
|
11773
|
+
const correlatedResult = applyCorrelations(simResult, lifecycle.correlations, random);
|
|
11774
|
+
const schemaColumnLookup = /* @__PURE__ */ new Map();
|
|
11775
|
+
for (const table of schema.tables) {
|
|
11776
|
+
schemaColumnLookup.set(table.name, new Set(table.columns.map((c) => c.name)));
|
|
11777
|
+
}
|
|
11778
|
+
const warnedColumns = /* @__PURE__ */ new Set();
|
|
11779
|
+
if (rootTable) {
|
|
11780
|
+
const lifecycleRootRows = correlatedResult.tables.get(lifecycle.rootTable);
|
|
11781
|
+
if (lifecycleRootRows) {
|
|
11782
|
+
const validColumns = schemaColumnLookup.get(lifecycle.rootTable);
|
|
11783
|
+
const count = Math.min(rootTable.rows.length, lifecycleRootRows.length);
|
|
11784
|
+
for (let i = 0; i < count; i++) {
|
|
11785
|
+
for (const [col, val] of Object.entries(lifecycleRootRows[i])) {
|
|
11786
|
+
if (col === "id")
|
|
11787
|
+
continue;
|
|
11788
|
+
if (validColumns && !validColumns.has(col)) {
|
|
11789
|
+
const key = `${lifecycle.rootTable}.${col}`;
|
|
11790
|
+
if (!warnedColumns.has(key)) {
|
|
11791
|
+
console.warn(`[lifecycle] Skipping column '${col}' on table '${lifecycle.rootTable}' \u2014 does not exist in schema`);
|
|
11792
|
+
warnedColumns.add(key);
|
|
11793
|
+
}
|
|
11794
|
+
continue;
|
|
11795
|
+
}
|
|
11796
|
+
rootTable.rows[i][col] = val;
|
|
11797
|
+
}
|
|
11798
|
+
}
|
|
11799
|
+
}
|
|
11800
|
+
}
|
|
11801
|
+
for (const [tableName, lifecycleRows] of correlatedResult.tables) {
|
|
11802
|
+
if (tableName === lifecycle.rootTable)
|
|
11803
|
+
continue;
|
|
11804
|
+
const existingTable = dataset.tables.get(tableName);
|
|
11805
|
+
if (!existingTable || lifecycleRows.length === 0)
|
|
11806
|
+
continue;
|
|
11807
|
+
const validColumns = schemaColumnLookup.get(tableName);
|
|
11808
|
+
const entityIdCol = `${lifecycle.entityName}_id`;
|
|
11809
|
+
const count = Math.min(lifecycleRows.length, existingTable.rows.length);
|
|
11810
|
+
for (let i = 0; i < count; i++) {
|
|
11811
|
+
for (const [col, val] of Object.entries(lifecycleRows[i])) {
|
|
11812
|
+
if (col === "id" || col === entityIdCol)
|
|
11813
|
+
continue;
|
|
11814
|
+
if (validColumns && !validColumns.has(col)) {
|
|
11815
|
+
const key = `${tableName}.${col}`;
|
|
11816
|
+
if (!warnedColumns.has(key)) {
|
|
11817
|
+
console.warn(`[lifecycle] Skipping column '${col}' on table '${tableName}' \u2014 does not exist in schema`);
|
|
11818
|
+
warnedColumns.add(key);
|
|
11819
|
+
}
|
|
11820
|
+
continue;
|
|
11821
|
+
}
|
|
11822
|
+
existingTable.rows[i][col] = val;
|
|
11823
|
+
}
|
|
11824
|
+
}
|
|
11825
|
+
}
|
|
11826
|
+
return dataset;
|
|
11827
|
+
}
|
|
11822
11828
|
function computeTotalMonths(tc) {
|
|
11823
11829
|
const start = new Date(tc.startDate);
|
|
11824
11830
|
const end = new Date(tc.endDate);
|
|
@@ -12763,7 +12769,7 @@ var VERSION2 = "0.10.0";
|
|
|
12763
12769
|
async function scanCommand(options) {
|
|
12764
12770
|
const start = performance.now();
|
|
12765
12771
|
try {
|
|
12766
|
-
const config = await loadConfig();
|
|
12772
|
+
const config = await loadConfig(options.configPath);
|
|
12767
12773
|
const result = await scanDatabase(config);
|
|
12768
12774
|
const { schema } = result;
|
|
12769
12775
|
const masked = maskConnectionString(config.database.connectionString);
|
|
@@ -12883,7 +12889,7 @@ var VERSION3 = "1.3.1";
|
|
|
12883
12889
|
async function seedCommand(options) {
|
|
12884
12890
|
const start = performance.now();
|
|
12885
12891
|
try {
|
|
12886
|
-
const config = await loadConfig();
|
|
12892
|
+
const config = await loadConfig(options.configPath);
|
|
12887
12893
|
const records = options.records ? parseInt(options.records, 10) : void 0;
|
|
12888
12894
|
const seed = options.seed ? parseInt(options.seed, 10) : void 0;
|
|
12889
12895
|
const rawTemplateName = options.template ?? config.template;
|
|
@@ -13093,7 +13099,7 @@ async function resetCommand(options) {
|
|
|
13093
13099
|
process.exit(0);
|
|
13094
13100
|
}
|
|
13095
13101
|
try {
|
|
13096
|
-
const config = await loadConfig();
|
|
13102
|
+
const config = await loadConfig(options.configPath);
|
|
13097
13103
|
const masked = maskConnectionString(config.database.connectionString);
|
|
13098
13104
|
if (!options.ci) {
|
|
13099
13105
|
console.log("");
|
|
@@ -13158,7 +13164,7 @@ var VERSION5 = "1.3.1";
|
|
|
13158
13164
|
async function exportCommand(options) {
|
|
13159
13165
|
const start = performance.now();
|
|
13160
13166
|
try {
|
|
13161
|
-
const config = await loadConfig();
|
|
13167
|
+
const config = await loadConfig(options.configPath);
|
|
13162
13168
|
const format = options.format ?? config.export?.defaultFormat ?? "json";
|
|
13163
13169
|
const outputDir = options.output ?? config.export?.outputDir ?? "./.realitydb";
|
|
13164
13170
|
const records = options.records ? parseInt(options.records, 10) : void 0;
|
|
@@ -13518,7 +13524,7 @@ var import_node_path13 = require("path");
|
|
|
13518
13524
|
var import_promises10 = require("fs/promises");
|
|
13519
13525
|
async function packExportCommand(options) {
|
|
13520
13526
|
try {
|
|
13521
|
-
const config = await loadConfig();
|
|
13527
|
+
const config = await loadConfig(options.configPath);
|
|
13522
13528
|
const records = options.records ? parseInt(options.records, 10) : void 0;
|
|
13523
13529
|
const seed = options.seed ? parseInt(options.seed, 10) : void 0;
|
|
13524
13530
|
const rawTemplateName = options.template ?? config.template;
|
|
@@ -13620,7 +13626,7 @@ async function packImportCommand(filePath, options) {
|
|
|
13620
13626
|
console.error("Usage: realitydb pack import <file> --confirm");
|
|
13621
13627
|
process.exit(1);
|
|
13622
13628
|
}
|
|
13623
|
-
const config = await loadConfig();
|
|
13629
|
+
const config = await loadConfig(options.configPath);
|
|
13624
13630
|
const masked = maskConnectionString(config.database.connectionString);
|
|
13625
13631
|
const pack = await loadRealityPack(filePath);
|
|
13626
13632
|
console.log("");
|
|
@@ -13689,7 +13695,7 @@ async function captureCommand(options) {
|
|
|
13689
13695
|
console.error("Usage: realitydb capture --name <name>");
|
|
13690
13696
|
process.exit(1);
|
|
13691
13697
|
}
|
|
13692
|
-
const config = await loadConfig();
|
|
13698
|
+
const config = await loadConfig(options.configPath);
|
|
13693
13699
|
const masked = maskConnectionString(config.database.connectionString);
|
|
13694
13700
|
const tables = options.tables ? options.tables.split(",").map((t) => t.trim()).filter((t) => t.length > 0) : void 0;
|
|
13695
13701
|
if (!options.ci) {
|
|
@@ -13935,7 +13941,7 @@ async function loadCommand(filePath, options) {
|
|
|
13935
13941
|
}
|
|
13936
13942
|
return;
|
|
13937
13943
|
}
|
|
13938
|
-
const config = await loadConfig();
|
|
13944
|
+
const config = await loadConfig(options.configPath);
|
|
13939
13945
|
const masked = maskConnectionString(config.database.connectionString);
|
|
13940
13946
|
if (!options.ci) {
|
|
13941
13947
|
console.log("");
|
|
@@ -14254,7 +14260,7 @@ var VERSION12 = "1.3.1";
|
|
|
14254
14260
|
async function analyzeCommand(options) {
|
|
14255
14261
|
const start = performance.now();
|
|
14256
14262
|
try {
|
|
14257
|
-
const config = await loadConfig();
|
|
14263
|
+
const config = await loadConfig(options.configPath);
|
|
14258
14264
|
const sampleSize = options.sampleSize ? parseInt(options.sampleSize, 10) : 1e3;
|
|
14259
14265
|
const masked = maskConnectionString(config.database.connectionString);
|
|
14260
14266
|
if (!options.ci) {
|
|
@@ -14348,7 +14354,7 @@ var VERSION13 = "1.3.1";
|
|
|
14348
14354
|
async function maskCommand(options) {
|
|
14349
14355
|
const start = performance.now();
|
|
14350
14356
|
try {
|
|
14351
|
-
const config = await loadConfig();
|
|
14357
|
+
const config = await loadConfig(options.configPath);
|
|
14352
14358
|
const mode = options.mode ?? "gdpr";
|
|
14353
14359
|
const seed = options.seed ? parseInt(options.seed, 10) : void 0;
|
|
14354
14360
|
const dryRun = options.dryRun ?? false;
|
|
@@ -14557,7 +14563,7 @@ async function classroomListCommand(options) {
|
|
|
14557
14563
|
async function classroomStartCommand(courseName, options) {
|
|
14558
14564
|
const start = performance.now();
|
|
14559
14565
|
try {
|
|
14560
|
-
const config = await loadConfig();
|
|
14566
|
+
const config = await loadConfig(options.configPath);
|
|
14561
14567
|
const masked = maskConnectionString(config.database.connectionString);
|
|
14562
14568
|
if (!options.ci) {
|
|
14563
14569
|
console.log("");
|
|
@@ -15010,33 +15016,33 @@ async function simulateWebhooksCommand(options) {
|
|
|
15010
15016
|
}
|
|
15011
15017
|
|
|
15012
15018
|
// src/cli.ts
|
|
15013
|
-
var VERSION16 = "1.
|
|
15019
|
+
var VERSION16 = "1.4.4";
|
|
15014
15020
|
function run(argv) {
|
|
15015
15021
|
const program2 = new Command();
|
|
15016
15022
|
program2.name("realitydb").description("RealityDB \u2014 Developer Reality Platform").version(VERSION16).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);
|
|
15017
15023
|
program2.command("scan").description("Scan database schema").action(async () => {
|
|
15018
15024
|
const opts = program2.opts();
|
|
15019
|
-
await scanCommand({ ci: opts.ci });
|
|
15025
|
+
await scanCommand({ ci: opts.ci, configPath: opts.config });
|
|
15020
15026
|
});
|
|
15021
15027
|
program2.command("analyze").description("Analyze database schema and suggest column strategies").option("--output <file>", "Generate a template JSON file from analysis").option("--sample-size <count>", "Number of rows to sample per table", "1000").action(async (cmdOpts) => {
|
|
15022
15028
|
const opts = program2.opts();
|
|
15023
|
-
await analyzeCommand({ ...cmdOpts, ci: opts.ci });
|
|
15029
|
+
await analyzeCommand({ ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15024
15030
|
});
|
|
15025
15031
|
program2.command("seed").description("Seed database with generated data").option("--records <count>", "Number of records per table").option("--template <name|path>", "Template name or path to custom .json file").option("--seed <number>", "Random seed for reproducibility").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").option("--scenario-schedule <schedule>", 'Timeline-scheduled scenarios (e.g., "fraud-spike:month-6,churn-spike:month-9")').option("--lifecycle", "Enable lifecycle simulation for causally-connected data").action(async (cmdOpts) => {
|
|
15026
15032
|
const opts = program2.opts();
|
|
15027
|
-
await seedCommand({ ...cmdOpts, ci: opts.ci });
|
|
15033
|
+
await seedCommand({ ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15028
15034
|
});
|
|
15029
15035
|
program2.command("reset").description("Reset seeded data").option("--confirm", "Confirm destructive operation").action(async (cmdOpts) => {
|
|
15030
15036
|
const opts = program2.opts();
|
|
15031
|
-
await resetCommand({ ...cmdOpts, ci: opts.ci });
|
|
15037
|
+
await resetCommand({ ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15032
15038
|
});
|
|
15033
15039
|
program2.command("export").description("Export generated data").option("--format <format>", "Output format (json|csv|sql)", "json").option("--output <dir>", "Output directory", "./.realitydb").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").option("--scenario-schedule <schedule>", 'Timeline-scheduled scenarios (e.g., "fraud-spike:month-6,churn-spike:month-9")').action(async (cmdOpts) => {
|
|
15034
15040
|
const opts = program2.opts();
|
|
15035
|
-
await exportCommand({ ...cmdOpts, ci: opts.ci });
|
|
15041
|
+
await exportCommand({ ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15036
15042
|
});
|
|
15037
15043
|
program2.command("generate").description("Generate large-scale datasets for data science (no database required)").option("--records <count>", "Number of records to generate", "1000").option("--schema <file>", "Schema definition file (.sql or .json)").option("--format <format>", "Output format (json|csv|parquet)", "json").option("--output <dir>", "Output directory", "./.realitydb/generated").option("--seed <number>", "Random seed for reproducibility").option("--table <name>", "Generate only a specific table").option("--correlations", "Enable cross-column correlations from schema").action(async (cmdOpts) => {
|
|
15038
15044
|
const opts = program2.opts();
|
|
15039
|
-
await generateCommand({ ...cmdOpts, ci: opts.ci });
|
|
15045
|
+
await generateCommand({ ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15040
15046
|
});
|
|
15041
15047
|
const templates = program2.command("templates").description("Template management");
|
|
15042
15048
|
templates.command("list", { isDefault: true }).description("List available domain templates").action(templatesCommand);
|
|
@@ -15052,61 +15058,67 @@ function run(argv) {
|
|
|
15052
15058
|
});
|
|
15053
15059
|
program2.command("mask").description("Detect and mask PII in your database").option("--mode <mode>", "Compliance mode (hipaa|gdpr|strict)", "gdpr").option("--seed <number>", "Random seed for deterministic masking").option("--dry-run", "Preview PII detection without modifying data").option("--output <dir>", "Export masked data to files instead of writing to DB").option("--output-format <format>", "Output format (json|csv|sql)", "json").option("--audit-log <file>", "Write audit log to file").option("--confirm", "Confirm writing masked data back to database").action(async (cmdOpts) => {
|
|
15054
15060
|
const opts = program2.opts();
|
|
15055
|
-
await maskCommand({ ...cmdOpts, ci: opts.ci });
|
|
15061
|
+
await maskCommand({ ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15056
15062
|
});
|
|
15057
15063
|
const classroom = program2.command("classroom").description("Education and classroom mode");
|
|
15058
15064
|
classroom.command("list", { isDefault: true }).description("List available courses").action(async () => {
|
|
15059
15065
|
const opts = program2.opts();
|
|
15060
|
-
await classroomListCommand({ ci: opts.ci });
|
|
15066
|
+
await classroomListCommand({ ci: opts.ci, configPath: opts.config });
|
|
15061
15067
|
});
|
|
15062
15068
|
classroom.command("start <course>").description("Load a course into your database").action(async (course) => {
|
|
15063
15069
|
const opts = program2.opts();
|
|
15064
|
-
await classroomStartCommand(course, { ci: opts.ci });
|
|
15070
|
+
await classroomStartCommand(course, { ci: opts.ci, configPath: opts.config });
|
|
15065
15071
|
});
|
|
15066
15072
|
classroom.command("status [course]").description("Show progress for all courses or a specific course").action(async (course) => {
|
|
15067
15073
|
const opts = program2.opts();
|
|
15068
|
-
await classroomStatusCommand(course, { ci: opts.ci });
|
|
15074
|
+
await classroomStatusCommand(course, { ci: opts.ci, configPath: opts.config });
|
|
15069
15075
|
});
|
|
15070
15076
|
classroom.command("complete <course> <exercise>").description("Mark an exercise as completed").action(async (course, exercise) => {
|
|
15071
15077
|
const opts = program2.opts();
|
|
15072
|
-
await classroomCompleteCommand(course, exercise, { ci: opts.ci });
|
|
15078
|
+
await classroomCompleteCommand(course, exercise, { ci: opts.ci, configPath: opts.config });
|
|
15073
15079
|
});
|
|
15074
15080
|
classroom.command("reset <course>").description("Reset progress for a course").action(async (course) => {
|
|
15075
15081
|
const opts = program2.opts();
|
|
15076
|
-
await classroomResetCommand(course, { ci: opts.ci });
|
|
15082
|
+
await classroomResetCommand(course, { ci: opts.ci, configPath: opts.config });
|
|
15077
15083
|
});
|
|
15078
15084
|
classroom.command("create <name>").description("Scaffold a custom course JSON file").action(async (name) => {
|
|
15079
15085
|
const opts = program2.opts();
|
|
15080
|
-
await classroomCreateCommand(name, { ci: opts.ci });
|
|
15086
|
+
await classroomCreateCommand(name, { ci: opts.ci, configPath: opts.config });
|
|
15081
15087
|
});
|
|
15082
15088
|
const simulate = program2.command("simulate").description("System behavior simulation");
|
|
15083
15089
|
simulate.command("run", { isDefault: true }).description("Run a simulation with a profile").option("--profile <name>", "Simulation profile (saas-startup|ecommerce-peak|api-service)", "saas-startup").option("--duration <duration>", "Override profile duration (e.g., 1-hour, 1-day, 1-week)").option("--events <count>", "Number of events to generate", "1000").option("--seed <number>", "Random seed for reproducibility").option("--output <file>", "Output file path").option("--format <format>", "Output format (json|ndjson)", "json").action(async (cmdOpts) => {
|
|
15084
15090
|
const opts = program2.opts();
|
|
15085
|
-
await simulateRunCommand({ ...cmdOpts, ci: opts.ci });
|
|
15091
|
+
await simulateRunCommand({ ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15086
15092
|
});
|
|
15087
15093
|
simulate.command("profiles").description("List available simulation profiles").action(async () => {
|
|
15088
15094
|
const opts = program2.opts();
|
|
15089
|
-
await simulateProfilesCommand({ ci: opts.ci });
|
|
15095
|
+
await simulateProfilesCommand({ ci: opts.ci, configPath: opts.config });
|
|
15090
15096
|
});
|
|
15091
15097
|
simulate.command("webhooks").description("Generate webhook events from a specific source").option("--source <source>", "Webhook source (stripe|github)", "stripe").option("--events <count>", "Number of events to generate", "100").option("--seed <number>", "Random seed for reproducibility").option("--output <file>", "Output file path").option("--format <format>", "Output format (json|ndjson)", "json").action(async (cmdOpts) => {
|
|
15092
15098
|
const opts = program2.opts();
|
|
15093
|
-
await simulateWebhooksCommand({ ...cmdOpts, ci: opts.ci });
|
|
15099
|
+
await simulateWebhooksCommand({ ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15094
15100
|
});
|
|
15095
15101
|
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) => {
|
|
15096
15102
|
const opts = program2.opts();
|
|
15097
|
-
await captureCommand({ ...cmdOpts, ci: opts.ci });
|
|
15103
|
+
await captureCommand({ ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15098
15104
|
});
|
|
15099
15105
|
program2.command("share <file>").description("Share a Reality Pack file").option("--gist", "Upload to GitHub Gist").option("--description <desc>", "Gist description").action(async (filePath, cmdOpts) => {
|
|
15100
15106
|
const opts = program2.opts();
|
|
15101
|
-
await shareCommand(filePath, { ...cmdOpts, ci: opts.ci });
|
|
15107
|
+
await shareCommand(filePath, { ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15102
15108
|
});
|
|
15103
15109
|
program2.command("load <file>").description("Load a Reality Pack into the database (file path or URL)").option("--confirm", "Confirm import operation").option("--show-ddl", "Show schema DDL without importing").action(async (filePath, cmdOpts) => {
|
|
15104
15110
|
const opts = program2.opts();
|
|
15105
|
-
await loadCommand(filePath, { ...cmdOpts, ci: opts.ci });
|
|
15111
|
+
await loadCommand(filePath, { ...cmdOpts, ci: opts.ci, configPath: opts.config });
|
|
15106
15112
|
});
|
|
15107
15113
|
const pack = program2.command("pack").description("Reality Pack operations");
|
|
15108
|
-
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").option("--scenario-schedule <schedule>", 'Timeline-scheduled scenarios (e.g., "fraud-spike:month-6,churn-spike:month-9")').action(
|
|
15109
|
-
|
|
15114
|
+
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").option("--scenario-schedule <schedule>", 'Timeline-scheduled scenarios (e.g., "fraud-spike:month-6,churn-spike:month-9")').action(async (cmdOpts) => {
|
|
15115
|
+
const opts = program2.opts();
|
|
15116
|
+
await packExportCommand({ ...cmdOpts, configPath: opts.config });
|
|
15117
|
+
});
|
|
15118
|
+
pack.command("import <file>").description("Import Reality Pack into database").option("--confirm", "Confirm import operation").action(async (filePath, cmdOpts) => {
|
|
15119
|
+
const opts = program2.opts();
|
|
15120
|
+
await packImportCommand(filePath, { ...cmdOpts, configPath: opts.config });
|
|
15121
|
+
});
|
|
15110
15122
|
const packs = program2.command("packs").description("Browse available Reality Packs");
|
|
15111
15123
|
packs.command("list", { isDefault: true }).description("List available demo packs").action(() => {
|
|
15112
15124
|
const opts = program2.opts();
|
package/package.json
CHANGED