@contractual/cli 0.1.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/bin/cli.js +2 -0
- package/dist/commands/breaking.command.d.ts +19 -0
- package/dist/commands/breaking.command.d.ts.map +1 -0
- package/dist/commands/breaking.command.js +138 -0
- package/dist/commands/changeset.command.d.ts +11 -0
- package/dist/commands/changeset.command.d.ts.map +1 -0
- package/dist/commands/changeset.command.js +65 -0
- package/dist/commands/contract.command.d.ts +34 -0
- package/dist/commands/contract.command.d.ts.map +1 -0
- package/dist/commands/contract.command.js +259 -0
- package/dist/commands/diff.command.d.ts +21 -0
- package/dist/commands/diff.command.d.ts.map +1 -0
- package/dist/commands/diff.command.js +58 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +6 -0
- package/dist/commands/init.command.d.ts +21 -0
- package/dist/commands/init.command.d.ts.map +1 -0
- package/dist/commands/init.command.js +294 -0
- package/dist/commands/lint.command.d.ts +16 -0
- package/dist/commands/lint.command.d.ts.map +1 -0
- package/dist/commands/lint.command.js +174 -0
- package/dist/commands/pre.command.d.ts +14 -0
- package/dist/commands/pre.command.d.ts.map +1 -0
- package/dist/commands/pre.command.js +141 -0
- package/dist/commands/status.command.d.ts +5 -0
- package/dist/commands/status.command.d.ts.map +1 -0
- package/dist/commands/status.command.js +120 -0
- package/dist/commands/version.command.d.ts +16 -0
- package/dist/commands/version.command.d.ts.map +1 -0
- package/dist/commands/version.command.js +247 -0
- package/dist/commands.d.ts +2 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +84 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/loader.d.ts +28 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +123 -0
- package/dist/config/schema.json +121 -0
- package/dist/config/validator.d.ts +28 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +34 -0
- package/dist/core/diff.d.ts +26 -0
- package/dist/core/diff.d.ts.map +1 -0
- package/dist/core/diff.js +89 -0
- package/dist/formatters/diff.d.ts +31 -0
- package/dist/formatters/diff.d.ts.map +1 -0
- package/dist/formatters/diff.js +139 -0
- package/dist/governance/index.d.ts +11 -0
- package/dist/governance/index.d.ts.map +1 -0
- package/dist/governance/index.js +14 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/utils/exec.d.ts +29 -0
- package/dist/utils/exec.d.ts.map +1 -0
- package/dist/utils/exec.js +66 -0
- package/dist/utils/files.d.ts +36 -0
- package/dist/utils/files.d.ts.map +1 -0
- package/dist/utils/files.js +137 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/output.d.ts +25 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/output.js +73 -0
- package/dist/utils/prompts.d.ts +90 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +119 -0
- package/package.json +81 -0
- package/src/config/schema.json +121 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ContractType } from '@contractual/types';
|
|
2
|
+
import { CHANGESETS_DIR, SNAPSHOTS_DIR, VERSIONS_FILE } from '@contractual/changesets';
|
|
3
|
+
/**
|
|
4
|
+
* The .contractual directory name
|
|
5
|
+
*/
|
|
6
|
+
export declare const CONTRACTUAL_DIR = ".contractual";
|
|
7
|
+
export { CHANGESETS_DIR, SNAPSHOTS_DIR, VERSIONS_FILE };
|
|
8
|
+
/**
|
|
9
|
+
* Find the .contractual directory starting from a given path
|
|
10
|
+
*/
|
|
11
|
+
export declare function findContractualDir(startDir?: string): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Ensure the .contractual directory structure exists
|
|
14
|
+
*/
|
|
15
|
+
export declare function ensureContractualDir(baseDir: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Read and parse a spec file (YAML or JSON)
|
|
18
|
+
*/
|
|
19
|
+
export declare function readSpecFile(filePath: string): unknown;
|
|
20
|
+
/**
|
|
21
|
+
* Detect spec type from file path and content
|
|
22
|
+
*/
|
|
23
|
+
export declare function detectSpecType(filePath: string): ContractType | null;
|
|
24
|
+
/**
|
|
25
|
+
* Get the file extension for a contract type
|
|
26
|
+
*/
|
|
27
|
+
export declare function getSpecExtension(filePath: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Copy a spec file to the snapshots directory
|
|
30
|
+
*/
|
|
31
|
+
export declare function copyToSnapshots(specPath: string, contractName: string, contractualDir: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Get the snapshot path for a contract
|
|
34
|
+
*/
|
|
35
|
+
export declare function getSnapshotPath(contractName: string, contractualDir: string): string | null;
|
|
36
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAEvF;;GAEG;AACH,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;AAExD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAqBlF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAyB5D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUtD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAgCpE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,GACrB,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY3F"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, extname, join, resolve } from 'node:path';
|
|
3
|
+
import { parse as parseYaml } from 'yaml';
|
|
4
|
+
import { CHANGESETS_DIR, SNAPSHOTS_DIR, VERSIONS_FILE } from '@contractual/changesets';
|
|
5
|
+
/**
|
|
6
|
+
* The .contractual directory name
|
|
7
|
+
*/
|
|
8
|
+
export const CONTRACTUAL_DIR = '.contractual';
|
|
9
|
+
// Re-export constants from @contractual/changesets for backward compatibility
|
|
10
|
+
export { CHANGESETS_DIR, SNAPSHOTS_DIR, VERSIONS_FILE };
|
|
11
|
+
/**
|
|
12
|
+
* Find the .contractual directory starting from a given path
|
|
13
|
+
*/
|
|
14
|
+
export function findContractualDir(startDir = process.cwd()) {
|
|
15
|
+
let currentDir = resolve(startDir);
|
|
16
|
+
const root = dirname(currentDir);
|
|
17
|
+
while (currentDir !== root) {
|
|
18
|
+
const contractualDir = join(currentDir, CONTRACTUAL_DIR);
|
|
19
|
+
if (existsSync(contractualDir)) {
|
|
20
|
+
return contractualDir;
|
|
21
|
+
}
|
|
22
|
+
const parentDir = dirname(currentDir);
|
|
23
|
+
if (parentDir === currentDir)
|
|
24
|
+
break;
|
|
25
|
+
currentDir = parentDir;
|
|
26
|
+
}
|
|
27
|
+
// Check root directory too
|
|
28
|
+
const contractualDir = join(currentDir, CONTRACTUAL_DIR);
|
|
29
|
+
if (existsSync(contractualDir)) {
|
|
30
|
+
return contractualDir;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Ensure the .contractual directory structure exists
|
|
36
|
+
*/
|
|
37
|
+
export function ensureContractualDir(baseDir) {
|
|
38
|
+
const contractualDir = join(baseDir, CONTRACTUAL_DIR);
|
|
39
|
+
const changesetsDir = join(contractualDir, CHANGESETS_DIR);
|
|
40
|
+
const snapshotsDir = join(contractualDir, SNAPSHOTS_DIR);
|
|
41
|
+
mkdirSync(changesetsDir, { recursive: true });
|
|
42
|
+
mkdirSync(snapshotsDir, { recursive: true });
|
|
43
|
+
// Create versions.json if it doesn't exist
|
|
44
|
+
const versionsPath = join(contractualDir, VERSIONS_FILE);
|
|
45
|
+
if (!existsSync(versionsPath)) {
|
|
46
|
+
writeFileSync(versionsPath, '{}', 'utf-8');
|
|
47
|
+
}
|
|
48
|
+
// Create .gitkeep files
|
|
49
|
+
const changesetsGitkeep = join(changesetsDir, '.gitkeep');
|
|
50
|
+
const snapshotsGitkeep = join(snapshotsDir, '.gitkeep');
|
|
51
|
+
if (!existsSync(changesetsGitkeep)) {
|
|
52
|
+
writeFileSync(changesetsGitkeep, '', 'utf-8');
|
|
53
|
+
}
|
|
54
|
+
if (!existsSync(snapshotsGitkeep)) {
|
|
55
|
+
writeFileSync(snapshotsGitkeep, '', 'utf-8');
|
|
56
|
+
}
|
|
57
|
+
return contractualDir;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Read and parse a spec file (YAML or JSON)
|
|
61
|
+
*/
|
|
62
|
+
export function readSpecFile(filePath) {
|
|
63
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
64
|
+
const ext = extname(filePath).toLowerCase();
|
|
65
|
+
if (ext === '.json') {
|
|
66
|
+
return JSON.parse(content);
|
|
67
|
+
}
|
|
68
|
+
// YAML (handles .yaml, .yml)
|
|
69
|
+
return parseYaml(content);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Detect spec type from file path and content
|
|
73
|
+
*/
|
|
74
|
+
export function detectSpecType(filePath) {
|
|
75
|
+
// Check extension patterns first
|
|
76
|
+
if (/\.openapi\.(ya?ml|json)$/i.test(filePath))
|
|
77
|
+
return 'openapi';
|
|
78
|
+
if (/\.asyncapi\.(ya?ml|json)$/i.test(filePath))
|
|
79
|
+
return 'asyncapi';
|
|
80
|
+
if (/\.odcs\.ya?ml$/i.test(filePath))
|
|
81
|
+
return 'odcs';
|
|
82
|
+
if (/\.schema\.json$/i.test(filePath))
|
|
83
|
+
return 'json-schema';
|
|
84
|
+
// Content sniffing
|
|
85
|
+
try {
|
|
86
|
+
const spec = readSpecFile(filePath);
|
|
87
|
+
if (!spec || typeof spec !== 'object')
|
|
88
|
+
return null;
|
|
89
|
+
// OpenAPI detection
|
|
90
|
+
if ('openapi' in spec || 'swagger' in spec)
|
|
91
|
+
return 'openapi';
|
|
92
|
+
// AsyncAPI detection
|
|
93
|
+
if ('asyncapi' in spec)
|
|
94
|
+
return 'asyncapi';
|
|
95
|
+
// ODCS detection
|
|
96
|
+
if ('dataContractSpecification' in spec || spec.kind === 'DataContract')
|
|
97
|
+
return 'odcs';
|
|
98
|
+
// JSON Schema detection
|
|
99
|
+
if (('$schema' in spec && String(spec.$schema).includes('json-schema')) ||
|
|
100
|
+
('type' in spec && 'properties' in spec))
|
|
101
|
+
return 'json-schema';
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get the file extension for a contract type
|
|
110
|
+
*/
|
|
111
|
+
export function getSpecExtension(filePath) {
|
|
112
|
+
const ext = extname(filePath).toLowerCase();
|
|
113
|
+
return ext || '.yaml';
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Copy a spec file to the snapshots directory
|
|
117
|
+
*/
|
|
118
|
+
export function copyToSnapshots(specPath, contractName, contractualDir) {
|
|
119
|
+
const ext = getSpecExtension(specPath);
|
|
120
|
+
const snapshotPath = join(contractualDir, SNAPSHOTS_DIR, `${contractName}${ext}`);
|
|
121
|
+
copyFileSync(specPath, snapshotPath);
|
|
122
|
+
return snapshotPath;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get the snapshot path for a contract
|
|
126
|
+
*/
|
|
127
|
+
export function getSnapshotPath(contractName, contractualDir) {
|
|
128
|
+
const snapshotsDir = join(contractualDir, SNAPSHOTS_DIR);
|
|
129
|
+
const extensions = ['.yaml', '.yml', '.json'];
|
|
130
|
+
for (const ext of extensions) {
|
|
131
|
+
const snapshotPath = join(snapshotsDir, `${contractName}${ext}`);
|
|
132
|
+
if (existsSync(snapshotPath)) {
|
|
133
|
+
return snapshotPath;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Print a success message with green checkmark
|
|
3
|
+
*/
|
|
4
|
+
export declare function printSuccess(message: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Print an error message with red X
|
|
7
|
+
*/
|
|
8
|
+
export declare function printError(message: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Print a warning message with yellow warning symbol
|
|
11
|
+
*/
|
|
12
|
+
export declare function printWarning(message: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Print an info message with blue info symbol
|
|
15
|
+
*/
|
|
16
|
+
export declare function printInfo(message: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Print a simple ASCII table
|
|
19
|
+
*/
|
|
20
|
+
export declare function printTable(headers: string[], rows: string[][]): void;
|
|
21
|
+
/**
|
|
22
|
+
* Format severity level with appropriate color
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatSeverity(severity: 'breaking' | 'non-breaking' | 'patch' | 'unknown'): string;
|
|
25
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,CAkCpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,UAAU,GAAG,cAAc,GAAG,OAAO,GAAG,SAAS,GAC1D,MAAM,CAYR"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
/**
|
|
3
|
+
* Print a success message with green checkmark
|
|
4
|
+
*/
|
|
5
|
+
export function printSuccess(message) {
|
|
6
|
+
console.log(chalk.green('✓') + ' ' + message);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Print an error message with red X
|
|
10
|
+
*/
|
|
11
|
+
export function printError(message) {
|
|
12
|
+
console.log(chalk.red('✗') + ' ' + message);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Print a warning message with yellow warning symbol
|
|
16
|
+
*/
|
|
17
|
+
export function printWarning(message) {
|
|
18
|
+
console.log(chalk.yellow('⚠') + ' ' + message);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Print an info message with blue info symbol
|
|
22
|
+
*/
|
|
23
|
+
export function printInfo(message) {
|
|
24
|
+
console.log(chalk.blue('ℹ') + ' ' + message);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Print a simple ASCII table
|
|
28
|
+
*/
|
|
29
|
+
export function printTable(headers, rows) {
|
|
30
|
+
if (headers.length === 0) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Calculate column widths
|
|
34
|
+
const columnWidths = headers.map((header, index) => {
|
|
35
|
+
const maxRowWidth = rows.reduce((max, row) => {
|
|
36
|
+
const cellLength = row[index]?.length ?? 0;
|
|
37
|
+
return Math.max(max, cellLength);
|
|
38
|
+
}, 0);
|
|
39
|
+
return Math.max(header.length, maxRowWidth);
|
|
40
|
+
});
|
|
41
|
+
// Create separator line
|
|
42
|
+
const separator = '+' + columnWidths.map((width) => '-'.repeat(width + 2)).join('+') + '+';
|
|
43
|
+
// Format a row
|
|
44
|
+
const formatRow = (cells) => {
|
|
45
|
+
return ('|' +
|
|
46
|
+
cells.map((cell, index) => ' ' + (cell ?? '').padEnd(columnWidths[index]) + ' ').join('|') +
|
|
47
|
+
'|');
|
|
48
|
+
};
|
|
49
|
+
// Print table
|
|
50
|
+
console.log(separator);
|
|
51
|
+
console.log(formatRow(headers));
|
|
52
|
+
console.log(separator);
|
|
53
|
+
for (const row of rows) {
|
|
54
|
+
console.log(formatRow(row));
|
|
55
|
+
}
|
|
56
|
+
console.log(separator);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Format severity level with appropriate color
|
|
60
|
+
*/
|
|
61
|
+
export function formatSeverity(severity) {
|
|
62
|
+
switch (severity) {
|
|
63
|
+
case 'breaking':
|
|
64
|
+
return chalk.red.bold('BREAKING');
|
|
65
|
+
case 'non-breaking':
|
|
66
|
+
return chalk.yellow('NON-BREAKING');
|
|
67
|
+
case 'patch':
|
|
68
|
+
return chalk.green('PATCH');
|
|
69
|
+
case 'unknown':
|
|
70
|
+
default:
|
|
71
|
+
return chalk.gray('UNKNOWN');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if running in interactive mode (TTY available)
|
|
3
|
+
*/
|
|
4
|
+
export declare function isInteractive(): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Check if running in CI environment
|
|
7
|
+
*/
|
|
8
|
+
export declare function isCI(): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Options for prompt functions
|
|
11
|
+
*/
|
|
12
|
+
export interface PromptOptions {
|
|
13
|
+
/** Skip prompts and use defaults (--yes flag) */
|
|
14
|
+
yes?: boolean;
|
|
15
|
+
/** Force interactive mode even in CI */
|
|
16
|
+
interactive?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Determine if prompts should be shown
|
|
20
|
+
*/
|
|
21
|
+
export declare function shouldPrompt(options: PromptOptions): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Prompt for a selection from a list of choices
|
|
24
|
+
*/
|
|
25
|
+
export declare function promptSelect<T extends string>(message: string, choices: Array<{
|
|
26
|
+
value: T;
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
}>, defaultValue: T, options?: PromptOptions): Promise<T>;
|
|
30
|
+
/**
|
|
31
|
+
* Prompt for text input
|
|
32
|
+
*/
|
|
33
|
+
export declare function promptInput(message: string, defaultValue: string, options?: PromptOptions): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Prompt for confirmation (yes/no)
|
|
36
|
+
*/
|
|
37
|
+
export declare function promptConfirm(message: string, defaultValue: boolean, options?: PromptOptions): Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Prompt for version input with validation
|
|
40
|
+
*/
|
|
41
|
+
export declare function promptVersion(message: string, defaultValue: string, options?: PromptOptions): Promise<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Common version choices for init
|
|
44
|
+
*/
|
|
45
|
+
export declare const VERSION_CHOICES: readonly [{
|
|
46
|
+
readonly value: "0.0.0";
|
|
47
|
+
readonly name: "0.0.0";
|
|
48
|
+
readonly description: "Start fresh (recommended for new projects)";
|
|
49
|
+
}, {
|
|
50
|
+
readonly value: "1.0.0";
|
|
51
|
+
readonly name: "1.0.0";
|
|
52
|
+
readonly description: "Production-ready";
|
|
53
|
+
}, {
|
|
54
|
+
readonly value: "custom";
|
|
55
|
+
readonly name: "Custom";
|
|
56
|
+
readonly description: "Enter a custom version";
|
|
57
|
+
}];
|
|
58
|
+
/**
|
|
59
|
+
* Common versioning mode choices
|
|
60
|
+
*/
|
|
61
|
+
export declare const VERSIONING_MODE_CHOICES: readonly [{
|
|
62
|
+
readonly value: "independent";
|
|
63
|
+
readonly name: "Independent";
|
|
64
|
+
readonly description: "Each contract versioned separately";
|
|
65
|
+
}, {
|
|
66
|
+
readonly value: "fixed";
|
|
67
|
+
readonly name: "Fixed";
|
|
68
|
+
readonly description: "All contracts share same version";
|
|
69
|
+
}];
|
|
70
|
+
/**
|
|
71
|
+
* Contract type choices
|
|
72
|
+
*/
|
|
73
|
+
export declare const CONTRACT_TYPE_CHOICES: readonly [{
|
|
74
|
+
readonly value: "openapi";
|
|
75
|
+
readonly name: "OpenAPI";
|
|
76
|
+
readonly description: "OpenAPI/Swagger specification";
|
|
77
|
+
}, {
|
|
78
|
+
readonly value: "asyncapi";
|
|
79
|
+
readonly name: "AsyncAPI";
|
|
80
|
+
readonly description: "AsyncAPI specification";
|
|
81
|
+
}, {
|
|
82
|
+
readonly value: "json-schema";
|
|
83
|
+
readonly name: "JSON Schema";
|
|
84
|
+
readonly description: "JSON Schema definition";
|
|
85
|
+
}, {
|
|
86
|
+
readonly value: "odcs";
|
|
87
|
+
readonly name: "ODCS";
|
|
88
|
+
readonly description: "Open Data Contract Standard";
|
|
89
|
+
}];
|
|
90
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;GAEG;AACH,wBAAgB,IAAI,IAAI,OAAO,CAS9B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,wCAAwC;IACxC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAK5D;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EACjD,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAChE,YAAY,EAAE,CAAC,EACf,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,CAAC,CAAC,CAcZ;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CASjB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,OAAO,EACrB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,OAAO,CAAC,CASlB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;EAIlB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;EAO1B,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;EAKxB,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { select, input, confirm } from '@inquirer/prompts';
|
|
2
|
+
/**
|
|
3
|
+
* Check if running in interactive mode (TTY available)
|
|
4
|
+
*/
|
|
5
|
+
export function isInteractive() {
|
|
6
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Check if running in CI environment
|
|
10
|
+
*/
|
|
11
|
+
export function isCI() {
|
|
12
|
+
return (process.env.CI === 'true' ||
|
|
13
|
+
process.env.CI === '1' ||
|
|
14
|
+
process.env.CONTINUOUS_INTEGRATION === 'true' ||
|
|
15
|
+
process.env.GITHUB_ACTIONS === 'true' ||
|
|
16
|
+
process.env.GITLAB_CI === 'true' ||
|
|
17
|
+
process.env.CIRCLECI === 'true');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Determine if prompts should be shown
|
|
21
|
+
*/
|
|
22
|
+
export function shouldPrompt(options) {
|
|
23
|
+
if (options.yes)
|
|
24
|
+
return false;
|
|
25
|
+
if (options.interactive)
|
|
26
|
+
return true;
|
|
27
|
+
if (isCI())
|
|
28
|
+
return false;
|
|
29
|
+
return isInteractive();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Prompt for a selection from a list of choices
|
|
33
|
+
*/
|
|
34
|
+
export async function promptSelect(message, choices, defaultValue, options = {}) {
|
|
35
|
+
if (!shouldPrompt(options)) {
|
|
36
|
+
return defaultValue;
|
|
37
|
+
}
|
|
38
|
+
return select({
|
|
39
|
+
message,
|
|
40
|
+
choices: choices.map((c) => ({
|
|
41
|
+
value: c.value,
|
|
42
|
+
name: c.name,
|
|
43
|
+
description: c.description,
|
|
44
|
+
})),
|
|
45
|
+
default: defaultValue,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Prompt for text input
|
|
50
|
+
*/
|
|
51
|
+
export async function promptInput(message, defaultValue, options = {}) {
|
|
52
|
+
if (!shouldPrompt(options)) {
|
|
53
|
+
return defaultValue;
|
|
54
|
+
}
|
|
55
|
+
return input({
|
|
56
|
+
message,
|
|
57
|
+
default: defaultValue,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Prompt for confirmation (yes/no)
|
|
62
|
+
*/
|
|
63
|
+
export async function promptConfirm(message, defaultValue, options = {}) {
|
|
64
|
+
if (!shouldPrompt(options)) {
|
|
65
|
+
return defaultValue;
|
|
66
|
+
}
|
|
67
|
+
return confirm({
|
|
68
|
+
message,
|
|
69
|
+
default: defaultValue,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Prompt for version input with validation
|
|
74
|
+
*/
|
|
75
|
+
export async function promptVersion(message, defaultValue, options = {}) {
|
|
76
|
+
if (!shouldPrompt(options)) {
|
|
77
|
+
return defaultValue;
|
|
78
|
+
}
|
|
79
|
+
const result = await input({
|
|
80
|
+
message,
|
|
81
|
+
default: defaultValue,
|
|
82
|
+
validate: (value) => {
|
|
83
|
+
const semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
|
|
84
|
+
if (semverRegex.test(value)) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
return 'Please enter a valid semver version (e.g., 0.0.0, 1.2.3-beta.1)';
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Common version choices for init
|
|
94
|
+
*/
|
|
95
|
+
export const VERSION_CHOICES = [
|
|
96
|
+
{ value: '0.0.0', name: '0.0.0', description: 'Start fresh (recommended for new projects)' },
|
|
97
|
+
{ value: '1.0.0', name: '1.0.0', description: 'Production-ready' },
|
|
98
|
+
{ value: 'custom', name: 'Custom', description: 'Enter a custom version' },
|
|
99
|
+
];
|
|
100
|
+
/**
|
|
101
|
+
* Common versioning mode choices
|
|
102
|
+
*/
|
|
103
|
+
export const VERSIONING_MODE_CHOICES = [
|
|
104
|
+
{
|
|
105
|
+
value: 'independent',
|
|
106
|
+
name: 'Independent',
|
|
107
|
+
description: 'Each contract versioned separately',
|
|
108
|
+
},
|
|
109
|
+
{ value: 'fixed', name: 'Fixed', description: 'All contracts share same version' },
|
|
110
|
+
];
|
|
111
|
+
/**
|
|
112
|
+
* Contract type choices
|
|
113
|
+
*/
|
|
114
|
+
export const CONTRACT_TYPE_CHOICES = [
|
|
115
|
+
{ value: 'openapi', name: 'OpenAPI', description: 'OpenAPI/Swagger specification' },
|
|
116
|
+
{ value: 'asyncapi', name: 'AsyncAPI', description: 'AsyncAPI specification' },
|
|
117
|
+
{ value: 'json-schema', name: 'JSON Schema', description: 'JSON Schema definition' },
|
|
118
|
+
{ value: 'odcs', name: 'ODCS', description: 'Open Data Contract Standard' },
|
|
119
|
+
];
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@contractual/cli",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.1.0-dev.0",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"contractual": "./bin/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/contractual-dev/contractual.git",
|
|
21
|
+
"directory": "packages/cli"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://contractual.dev",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/contractual-dev/contractual/issues"
|
|
26
|
+
},
|
|
27
|
+
"contributors": [
|
|
28
|
+
{
|
|
29
|
+
"name": "Omer Morad",
|
|
30
|
+
"email": "omer.moradd@gmail.com"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"funding": [
|
|
34
|
+
{
|
|
35
|
+
"type": "github",
|
|
36
|
+
"url": "https://github.com/sponsors/contractual-dev"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"type": "opencollective",
|
|
40
|
+
"url": "https://opencollective.com/contractual-dev"
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=20.0.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"prebuild": "pnpm rimraf dist",
|
|
48
|
+
"build": "tsc -p tsconfig.build.json",
|
|
49
|
+
"build:watch": "tsc -p tsconfig.build.json --watch",
|
|
50
|
+
"tester": "jest --coverage --verbose",
|
|
51
|
+
"lint": "eslint '{src,test}/**/*.ts'"
|
|
52
|
+
},
|
|
53
|
+
"files": [
|
|
54
|
+
"bin",
|
|
55
|
+
"dist",
|
|
56
|
+
"src/config/schema.json",
|
|
57
|
+
"README.md"
|
|
58
|
+
],
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@contractual/changesets": "0.1.0-dev.0",
|
|
61
|
+
"@contractual/governance": "0.1.0-dev.0",
|
|
62
|
+
"@contractual/types": "0.1.0-dev.0",
|
|
63
|
+
"@inquirer/prompts": "^8.1.0",
|
|
64
|
+
"ajv": "^8.17.1",
|
|
65
|
+
"ajv-formats": "^3.0.1",
|
|
66
|
+
"chalk": "^5.4.1",
|
|
67
|
+
"commander": "^12.1.0",
|
|
68
|
+
"fast-glob": "^3.3.3",
|
|
69
|
+
"ora": "^8.1.1",
|
|
70
|
+
"yaml": "^2.7.0"
|
|
71
|
+
},
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"access": "public",
|
|
74
|
+
"provenance": true
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@vitest/coverage-v8": "^3.0.0",
|
|
78
|
+
"vitest": "^3.0.3"
|
|
79
|
+
},
|
|
80
|
+
"gitHead": "a18dcec2397cf45cbd4ba86461d378ccd71ba657"
|
|
81
|
+
}
|