@contrail/cli 3.4.4 → 3.4.5-alpha.18160f5
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/README.md +1 -1
- package/dist/commands/load-local/index.d.ts +18 -0
- package/dist/commands/load-local/index.js +157 -0
- package/dist/helpers/pipeline/formatters.d.ts +6 -0
- package/dist/helpers/pipeline/formatters.js +223 -0
- package/node_modules/@contrail/entity-types/.idea/codeStyles/Project.xml +62 -0
- package/node_modules/@contrail/entity-types/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/node_modules/@contrail/entity-types/.idea/contrail-entity-types.iml +12 -0
- package/node_modules/@contrail/entity-types/.idea/git_toolbox_prj.xml +15 -0
- package/node_modules/@contrail/entity-types/.idea/modules.xml +8 -0
- package/node_modules/@contrail/entity-types/.idea/vcs.xml +6 -0
- package/node_modules/@contrail/entity-types/lib/loader.d.ts +15 -17
- package/node_modules/@contrail/entity-types/lib/loader.js +5 -43
- package/node_modules/@contrail/entity-types/package.json +1 -1
- package/oclif.manifest.json +86 -1
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ $ npm install -g @contrail/cli
|
|
|
17
17
|
$ contrail COMMAND
|
|
18
18
|
running command...
|
|
19
19
|
$ contrail (--version)
|
|
20
|
-
@contrail/cli/3.4.
|
|
20
|
+
@contrail/cli/3.4.5-alpha.18160f5 linux-x64 node-v18.20.8
|
|
21
21
|
$ contrail --help [COMMAND]
|
|
22
22
|
USAGE
|
|
23
23
|
$ contrail COMMAND
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseCommand } from '../../basecommand';
|
|
2
|
+
export default class LoadLocal extends BaseCommand {
|
|
3
|
+
static hidden: boolean;
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
stage: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
|
+
alwaysConfirmEnv: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
11
|
+
logLevel: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
static args: {
|
|
14
|
+
dataFile: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
15
|
+
configFile: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const sdk_1 = require("@contrail/sdk");
|
|
6
|
+
const loader_1 = require("@contrail/loader");
|
|
7
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
|
+
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
9
|
+
const login_1 = require("../../auth/login");
|
|
10
|
+
const basecommand_1 = require("../../basecommand");
|
|
11
|
+
const helpers_1 = require("../../helpers/load/helpers");
|
|
12
|
+
const file_helpers_1 = require("../../helpers/file-helpers");
|
|
13
|
+
const logger_1 = tslib_1.__importDefault(require("../../logger"));
|
|
14
|
+
const formatters_1 = require("../../helpers/pipeline/formatters");
|
|
15
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
16
|
+
const path = tslib_1.__importStar(require("path"));
|
|
17
|
+
class LoadLocal extends basecommand_1.BaseCommand {
|
|
18
|
+
static hidden = true;
|
|
19
|
+
static description = 'Run the full data loading pipeline locally. Reads a CSV data file and a YAML/JSON config, then runs preprocess → analyze → validate → preview → execute stages with detailed feedback.';
|
|
20
|
+
static examples = [
|
|
21
|
+
'$ contrail load-local data.csv config.yml',
|
|
22
|
+
'$ contrail load-local data.csv config.yml --dry-run',
|
|
23
|
+
'$ contrail load-local data.csv config.yml --yes',
|
|
24
|
+
'$ contrail load-local data.csv config.yml --stage 3',
|
|
25
|
+
];
|
|
26
|
+
static flags = {
|
|
27
|
+
...basecommand_1.BaseCommand.baseFlags,
|
|
28
|
+
yes: core_1.Flags.boolean({
|
|
29
|
+
char: 'y',
|
|
30
|
+
description: 'Skip confirmation prompt before executing',
|
|
31
|
+
default: false,
|
|
32
|
+
}),
|
|
33
|
+
'dry-run': core_1.Flags.boolean({
|
|
34
|
+
char: 'd',
|
|
35
|
+
description: 'Run stages 1-4 only (no execution)',
|
|
36
|
+
default: false,
|
|
37
|
+
}),
|
|
38
|
+
stage: core_1.Flags.integer({
|
|
39
|
+
char: 's',
|
|
40
|
+
description: 'Run only up to this stage (1-5)',
|
|
41
|
+
options: ['1', '2', '3', '4', '5'],
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
static args = {
|
|
45
|
+
dataFile: core_1.Args.string({
|
|
46
|
+
description: 'Path to the CSV data file',
|
|
47
|
+
required: true,
|
|
48
|
+
}),
|
|
49
|
+
configFile: core_1.Args.string({
|
|
50
|
+
description: 'Path to the YAML or JSON configuration file',
|
|
51
|
+
required: true,
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
async run() {
|
|
55
|
+
const maxStage = this.flags['dry-run'] ? 4 : this.flags.stage || 5;
|
|
56
|
+
// Read and parse files
|
|
57
|
+
let csvData;
|
|
58
|
+
let config;
|
|
59
|
+
try {
|
|
60
|
+
const csvPath = path.resolve(process.cwd(), this.args.dataFile);
|
|
61
|
+
const csvRaw = fs.readFileSync(csvPath, 'utf8');
|
|
62
|
+
csvData = (0, file_helpers_1.parseCSVData)(csvRaw);
|
|
63
|
+
logger_1.default.info(`${chalk_1.default.yellow.bold('LOAD-LOCAL')} Parsed ${csvData.length} rows from ${this.args.dataFile}`);
|
|
64
|
+
const ext = this.args.configFile.toLowerCase();
|
|
65
|
+
const fileExt = ext.endsWith('.yml') || ext.endsWith('.yaml')
|
|
66
|
+
? helpers_1.FileExtension.YAML
|
|
67
|
+
: helpers_1.FileExtension.JSON;
|
|
68
|
+
config = (0, helpers_1.readFile)(this.args.configFile, fileExt);
|
|
69
|
+
logger_1.default.info(`${chalk_1.default.yellow.bold('LOAD-LOCAL')} Loaded config from ${this.args.configFile}`);
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
logger_1.default.info(`${chalk_1.default.red.bold('FAIL')} Failed to read input files. ${e}`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Authenticate and create pipeline
|
|
76
|
+
await (0, login_1.authUser)();
|
|
77
|
+
const pipeline = new loader_1.LoaderPipeline(new sdk_1.Entities());
|
|
78
|
+
try {
|
|
79
|
+
// Fetch type definitions (needed by both preprocessing and column analysis)
|
|
80
|
+
logger_1.default.info(`\n${chalk_1.default.yellow.bold('LOAD-LOCAL')} Fetching type definitions...`);
|
|
81
|
+
const typeDefs = await pipeline.fetchTypeDefinitions(csvData, config);
|
|
82
|
+
// Stage 1: Preprocess
|
|
83
|
+
logger_1.default.info(`\n${chalk_1.default.yellow.bold('LOAD-LOCAL')} Running Stage 1: Preprocess...`);
|
|
84
|
+
const preprocessed = await pipeline.preprocess(csvData, config, typeDefs);
|
|
85
|
+
console.log('\n' + (0, formatters_1.formatPreprocessResult)(preprocessed));
|
|
86
|
+
if (maxStage <= 1)
|
|
87
|
+
return;
|
|
88
|
+
// Stage 2: Analyze Columns
|
|
89
|
+
logger_1.default.info(`\n${chalk_1.default.yellow.bold('LOAD-LOCAL')} Running Stage 2: Analyze Columns...`);
|
|
90
|
+
const analysis = pipeline.analyzeColumns(preprocessed, config, typeDefs);
|
|
91
|
+
console.log('\n' + (0, formatters_1.formatColumnAnalysis)(analysis));
|
|
92
|
+
if (maxStage <= 2)
|
|
93
|
+
return;
|
|
94
|
+
// Stage 3: Validate
|
|
95
|
+
logger_1.default.info(`\n${chalk_1.default.yellow.bold('LOAD-LOCAL')} Running Stage 3: Validate...`);
|
|
96
|
+
const validation = await pipeline.validate(preprocessed, config, analysis);
|
|
97
|
+
console.log('\n' + (0, formatters_1.formatValidationResult)(validation));
|
|
98
|
+
if (!validation.valid) {
|
|
99
|
+
logger_1.default.info(`\n${chalk_1.default.red.bold('LOAD-LOCAL')} Validation failed. Fix the issues above before proceeding.`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (maxStage <= 3)
|
|
103
|
+
return;
|
|
104
|
+
// Stage 4: Preview
|
|
105
|
+
logger_1.default.info(`\n${chalk_1.default.yellow.bold('LOAD-LOCAL')} Running Stage 4: Preview...`);
|
|
106
|
+
const previewResult = await pipeline.preview(preprocessed, config, analysis);
|
|
107
|
+
console.log('\n' + (0, formatters_1.formatPreviewResult)(previewResult));
|
|
108
|
+
if (maxStage <= 4)
|
|
109
|
+
return;
|
|
110
|
+
// Confirm before execute
|
|
111
|
+
if (!this.flags.yes) {
|
|
112
|
+
const noChangesDetected = previewResult.entities.every((e) => e.creates === 0 && e.updates === 0 && e.drops === 0);
|
|
113
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
114
|
+
{
|
|
115
|
+
type: 'confirm',
|
|
116
|
+
name: 'confirm',
|
|
117
|
+
message: noChangesDetected
|
|
118
|
+
? 'Proceed with the execution step anyway? This will try to detect updates again and persist any detected changes.'
|
|
119
|
+
: 'Proceed with execution?',
|
|
120
|
+
default: false,
|
|
121
|
+
},
|
|
122
|
+
]);
|
|
123
|
+
if (!confirm) {
|
|
124
|
+
logger_1.default.info(`${chalk_1.default.yellow.bold('LOAD-LOCAL')} Execution cancelled.`);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Stage 5: Execute
|
|
129
|
+
logger_1.default.info(`\n${chalk_1.default.yellow.bold('LOAD-LOCAL')} Running Stage 5: Execute...`);
|
|
130
|
+
const executeOptions = {
|
|
131
|
+
batchSize: config.options?.batchSize,
|
|
132
|
+
concurrency: config.options?.concurrency,
|
|
133
|
+
maxRetries: config.options?.maxRetries,
|
|
134
|
+
onProgress: (progress) => {
|
|
135
|
+
process.stdout.write(`\r ${chalk_1.default.dim(progress.stage)}: ${progress.current}/${progress.total}`);
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
const executionResult = await pipeline.execute(preprocessed, config, analysis, executeOptions, previewResult);
|
|
139
|
+
// Clear progress line
|
|
140
|
+
process.stdout.write('\r' + ' '.repeat(60) + '\r');
|
|
141
|
+
console.log('\n' + (0, formatters_1.formatExecutionResult)(executionResult));
|
|
142
|
+
if (executionResult.status === 'complete') {
|
|
143
|
+
logger_1.default.info(`\n${chalk_1.default.green.bold('COMPLETE')} Load finished successfully.`);
|
|
144
|
+
}
|
|
145
|
+
else if (executionResult.status === 'partial-failure') {
|
|
146
|
+
logger_1.default.info(`\n${chalk_1.default.yellow.bold('PARTIAL')} Load completed with some failures.`);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
logger_1.default.info(`\n${chalk_1.default.red.bold('FAILED')} Load failed.`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
logger_1.default.info(`\n${chalk_1.default.red.bold('FAIL')} Pipeline error: ${e}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
exports.default = LoadLocal;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ColumnAnalysisResult, PreprocessResult, PreviewResult, ExecutionResult, PreValidationResult } from '@contrail/loader';
|
|
2
|
+
export declare function formatColumnAnalysis(result: ColumnAnalysisResult): string;
|
|
3
|
+
export declare function formatPreprocessResult(result: PreprocessResult): string;
|
|
4
|
+
export declare function formatValidationResult(result: PreValidationResult): string;
|
|
5
|
+
export declare function formatPreviewResult(result: PreviewResult): string;
|
|
6
|
+
export declare function formatExecutionResult(result: ExecutionResult): string;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatExecutionResult = exports.formatPreviewResult = exports.formatValidationResult = exports.formatPreprocessResult = exports.formatColumnAnalysis = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
+
const cli_table3_1 = tslib_1.__importDefault(require("cli-table3"));
|
|
7
|
+
const loader_1 = require("@contrail/loader");
|
|
8
|
+
function formatColumnAnalysis(result) {
|
|
9
|
+
const table = new cli_table3_1.default({
|
|
10
|
+
head: [
|
|
11
|
+
chalk_1.default.cyan('CSV Header'),
|
|
12
|
+
chalk_1.default.cyan('Matched Slug'),
|
|
13
|
+
chalk_1.default.cyan('Property Type'),
|
|
14
|
+
chalk_1.default.cyan('Mapped'),
|
|
15
|
+
chalk_1.default.cyan('Required'),
|
|
16
|
+
chalk_1.default.cyan('Option Set'),
|
|
17
|
+
chalk_1.default.cyan('Archived'),
|
|
18
|
+
],
|
|
19
|
+
style: { head: [] },
|
|
20
|
+
});
|
|
21
|
+
for (const col of result.columns) {
|
|
22
|
+
table.push([
|
|
23
|
+
col.csvHeader,
|
|
24
|
+
col.matchedSlug || chalk_1.default.dim('—'),
|
|
25
|
+
col.propertyType || chalk_1.default.dim('—'),
|
|
26
|
+
col.isMapped ? chalk_1.default.green('yes') : chalk_1.default.red('no'),
|
|
27
|
+
col.isRequired
|
|
28
|
+
? chalk_1.default.yellow(col.requiredNote ? `yes (${col.requiredNote})` : 'yes')
|
|
29
|
+
: 'no',
|
|
30
|
+
col.hasOptionSet ? 'yes' : 'no',
|
|
31
|
+
col.isArchived ? chalk_1.default.red('yes') : 'no',
|
|
32
|
+
]);
|
|
33
|
+
}
|
|
34
|
+
const mapped = result.columns.filter((c) => c.isMapped).length;
|
|
35
|
+
const unmapped = result.columns.filter((c) => !c.isMapped).length;
|
|
36
|
+
return [
|
|
37
|
+
chalk_1.default.bold.underline('Stage 2: Column Analysis'),
|
|
38
|
+
table.toString(),
|
|
39
|
+
` ${chalk_1.default.green(mapped)} mapped, ${unmapped > 0 ? chalk_1.default.red(unmapped) : unmapped} unmapped, ${result.columns.length} total columns`,
|
|
40
|
+
` Entity types: ${result.entityTypes.join(', ') || 'none'}`,
|
|
41
|
+
].join('\n');
|
|
42
|
+
}
|
|
43
|
+
exports.formatColumnAnalysis = formatColumnAnalysis;
|
|
44
|
+
function formatPreprocessResult(result) {
|
|
45
|
+
const table = new cli_table3_1.default({
|
|
46
|
+
head: [
|
|
47
|
+
chalk_1.default.cyan('Step'),
|
|
48
|
+
chalk_1.default.cyan('Rows After'),
|
|
49
|
+
chalk_1.default.cyan('Errors'),
|
|
50
|
+
chalk_1.default.cyan('Warnings'),
|
|
51
|
+
],
|
|
52
|
+
style: { head: [] },
|
|
53
|
+
});
|
|
54
|
+
for (const step of result.stepResults) {
|
|
55
|
+
table.push([
|
|
56
|
+
step.stepName,
|
|
57
|
+
step.rowCountAfter.toString(),
|
|
58
|
+
step.errorCount > 0 ? chalk_1.default.red(step.errorCount.toString()) : '0',
|
|
59
|
+
step.warningCount > 0 ? chalk_1.default.yellow(step.warningCount.toString()) : '0',
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
const totalErrors = result.errors.length + result.generalErrors.length;
|
|
63
|
+
const totalWarnings = result.warnings.length + result.generalWarnings.length;
|
|
64
|
+
return [
|
|
65
|
+
chalk_1.default.bold.underline('Stage 1: Preprocessing'),
|
|
66
|
+
table.toString(),
|
|
67
|
+
` ${result.rows.length} rows after preprocessing, ${totalErrors > 0 ? chalk_1.default.red(`${totalErrors} errors`) : '0 errors'}, ${totalWarnings > 0 ? chalk_1.default.yellow(`${totalWarnings} warnings`) : '0 warnings'}`,
|
|
68
|
+
].join('\n');
|
|
69
|
+
}
|
|
70
|
+
exports.formatPreprocessResult = formatPreprocessResult;
|
|
71
|
+
function formatValidationResult(result) {
|
|
72
|
+
const lines = [chalk_1.default.bold.underline('Stage 3: Validation')];
|
|
73
|
+
if (result.valid) {
|
|
74
|
+
lines.push(` ${chalk_1.default.green.bold('VALID')} — no issues found`);
|
|
75
|
+
return lines.join('\n');
|
|
76
|
+
}
|
|
77
|
+
const table = new cli_table3_1.default({
|
|
78
|
+
head: [
|
|
79
|
+
chalk_1.default.cyan('Severity'),
|
|
80
|
+
chalk_1.default.cyan('Category'),
|
|
81
|
+
chalk_1.default.cyan('Column'),
|
|
82
|
+
chalk_1.default.cyan('Message'),
|
|
83
|
+
chalk_1.default.cyan('Rows Affected'),
|
|
84
|
+
chalk_1.default.cyan('Suggested Fix'),
|
|
85
|
+
],
|
|
86
|
+
style: { head: [] },
|
|
87
|
+
colWidths: [10, 16, 16, 40, 14, 24],
|
|
88
|
+
wordWrap: true,
|
|
89
|
+
});
|
|
90
|
+
for (const issue of result.issues) {
|
|
91
|
+
const severityStr = issue.severity === loader_1.PreValidationSeverity.ERROR
|
|
92
|
+
? chalk_1.default.red('ERROR')
|
|
93
|
+
: issue.severity === loader_1.PreValidationSeverity.WARNING
|
|
94
|
+
? chalk_1.default.yellow('WARN')
|
|
95
|
+
: chalk_1.default.blue('INFO');
|
|
96
|
+
table.push([
|
|
97
|
+
severityStr,
|
|
98
|
+
issue.category,
|
|
99
|
+
issue.columnName,
|
|
100
|
+
issue.message,
|
|
101
|
+
issue.affectedRows.length.toString(),
|
|
102
|
+
issue.suggestedFix ? `${issue.suggestedFix.type}` : chalk_1.default.dim('—'),
|
|
103
|
+
]);
|
|
104
|
+
}
|
|
105
|
+
lines.push(table.toString());
|
|
106
|
+
lines.push(` ${chalk_1.default.red(`${result.summary.errorCount} errors`)}, ${chalk_1.default.yellow(`${result.summary.warningCount} warnings`)}, ${result.summary.infoCount} info`);
|
|
107
|
+
return lines.join('\n');
|
|
108
|
+
}
|
|
109
|
+
exports.formatValidationResult = formatValidationResult;
|
|
110
|
+
function formatPreviewResult(result) {
|
|
111
|
+
const table = new cli_table3_1.default({
|
|
112
|
+
head: [
|
|
113
|
+
chalk_1.default.cyan('Entity Type'),
|
|
114
|
+
chalk_1.default.cyan('Total'),
|
|
115
|
+
chalk_1.default.cyan('Creates'),
|
|
116
|
+
chalk_1.default.cyan('Updates'),
|
|
117
|
+
chalk_1.default.cyan('Unchanged'),
|
|
118
|
+
chalk_1.default.cyan('Drops'),
|
|
119
|
+
chalk_1.default.cyan('Stale Skipped'),
|
|
120
|
+
],
|
|
121
|
+
style: { head: [] },
|
|
122
|
+
});
|
|
123
|
+
for (const entity of result.entities) {
|
|
124
|
+
table.push([
|
|
125
|
+
entity.entityType,
|
|
126
|
+
entity.total.toString(),
|
|
127
|
+
entity.creates > 0 ? chalk_1.default.green(entity.creates.toString()) : '0',
|
|
128
|
+
entity.updates > 0 ? chalk_1.default.blue(entity.updates.toString()) : '0',
|
|
129
|
+
entity.unchanged.toString(),
|
|
130
|
+
entity.drops > 0 ? chalk_1.default.red(entity.drops.toString()) : '0',
|
|
131
|
+
entity.skippedStale > 0 ? chalk_1.default.yellow(entity.skippedStale.toString()) : '0',
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
const totalChanges = result.entities.reduce((sum, e) => sum + e.creates + e.updates + e.drops, 0);
|
|
135
|
+
const hasWarnings = result.warnings.length > 0 || result.badRows.length > 0;
|
|
136
|
+
const lines = [chalk_1.default.bold.underline('Stage 4: Preview')];
|
|
137
|
+
if (totalChanges === 0 && !hasWarnings) {
|
|
138
|
+
lines.push(chalk_1.default.green.bold('\n ✔ No changes to make — all entities already exist and have the same property values as the load file.\n'));
|
|
139
|
+
}
|
|
140
|
+
else if (totalChanges === 0 && hasWarnings) {
|
|
141
|
+
lines.push(chalk_1.default.yellow.bold('\n No changes to make, but some rows could not be processed. See warnings below.\n'));
|
|
142
|
+
}
|
|
143
|
+
lines.push(table.toString());
|
|
144
|
+
if (result.badRows.length > 0) {
|
|
145
|
+
lines.push(chalk_1.default.red(` ${result.badRows.length} bad rows skipped:`));
|
|
146
|
+
for (const row of result.badRows.slice(0, 10)) {
|
|
147
|
+
lines.push(` Row ${row.rowNumber}: ${row.reason}`);
|
|
148
|
+
}
|
|
149
|
+
if (result.badRows.length > 10) {
|
|
150
|
+
lines.push(chalk_1.default.dim(` ... and ${result.badRows.length - 10} more`));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (result.staleRows.length > 0) {
|
|
154
|
+
lines.push(chalk_1.default.yellow(` ${result.staleRows.length} stale rows skipped`));
|
|
155
|
+
}
|
|
156
|
+
if (result.warnings.length > 0) {
|
|
157
|
+
lines.push(chalk_1.default.yellow(` ${result.warnings.length} warnings:`));
|
|
158
|
+
for (const w of result.warnings.slice(0, 5)) {
|
|
159
|
+
lines.push(` ${w}`);
|
|
160
|
+
}
|
|
161
|
+
if (result.warnings.length > 5) {
|
|
162
|
+
lines.push(chalk_1.default.dim(` ... and ${result.warnings.length - 5} more`));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return lines.join('\n');
|
|
166
|
+
}
|
|
167
|
+
exports.formatPreviewResult = formatPreviewResult;
|
|
168
|
+
function formatExecutionResult(result) {
|
|
169
|
+
const statusColor = result.status === 'complete'
|
|
170
|
+
? chalk_1.default.green.bold
|
|
171
|
+
: result.status === 'partial-failure'
|
|
172
|
+
? chalk_1.default.yellow.bold
|
|
173
|
+
: chalk_1.default.red.bold;
|
|
174
|
+
const table = new cli_table3_1.default({
|
|
175
|
+
head: [
|
|
176
|
+
chalk_1.default.cyan('Entity Type'),
|
|
177
|
+
chalk_1.default.cyan('Total'),
|
|
178
|
+
chalk_1.default.cyan('Created'),
|
|
179
|
+
chalk_1.default.cyan('Updated'),
|
|
180
|
+
chalk_1.default.cyan('Dropped'),
|
|
181
|
+
chalk_1.default.cyan('Stale Skipped'),
|
|
182
|
+
chalk_1.default.cyan('Failed'),
|
|
183
|
+
],
|
|
184
|
+
style: { head: [] },
|
|
185
|
+
});
|
|
186
|
+
for (const entity of result.entities) {
|
|
187
|
+
const total = entity.created + entity.updated + entity.dropped + entity.skippedStale + entity.failed;
|
|
188
|
+
table.push([
|
|
189
|
+
entity.entityType,
|
|
190
|
+
total.toString(),
|
|
191
|
+
entity.created > 0 ? chalk_1.default.green(entity.created.toString()) : '0',
|
|
192
|
+
entity.updated > 0 ? chalk_1.default.blue(entity.updated.toString()) : '0',
|
|
193
|
+
entity.dropped > 0 ? chalk_1.default.red(entity.dropped.toString()) : '0',
|
|
194
|
+
entity.skippedStale > 0 ? chalk_1.default.yellow(entity.skippedStale.toString()) : '0',
|
|
195
|
+
entity.failed > 0 ? chalk_1.default.red.bold(entity.failed.toString()) : '0',
|
|
196
|
+
]);
|
|
197
|
+
}
|
|
198
|
+
const totalOps = result.entities.reduce((sum, e) => sum + e.created + e.updated + e.dropped, 0);
|
|
199
|
+
const lines = [
|
|
200
|
+
chalk_1.default.bold.underline('Stage 5: Execution'),
|
|
201
|
+
` Status: ${statusColor(result.status.toUpperCase())}`,
|
|
202
|
+
` Duration: ${(result.duration / 1000).toFixed(1)}s`,
|
|
203
|
+
];
|
|
204
|
+
if (totalOps === 0 && result.entities.reduce((sum, e) => sum + e.failed, 0) === 0) {
|
|
205
|
+
lines.push(chalk_1.default.green.bold('\n ✔ No changes were needed — all entities already exist and have the same property values as the load file.\n'));
|
|
206
|
+
}
|
|
207
|
+
lines.push(table.toString());
|
|
208
|
+
const allFailures = result.entities.flatMap((e) => e.failures);
|
|
209
|
+
if (allFailures.length > 0) {
|
|
210
|
+
lines.push(chalk_1.default.red(` ${allFailures.length} failures:`));
|
|
211
|
+
for (const f of allFailures.slice(0, 10)) {
|
|
212
|
+
lines.push(` ${f.operation} ${f.federatedId}: ${f.error}`);
|
|
213
|
+
}
|
|
214
|
+
if (allFailures.length > 10) {
|
|
215
|
+
lines.push(chalk_1.default.dim(` ... and ${allFailures.length - 10} more`));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (result.warnings.length > 0) {
|
|
219
|
+
lines.push(chalk_1.default.yellow(` ${result.warnings.length} warnings`));
|
|
220
|
+
}
|
|
221
|
+
return lines.join('\n');
|
|
222
|
+
}
|
|
223
|
+
exports.formatExecutionResult = formatExecutionResult;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<component name="ProjectCodeStyleConfiguration">
|
|
2
|
+
<code_scheme name="Project" version="173">
|
|
3
|
+
<HTMLCodeStyleSettings>
|
|
4
|
+
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
|
5
|
+
</HTMLCodeStyleSettings>
|
|
6
|
+
<JSCodeStyleSettings version="0">
|
|
7
|
+
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
|
8
|
+
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
|
9
|
+
<option name="USE_DOUBLE_QUOTES" value="false" />
|
|
10
|
+
<option name="FORCE_QUOTE_STYlE" value="true" />
|
|
11
|
+
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
|
|
12
|
+
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
|
13
|
+
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
|
14
|
+
</JSCodeStyleSettings>
|
|
15
|
+
<TypeScriptCodeStyleSettings version="0">
|
|
16
|
+
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
|
17
|
+
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
|
18
|
+
<option name="USE_DOUBLE_QUOTES" value="false" />
|
|
19
|
+
<option name="FORCE_QUOTE_STYlE" value="true" />
|
|
20
|
+
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
|
|
21
|
+
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
|
22
|
+
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
|
23
|
+
</TypeScriptCodeStyleSettings>
|
|
24
|
+
<VueCodeStyleSettings>
|
|
25
|
+
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
|
|
26
|
+
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
|
|
27
|
+
</VueCodeStyleSettings>
|
|
28
|
+
<editorconfig>
|
|
29
|
+
<option name="ENABLED" value="false" />
|
|
30
|
+
</editorconfig>
|
|
31
|
+
<codeStyleSettings language="HTML">
|
|
32
|
+
<option name="SOFT_MARGINS" value="120" />
|
|
33
|
+
<indentOptions>
|
|
34
|
+
<option name="INDENT_SIZE" value="2" />
|
|
35
|
+
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
|
36
|
+
<option name="TAB_SIZE" value="2" />
|
|
37
|
+
</indentOptions>
|
|
38
|
+
</codeStyleSettings>
|
|
39
|
+
<codeStyleSettings language="JavaScript">
|
|
40
|
+
<option name="SOFT_MARGINS" value="120" />
|
|
41
|
+
<indentOptions>
|
|
42
|
+
<option name="INDENT_SIZE" value="2" />
|
|
43
|
+
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
|
44
|
+
<option name="TAB_SIZE" value="2" />
|
|
45
|
+
</indentOptions>
|
|
46
|
+
</codeStyleSettings>
|
|
47
|
+
<codeStyleSettings language="TypeScript">
|
|
48
|
+
<option name="SOFT_MARGINS" value="120" />
|
|
49
|
+
<indentOptions>
|
|
50
|
+
<option name="INDENT_SIZE" value="2" />
|
|
51
|
+
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
|
52
|
+
<option name="TAB_SIZE" value="2" />
|
|
53
|
+
</indentOptions>
|
|
54
|
+
</codeStyleSettings>
|
|
55
|
+
<codeStyleSettings language="Vue">
|
|
56
|
+
<option name="SOFT_MARGINS" value="120" />
|
|
57
|
+
<indentOptions>
|
|
58
|
+
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
|
59
|
+
</indentOptions>
|
|
60
|
+
</codeStyleSettings>
|
|
61
|
+
</code_scheme>
|
|
62
|
+
</component>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="WEB_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager">
|
|
4
|
+
<content url="file://$MODULE_DIR$">
|
|
5
|
+
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
6
|
+
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
7
|
+
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
8
|
+
</content>
|
|
9
|
+
<orderEntry type="inheritedJdk" />
|
|
10
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
11
|
+
</component>
|
|
12
|
+
</module>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="GitToolBoxProjectSettings">
|
|
4
|
+
<option name="commitMessageIssueKeyValidationOverride">
|
|
5
|
+
<BoolValueOverride>
|
|
6
|
+
<option name="enabled" value="true" />
|
|
7
|
+
</BoolValueOverride>
|
|
8
|
+
</option>
|
|
9
|
+
<option name="commitMessageValidationEnabledOverride">
|
|
10
|
+
<BoolValueOverride>
|
|
11
|
+
<option name="enabled" value="true" />
|
|
12
|
+
</BoolValueOverride>
|
|
13
|
+
</option>
|
|
14
|
+
</component>
|
|
15
|
+
</project>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ProjectModuleManager">
|
|
4
|
+
<modules>
|
|
5
|
+
<module fileurl="file://$PROJECT_DIR$/.idea/contrail-entity-types.iml" filepath="$PROJECT_DIR$/.idea/contrail-entity-types.iml" />
|
|
6
|
+
</modules>
|
|
7
|
+
</component>
|
|
8
|
+
</project>
|
|
@@ -23,12 +23,21 @@ export declare class ValueToAssortment {
|
|
|
23
23
|
}
|
|
24
24
|
export interface LoaderConfiguration extends OrgManagedEntity {
|
|
25
25
|
name?: string;
|
|
26
|
+
loadType: LoadType[];
|
|
27
|
+
messageGroupId?: string;
|
|
26
28
|
federatedMappings?: any;
|
|
27
29
|
conditionalColumns?: ColumnDefinition[];
|
|
28
30
|
assortmentSplit?: AssortmentSplit;
|
|
29
31
|
workspaceIdentifier?: string;
|
|
30
32
|
propertiesToRemove?: string[];
|
|
31
33
|
skipStaleUpdatesUsing?: string;
|
|
34
|
+
ignoreParameters?: IgnoreParameters;
|
|
35
|
+
loaderConfigurationId?: string;
|
|
36
|
+
shouldSkipAssortmentPublish?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface IgnoreParameters {
|
|
39
|
+
ignoreFamilyNameOnUpdate: boolean;
|
|
40
|
+
ignoreOptionNameOnUpdate: boolean;
|
|
32
41
|
}
|
|
33
42
|
export declare enum LoadStatus {
|
|
34
43
|
ACTIVE = "ACTIVE",
|
|
@@ -122,17 +131,10 @@ export interface ProcessedData {
|
|
|
122
131
|
systemErrors: GeneralIssueDetails[];
|
|
123
132
|
failureArea: LoaderFailureArea;
|
|
124
133
|
}
|
|
125
|
-
export
|
|
134
|
+
export interface LoaderProcess extends LoaderConfiguration {
|
|
126
135
|
id: string;
|
|
127
|
-
createdOn?: Date;
|
|
128
|
-
updatedOn?: Date;
|
|
129
|
-
createdById?: string;
|
|
130
|
-
updatedById?: string;
|
|
131
136
|
createdBy?: any;
|
|
132
137
|
updatedBy?: any;
|
|
133
|
-
orgId?: string;
|
|
134
|
-
loaderConfigurationId?: string;
|
|
135
|
-
name?: string;
|
|
136
138
|
endedOn?: Date;
|
|
137
139
|
status: LoadStatus;
|
|
138
140
|
logLevel?: LogLevel;
|
|
@@ -147,21 +149,13 @@ export declare class LoaderProcess implements OrgManagedEntity {
|
|
|
147
149
|
preprocessingStepResults?: PreprocessingStepStoredResultSummary[];
|
|
148
150
|
processDurationSeconds?: number;
|
|
149
151
|
loadFileId: string;
|
|
150
|
-
loadType: LoadType[];
|
|
151
|
-
federatedMappings?: any;
|
|
152
|
-
conditionalColumns?: ColumnDefinition[];
|
|
153
|
-
assortmentSplit?: AssortmentSplit;
|
|
154
152
|
partialAssortmentUpdate?: boolean;
|
|
155
153
|
assortmentItemDropField?: string;
|
|
156
|
-
workspaceIdentifier?: string;
|
|
157
|
-
propertiesToRemove?: string[];
|
|
158
154
|
badRowsCount?: number;
|
|
159
155
|
uploadErrorCount?: number;
|
|
160
156
|
hasErrors?: boolean;
|
|
161
157
|
parallelWorkerCount?: number;
|
|
162
|
-
messageGroupId?: string;
|
|
163
158
|
isPartialFailure?: boolean;
|
|
164
|
-
skipStaleUpdatesUsing?: string;
|
|
165
159
|
}
|
|
166
160
|
export declare enum IssueType {
|
|
167
161
|
CONFIG = "CONFIG",
|
|
@@ -191,7 +185,11 @@ export declare enum EntityType {
|
|
|
191
185
|
export declare enum PreValidationCategory {
|
|
192
186
|
OPTION_SET = "OPTION_SET",
|
|
193
187
|
FORMAT_BOOLEAN = "FORMAT_BOOLEAN",
|
|
194
|
-
FORMAT_MULTI_SELECT = "FORMAT_MULTI_SELECT"
|
|
188
|
+
FORMAT_MULTI_SELECT = "FORMAT_MULTI_SELECT",
|
|
189
|
+
CONFIG = "CONFIG",
|
|
190
|
+
MISSING_REQUIRED_FIELD = "MISSING_REQUIRED_FIELD",
|
|
191
|
+
REFERENCE_DATA_NOT_FOUND = "REFERENCE_DATA_NOT_FOUND",
|
|
192
|
+
FAMILY_PROPERTY_VALUES_INCONSISTENT = "FAMILY_PROPERTY_VALUES_INCONSISTENT"
|
|
195
193
|
}
|
|
196
194
|
export declare enum PreValidationSeverity {
|
|
197
195
|
ERROR = "error",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SuggestedFixType = exports.PreValidationSeverity = exports.PreValidationCategory = exports.EntityType = exports.LoaderFailureArea = exports.IssueType = exports.
|
|
3
|
+
exports.SuggestedFixType = exports.PreValidationSeverity = exports.PreValidationCategory = exports.EntityType = exports.LoaderFailureArea = exports.IssueType = exports.LoadType = exports.LoadStatus = exports.ValueToAssortment = exports.AssortmentSplit = exports.ConditionalValues = exports.ColumnDefinition = void 0;
|
|
4
4
|
class ColumnDefinition {
|
|
5
5
|
fromProperty;
|
|
6
6
|
toProperty;
|
|
@@ -44,48 +44,6 @@ var LoadType;
|
|
|
44
44
|
LoadType["SIZE_RANGE_TEMPLATE"] = "SIZE_RANGE_TEMPLATE";
|
|
45
45
|
LoadType["PROJECT"] = "PROJECT";
|
|
46
46
|
})(LoadType = exports.LoadType || (exports.LoadType = {}));
|
|
47
|
-
class LoaderProcess {
|
|
48
|
-
id;
|
|
49
|
-
createdOn;
|
|
50
|
-
updatedOn;
|
|
51
|
-
createdById;
|
|
52
|
-
updatedById;
|
|
53
|
-
createdBy;
|
|
54
|
-
updatedBy;
|
|
55
|
-
orgId;
|
|
56
|
-
loaderConfigurationId;
|
|
57
|
-
name;
|
|
58
|
-
endedOn;
|
|
59
|
-
status;
|
|
60
|
-
logLevel;
|
|
61
|
-
processLogs;
|
|
62
|
-
processLogS3File;
|
|
63
|
-
processLogS3FileDownloadLink;
|
|
64
|
-
logsFileId;
|
|
65
|
-
logFileDownloadLink;
|
|
66
|
-
loadProcessResult;
|
|
67
|
-
loadProcessResultFileId;
|
|
68
|
-
loadProcessResultDownloadLink;
|
|
69
|
-
preprocessingStepResults;
|
|
70
|
-
processDurationSeconds;
|
|
71
|
-
loadFileId;
|
|
72
|
-
loadType;
|
|
73
|
-
federatedMappings;
|
|
74
|
-
conditionalColumns;
|
|
75
|
-
assortmentSplit;
|
|
76
|
-
partialAssortmentUpdate;
|
|
77
|
-
assortmentItemDropField;
|
|
78
|
-
workspaceIdentifier;
|
|
79
|
-
propertiesToRemove;
|
|
80
|
-
badRowsCount;
|
|
81
|
-
uploadErrorCount;
|
|
82
|
-
hasErrors;
|
|
83
|
-
parallelWorkerCount;
|
|
84
|
-
messageGroupId;
|
|
85
|
-
isPartialFailure;
|
|
86
|
-
skipStaleUpdatesUsing;
|
|
87
|
-
}
|
|
88
|
-
exports.LoaderProcess = LoaderProcess;
|
|
89
47
|
var IssueType;
|
|
90
48
|
(function (IssueType) {
|
|
91
49
|
IssueType["CONFIG"] = "CONFIG";
|
|
@@ -119,6 +77,10 @@ var PreValidationCategory;
|
|
|
119
77
|
PreValidationCategory["OPTION_SET"] = "OPTION_SET";
|
|
120
78
|
PreValidationCategory["FORMAT_BOOLEAN"] = "FORMAT_BOOLEAN";
|
|
121
79
|
PreValidationCategory["FORMAT_MULTI_SELECT"] = "FORMAT_MULTI_SELECT";
|
|
80
|
+
PreValidationCategory["CONFIG"] = "CONFIG";
|
|
81
|
+
PreValidationCategory["MISSING_REQUIRED_FIELD"] = "MISSING_REQUIRED_FIELD";
|
|
82
|
+
PreValidationCategory["REFERENCE_DATA_NOT_FOUND"] = "REFERENCE_DATA_NOT_FOUND";
|
|
83
|
+
PreValidationCategory["FAMILY_PROPERTY_VALUES_INCONSISTENT"] = "FAMILY_PROPERTY_VALUES_INCONSISTENT";
|
|
122
84
|
})(PreValidationCategory = exports.PreValidationCategory || (exports.PreValidationCategory = {}));
|
|
123
85
|
var PreValidationSeverity;
|
|
124
86
|
(function (PreValidationSeverity) {
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.4.
|
|
2
|
+
"version": "3.4.5-alpha.18160f5",
|
|
3
3
|
"commands": {
|
|
4
4
|
"app:create": {
|
|
5
5
|
"id": "app:create",
|
|
@@ -1155,6 +1155,91 @@
|
|
|
1155
1155
|
}
|
|
1156
1156
|
}
|
|
1157
1157
|
},
|
|
1158
|
+
"load-local": {
|
|
1159
|
+
"id": "load-local",
|
|
1160
|
+
"description": "Run the full data loading pipeline locally. Reads a CSV data file and a YAML/JSON config, then runs preprocess → analyze → validate → preview → execute stages with detailed feedback.",
|
|
1161
|
+
"strict": true,
|
|
1162
|
+
"pluginName": "@contrail/cli",
|
|
1163
|
+
"pluginAlias": "@contrail/cli",
|
|
1164
|
+
"pluginType": "core",
|
|
1165
|
+
"hidden": true,
|
|
1166
|
+
"aliases": [],
|
|
1167
|
+
"examples": [
|
|
1168
|
+
"$ contrail load-local data.csv config.yml",
|
|
1169
|
+
"$ contrail load-local data.csv config.yml --dry-run",
|
|
1170
|
+
"$ contrail load-local data.csv config.yml --yes",
|
|
1171
|
+
"$ contrail load-local data.csv config.yml --stage 3"
|
|
1172
|
+
],
|
|
1173
|
+
"flags": {
|
|
1174
|
+
"logLevel": {
|
|
1175
|
+
"name": "logLevel",
|
|
1176
|
+
"type": "option",
|
|
1177
|
+
"char": "l",
|
|
1178
|
+
"description": "The Log Level",
|
|
1179
|
+
"required": false,
|
|
1180
|
+
"multiple": false,
|
|
1181
|
+
"options": [
|
|
1182
|
+
"error",
|
|
1183
|
+
"warn",
|
|
1184
|
+
"info",
|
|
1185
|
+
"debug"
|
|
1186
|
+
]
|
|
1187
|
+
},
|
|
1188
|
+
"alwaysConfirmEnv": {
|
|
1189
|
+
"name": "alwaysConfirmEnv",
|
|
1190
|
+
"type": "option",
|
|
1191
|
+
"char": "e",
|
|
1192
|
+
"description": "The Environment variables",
|
|
1193
|
+
"required": false,
|
|
1194
|
+
"multiple": false,
|
|
1195
|
+
"options": [
|
|
1196
|
+
"true",
|
|
1197
|
+
"false"
|
|
1198
|
+
],
|
|
1199
|
+
"default": "true"
|
|
1200
|
+
},
|
|
1201
|
+
"yes": {
|
|
1202
|
+
"name": "yes",
|
|
1203
|
+
"type": "boolean",
|
|
1204
|
+
"char": "y",
|
|
1205
|
+
"description": "Skip confirmation prompt before executing",
|
|
1206
|
+
"allowNo": false
|
|
1207
|
+
},
|
|
1208
|
+
"dry-run": {
|
|
1209
|
+
"name": "dry-run",
|
|
1210
|
+
"type": "boolean",
|
|
1211
|
+
"char": "d",
|
|
1212
|
+
"description": "Run stages 1-4 only (no execution)",
|
|
1213
|
+
"allowNo": false
|
|
1214
|
+
},
|
|
1215
|
+
"stage": {
|
|
1216
|
+
"name": "stage",
|
|
1217
|
+
"type": "option",
|
|
1218
|
+
"char": "s",
|
|
1219
|
+
"description": "Run only up to this stage (1-5)",
|
|
1220
|
+
"multiple": false,
|
|
1221
|
+
"options": [
|
|
1222
|
+
"1",
|
|
1223
|
+
"2",
|
|
1224
|
+
"3",
|
|
1225
|
+
"4",
|
|
1226
|
+
"5"
|
|
1227
|
+
]
|
|
1228
|
+
}
|
|
1229
|
+
},
|
|
1230
|
+
"args": {
|
|
1231
|
+
"dataFile": {
|
|
1232
|
+
"name": "dataFile",
|
|
1233
|
+
"description": "Path to the CSV data file",
|
|
1234
|
+
"required": true
|
|
1235
|
+
},
|
|
1236
|
+
"configFile": {
|
|
1237
|
+
"name": "configFile",
|
|
1238
|
+
"description": "Path to the YAML or JSON configuration file",
|
|
1239
|
+
"required": true
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1158
1243
|
"projects:export": {
|
|
1159
1244
|
"id": "projects:export",
|
|
1160
1245
|
"description": "Export a project.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrail/cli",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.5-alpha.18160f5",
|
|
4
4
|
"description": "VibeIQ's Contrail Platform CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"contrail-cli": "./bin/run",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@contrail/util"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@contrail/entity-types": "^1.6.
|
|
33
|
+
"@contrail/entity-types": "^1.6.1",
|
|
34
34
|
"@contrail/loader": "1.0.32",
|
|
35
35
|
"@contrail/org-config-migration": "^1.1.13",
|
|
36
36
|
"@contrail/sdk": "^1.5.5",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"aws-sdk": "^2.1044.0",
|
|
46
46
|
"axios": "^1.3.5",
|
|
47
47
|
"chalk": "^4.0.0",
|
|
48
|
+
"cli-table3": "^0.6.5",
|
|
48
49
|
"command-line-usage": "^6.1.1",
|
|
49
50
|
"csv-parse": "^5.5.5",
|
|
50
51
|
"csvtojson": "^2.0.10",
|
|
@@ -99,6 +100,10 @@
|
|
|
99
100
|
"load": {
|
|
100
101
|
"description": "Load data to VibeIQ from local CSV files"
|
|
101
102
|
},
|
|
103
|
+
"load-local": {
|
|
104
|
+
"description": "Run the full data loading pipeline locally with staged feedback",
|
|
105
|
+
"hidden": true
|
|
106
|
+
},
|
|
102
107
|
"types": {
|
|
103
108
|
"description": "Export, manage, and import types"
|
|
104
109
|
},
|