@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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/bin/cli.js +2 -0
  3. package/dist/commands/breaking.command.d.ts +19 -0
  4. package/dist/commands/breaking.command.d.ts.map +1 -0
  5. package/dist/commands/breaking.command.js +138 -0
  6. package/dist/commands/changeset.command.d.ts +11 -0
  7. package/dist/commands/changeset.command.d.ts.map +1 -0
  8. package/dist/commands/changeset.command.js +65 -0
  9. package/dist/commands/contract.command.d.ts +34 -0
  10. package/dist/commands/contract.command.d.ts.map +1 -0
  11. package/dist/commands/contract.command.js +259 -0
  12. package/dist/commands/diff.command.d.ts +21 -0
  13. package/dist/commands/diff.command.d.ts.map +1 -0
  14. package/dist/commands/diff.command.js +58 -0
  15. package/dist/commands/index.d.ts +7 -0
  16. package/dist/commands/index.d.ts.map +1 -0
  17. package/dist/commands/index.js +6 -0
  18. package/dist/commands/init.command.d.ts +21 -0
  19. package/dist/commands/init.command.d.ts.map +1 -0
  20. package/dist/commands/init.command.js +294 -0
  21. package/dist/commands/lint.command.d.ts +16 -0
  22. package/dist/commands/lint.command.d.ts.map +1 -0
  23. package/dist/commands/lint.command.js +174 -0
  24. package/dist/commands/pre.command.d.ts +14 -0
  25. package/dist/commands/pre.command.d.ts.map +1 -0
  26. package/dist/commands/pre.command.js +141 -0
  27. package/dist/commands/status.command.d.ts +5 -0
  28. package/dist/commands/status.command.d.ts.map +1 -0
  29. package/dist/commands/status.command.js +120 -0
  30. package/dist/commands/version.command.d.ts +16 -0
  31. package/dist/commands/version.command.d.ts.map +1 -0
  32. package/dist/commands/version.command.js +247 -0
  33. package/dist/commands.d.ts +2 -0
  34. package/dist/commands.d.ts.map +1 -0
  35. package/dist/commands.js +84 -0
  36. package/dist/config/index.d.ts +3 -0
  37. package/dist/config/index.d.ts.map +1 -0
  38. package/dist/config/index.js +2 -0
  39. package/dist/config/loader.d.ts +28 -0
  40. package/dist/config/loader.d.ts.map +1 -0
  41. package/dist/config/loader.js +123 -0
  42. package/dist/config/schema.json +121 -0
  43. package/dist/config/validator.d.ts +28 -0
  44. package/dist/config/validator.d.ts.map +1 -0
  45. package/dist/config/validator.js +34 -0
  46. package/dist/core/diff.d.ts +26 -0
  47. package/dist/core/diff.d.ts.map +1 -0
  48. package/dist/core/diff.js +89 -0
  49. package/dist/formatters/diff.d.ts +31 -0
  50. package/dist/formatters/diff.d.ts.map +1 -0
  51. package/dist/formatters/diff.js +139 -0
  52. package/dist/governance/index.d.ts +11 -0
  53. package/dist/governance/index.d.ts.map +1 -0
  54. package/dist/governance/index.js +14 -0
  55. package/dist/index.d.ts +9 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +9 -0
  58. package/dist/utils/exec.d.ts +29 -0
  59. package/dist/utils/exec.d.ts.map +1 -0
  60. package/dist/utils/exec.js +66 -0
  61. package/dist/utils/files.d.ts +36 -0
  62. package/dist/utils/files.d.ts.map +1 -0
  63. package/dist/utils/files.js +137 -0
  64. package/dist/utils/index.d.ts +4 -0
  65. package/dist/utils/index.d.ts.map +1 -0
  66. package/dist/utils/index.js +3 -0
  67. package/dist/utils/output.d.ts +25 -0
  68. package/dist/utils/output.d.ts.map +1 -0
  69. package/dist/utils/output.js +73 -0
  70. package/dist/utils/prompts.d.ts +90 -0
  71. package/dist/utils/prompts.d.ts.map +1 -0
  72. package/dist/utils/prompts.js +119 -0
  73. package/package.json +81 -0
  74. package/src/config/schema.json +121 -0
@@ -0,0 +1,121 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://contractual.dev/schemas/config.json",
4
+ "title": "Contractual Configuration",
5
+ "description": "Configuration file for Contractual schema contract lifecycle orchestrator",
6
+ "type": "object",
7
+ "required": ["contracts"],
8
+ "properties": {
9
+ "contracts": {
10
+ "type": "array",
11
+ "description": "List of contract definitions",
12
+ "minItems": 1,
13
+ "items": {
14
+ "type": "object",
15
+ "required": ["name", "type", "path"],
16
+ "properties": {
17
+ "name": {
18
+ "type": "string",
19
+ "description": "Unique identifier for the contract",
20
+ "pattern": "^[a-z][a-z0-9-]*$"
21
+ },
22
+ "type": {
23
+ "type": "string",
24
+ "description": "Type of schema",
25
+ "enum": ["openapi", "json-schema", "asyncapi", "odcs"]
26
+ },
27
+ "path": {
28
+ "type": "string",
29
+ "description": "Path to spec file (can be glob pattern)"
30
+ },
31
+ "lint": {
32
+ "oneOf": [
33
+ { "type": "string", "description": "Linter tool name or custom command" },
34
+ { "type": "boolean", "const": false, "description": "Disable linting" }
35
+ ]
36
+ },
37
+ "breaking": {
38
+ "oneOf": [
39
+ { "type": "string", "description": "Differ tool name or custom command" },
40
+ { "type": "boolean", "const": false, "description": "Disable breaking change detection" }
41
+ ]
42
+ },
43
+ "generate": {
44
+ "type": "array",
45
+ "description": "Output generation commands",
46
+ "items": { "type": "string" }
47
+ }
48
+ },
49
+ "additionalProperties": false
50
+ }
51
+ },
52
+ "versioning": {
53
+ "type": "object",
54
+ "description": "Versioning configuration",
55
+ "properties": {
56
+ "mode": {
57
+ "type": "string",
58
+ "enum": ["independent", "fixed"],
59
+ "description": "Versioning mode: independent (each contract separate) or fixed (all share same version)",
60
+ "default": "independent"
61
+ }
62
+ },
63
+ "additionalProperties": false
64
+ },
65
+ "changeset": {
66
+ "type": "object",
67
+ "description": "Changeset behavior configuration",
68
+ "properties": {
69
+ "autoDetect": {
70
+ "type": "boolean",
71
+ "description": "Auto-detect change classifications",
72
+ "default": true
73
+ },
74
+ "requireOnPR": {
75
+ "type": "boolean",
76
+ "description": "Require changeset for spec changes in PRs",
77
+ "default": true
78
+ }
79
+ },
80
+ "additionalProperties": false
81
+ },
82
+ "ai": {
83
+ "type": "object",
84
+ "description": "AI/LLM integration configuration",
85
+ "properties": {
86
+ "provider": {
87
+ "type": "string",
88
+ "enum": ["anthropic"],
89
+ "default": "anthropic"
90
+ },
91
+ "model": {
92
+ "type": "string",
93
+ "description": "Model to use"
94
+ },
95
+ "features": {
96
+ "type": "object",
97
+ "properties": {
98
+ "explain": {
99
+ "type": "boolean",
100
+ "description": "PR change explanations",
101
+ "default": true
102
+ },
103
+ "changelog": {
104
+ "type": "boolean",
105
+ "description": "AI-enriched changelog entries",
106
+ "default": true
107
+ },
108
+ "enhance": {
109
+ "type": "boolean",
110
+ "description": "Spec metadata enhancement",
111
+ "default": false
112
+ }
113
+ },
114
+ "additionalProperties": false
115
+ }
116
+ },
117
+ "additionalProperties": false
118
+ }
119
+ },
120
+ "additionalProperties": false
121
+ }
@@ -0,0 +1,28 @@
1
+ import type { ContractualConfig } from '@contractual/types';
2
+ /**
3
+ * Validation error with path and message
4
+ */
5
+ export interface ValidationError {
6
+ path: string;
7
+ message: string;
8
+ }
9
+ /**
10
+ * Result of config validation
11
+ */
12
+ export interface ValidationResult {
13
+ valid: boolean;
14
+ errors: ValidationError[];
15
+ }
16
+ /**
17
+ * Validates a parsed config object against the JSON schema
18
+ */
19
+ export declare function validateConfig(config: unknown): ValidationResult;
20
+ /**
21
+ * Type guard to check if config is valid ContractualConfig
22
+ */
23
+ export declare function isValidConfig(config: unknown): config is ContractualConfig;
24
+ /**
25
+ * Format validation errors for display
26
+ */
27
+ export declare function formatValidationErrors(errors: ValidationError[]): string;
28
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/config/validator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG5D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAiBhE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,iBAAiB,CAE1E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAExE"}
@@ -0,0 +1,34 @@
1
+ import Ajv from 'ajv';
2
+ import addFormats from 'ajv-formats';
3
+ const AjvConstructor = Ajv.default ?? Ajv;
4
+ const addFormatsFunc = addFormats.default ?? addFormats;
5
+ import configSchema from './schema.json' with { type: 'json' };
6
+ /**
7
+ * Validates a parsed config object against the JSON schema
8
+ */
9
+ export function validateConfig(config) {
10
+ const ajv = new AjvConstructor({ allErrors: true, strict: false });
11
+ addFormatsFunc(ajv);
12
+ const validate = ajv.compile(configSchema);
13
+ const valid = validate(config);
14
+ if (valid) {
15
+ return { valid: true, errors: [] };
16
+ }
17
+ const errors = (validate.errors ?? []).map((err) => ({
18
+ path: err.instancePath || '/',
19
+ message: err.message ?? 'Unknown validation error',
20
+ }));
21
+ return { valid: false, errors };
22
+ }
23
+ /**
24
+ * Type guard to check if config is valid ContractualConfig
25
+ */
26
+ export function isValidConfig(config) {
27
+ return validateConfig(config).valid;
28
+ }
29
+ /**
30
+ * Format validation errors for display
31
+ */
32
+ export function formatValidationErrors(errors) {
33
+ return errors.map((err) => ` ${err.path}: ${err.message}`).join('\n');
34
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Core diffing logic
3
+ *
4
+ * Shared module for running diffs across contracts.
5
+ * Used by `diff`, `breaking`, and `changeset` commands.
6
+ */
7
+ import type { ResolvedConfig, DiffResult } from '@contractual/types';
8
+ export interface DiffOptions {
9
+ /** Filter to specific contract names */
10
+ contracts?: string[];
11
+ /** Include contracts with no changes in results */
12
+ includeEmpty?: boolean;
13
+ }
14
+ export interface DiffContractsResult {
15
+ results: DiffResult[];
16
+ contractualDir: string;
17
+ }
18
+ /**
19
+ * Core diffing function. Runs the appropriate differ for each contract,
20
+ * comparing current spec against last versioned snapshot.
21
+ *
22
+ * Returns classified changes for all contracts.
23
+ * This is the primitive that `diff`, `breaking`, and `changeset` all use.
24
+ */
25
+ export declare function diffContracts(config: ResolvedConfig, options?: DiffOptions): Promise<DiffContractsResult>;
26
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAoB,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAIvF,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CA+B9B"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Core diffing logic
3
+ *
4
+ * Shared module for running diffs across contracts.
5
+ * Used by `diff`, `breaking`, and `changeset` commands.
6
+ */
7
+ import { getDiffer } from '../governance/index.js';
8
+ import { findContractualDir, getSnapshotPath } from '../utils/files.js';
9
+ /**
10
+ * Core diffing function. Runs the appropriate differ for each contract,
11
+ * comparing current spec against last versioned snapshot.
12
+ *
13
+ * Returns classified changes for all contracts.
14
+ * This is the primitive that `diff`, `breaking`, and `changeset` all use.
15
+ */
16
+ export async function diffContracts(config, options = {}) {
17
+ const contractualDir = findContractualDir(config.configDir);
18
+ if (!contractualDir) {
19
+ throw new Error('No .contractual directory found. Run `contractual init` first.');
20
+ }
21
+ // Filter contracts if specific ones requested
22
+ let contracts = config.contracts;
23
+ if (options.contracts && options.contracts.length > 0) {
24
+ contracts = config.contracts.filter((c) => options.contracts.includes(c.name));
25
+ // Check for missing contracts
26
+ for (const name of options.contracts) {
27
+ if (!config.contracts.some((c) => c.name === name)) {
28
+ throw new Error(`Contract "${name}" not found in configuration.`);
29
+ }
30
+ }
31
+ }
32
+ const results = [];
33
+ for (const contract of contracts) {
34
+ const result = await diffSingleContract(contract, contractualDir);
35
+ // Include result if it has changes, or if includeEmpty is true
36
+ if (result.changes.length > 0 || options.includeEmpty) {
37
+ results.push(result);
38
+ }
39
+ }
40
+ return { results, contractualDir };
41
+ }
42
+ /**
43
+ * Diff a single contract against its snapshot
44
+ */
45
+ async function diffSingleContract(contract, contractualDir) {
46
+ // Get snapshot path
47
+ const snapshotPath = getSnapshotPath(contract.name, contractualDir);
48
+ // No snapshot = first version, no changes
49
+ if (!snapshotPath) {
50
+ return createEmptyResult(contract.name, 'first-version');
51
+ }
52
+ // Check if breaking detection is disabled
53
+ if (contract.breaking === false) {
54
+ return createEmptyResult(contract.name, 'disabled');
55
+ }
56
+ // Get the differ from the registry
57
+ const differ = getDiffer(contract.type, contract.breaking);
58
+ if (differ === null) {
59
+ // Disabled via config override
60
+ return createEmptyResult(contract.name, 'disabled');
61
+ }
62
+ if (!differ) {
63
+ // No differ registered for this type
64
+ return createEmptyResult(contract.name, 'no-differ');
65
+ }
66
+ // Run the differ: snapshot (old) vs current spec (new)
67
+ const diffResult = await differ(snapshotPath, contract.absolutePath);
68
+ // Override contract name to match config
69
+ return {
70
+ ...diffResult,
71
+ contract: contract.name,
72
+ };
73
+ }
74
+ /**
75
+ * Create an empty diff result
76
+ */
77
+ function createEmptyResult(contractName, _reason) {
78
+ return {
79
+ contract: contractName,
80
+ changes: [],
81
+ summary: {
82
+ breaking: 0,
83
+ nonBreaking: 0,
84
+ patch: 0,
85
+ unknown: 0,
86
+ },
87
+ suggestedBump: 'none',
88
+ };
89
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Diff output formatters
3
+ *
4
+ * Format diff results for text and JSON output.
5
+ */
6
+ import type { DiffResult } from '@contractual/types';
7
+ export interface FormatOptions {
8
+ /** Show JSON Pointer paths for each change */
9
+ verbose?: boolean;
10
+ }
11
+ /**
12
+ * Format diff results as human-readable text
13
+ */
14
+ export declare function formatDiffText(results: DiffResult[], options?: FormatOptions): void;
15
+ /**
16
+ * Format diff results as JSON
17
+ *
18
+ * Output format:
19
+ * {
20
+ * "contracts": {
21
+ * "order": { "changes": [...], "summary": {...}, "suggestedBump": "minor" },
22
+ * "petstore": { "changes": [...], "summary": {...}, "suggestedBump": "none" }
23
+ * }
24
+ * }
25
+ */
26
+ export declare function formatDiffJson(results: DiffResult[]): string;
27
+ /**
28
+ * Filter results by severity level
29
+ */
30
+ export declare function filterBySeverity(results: DiffResult[], severity: string): DiffResult[];
31
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/formatters/diff.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAuC,MAAM,oBAAoB,CAAC;AAE1F,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,OAAO,GAAE,aAAkB,GAAG,IAAI,CASvF;AAsED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAS5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CActF"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Diff output formatters
3
+ *
4
+ * Format diff results for text and JSON output.
5
+ */
6
+ import chalk from 'chalk';
7
+ /**
8
+ * Format diff results as human-readable text
9
+ */
10
+ export function formatDiffText(results, options = {}) {
11
+ if (results.length === 0) {
12
+ console.log(chalk.dim('No contracts to diff.'));
13
+ return;
14
+ }
15
+ for (const result of results) {
16
+ formatContractResult(result, options);
17
+ }
18
+ }
19
+ /**
20
+ * Format a single contract's diff result
21
+ */
22
+ function formatContractResult(result, options) {
23
+ if (result.changes.length === 0) {
24
+ console.log(`${chalk.cyan(result.contract)}: ${chalk.dim('no changes')}`);
25
+ console.log();
26
+ return;
27
+ }
28
+ // Build summary parts
29
+ const parts = [];
30
+ if (result.summary.breaking > 0) {
31
+ parts.push(`${result.summary.breaking} breaking`);
32
+ }
33
+ if (result.summary.nonBreaking > 0) {
34
+ parts.push(`${result.summary.nonBreaking} non-breaking`);
35
+ }
36
+ if (result.summary.patch > 0) {
37
+ parts.push(`${result.summary.patch} patch`);
38
+ }
39
+ if (result.summary.unknown > 0) {
40
+ parts.push(`${result.summary.unknown} unknown`);
41
+ }
42
+ // Color for suggested bump
43
+ const bumpColor = result.suggestedBump === 'major'
44
+ ? chalk.red
45
+ : result.suggestedBump === 'minor'
46
+ ? chalk.yellow
47
+ : chalk.green;
48
+ // Header line
49
+ console.log(`${chalk.cyan(result.contract)}: ${result.changes.length} change(s) (${parts.join(', ')}) — suggested bump: ${bumpColor(result.suggestedBump)}`);
50
+ console.log();
51
+ // Each change
52
+ for (const change of result.changes) {
53
+ const label = formatSeverityLabel(change.severity);
54
+ console.log(` ${label} ${change.message}`);
55
+ if (options.verbose && change.path) {
56
+ console.log(`${' '.repeat(14)}path: ${chalk.dim(change.path)}`);
57
+ }
58
+ }
59
+ console.log();
60
+ }
61
+ /**
62
+ * Format severity as a colored, padded label
63
+ */
64
+ function formatSeverityLabel(severity) {
65
+ switch (severity) {
66
+ case 'breaking':
67
+ return chalk.red.bold('BREAKING'.padEnd(12));
68
+ case 'non-breaking':
69
+ return chalk.yellow('non-breaking');
70
+ case 'patch':
71
+ return chalk.green('patch'.padEnd(12));
72
+ case 'unknown':
73
+ return chalk.gray('unknown'.padEnd(12));
74
+ default:
75
+ return chalk.gray(String(severity).padEnd(12));
76
+ }
77
+ }
78
+ /**
79
+ * Format diff results as JSON
80
+ *
81
+ * Output format:
82
+ * {
83
+ * "contracts": {
84
+ * "order": { "changes": [...], "summary": {...}, "suggestedBump": "minor" },
85
+ * "petstore": { "changes": [...], "summary": {...}, "suggestedBump": "none" }
86
+ * }
87
+ * }
88
+ */
89
+ export function formatDiffJson(results) {
90
+ const contracts = {};
91
+ for (const result of results) {
92
+ const { contract, ...rest } = result;
93
+ contracts[contract] = rest;
94
+ }
95
+ return JSON.stringify({ contracts }, null, 2);
96
+ }
97
+ /**
98
+ * Filter results by severity level
99
+ */
100
+ export function filterBySeverity(results, severity) {
101
+ if (severity === 'all') {
102
+ return results;
103
+ }
104
+ return results.map((r) => {
105
+ const filteredChanges = r.changes.filter((c) => c.severity === severity);
106
+ return {
107
+ ...r,
108
+ changes: filteredChanges,
109
+ summary: recalculateSummary(filteredChanges),
110
+ suggestedBump: calculateSuggestedBump(filteredChanges),
111
+ };
112
+ });
113
+ }
114
+ /**
115
+ * Recalculate summary from filtered changes
116
+ */
117
+ function recalculateSummary(changes) {
118
+ return {
119
+ breaking: changes.filter((c) => c.severity === 'breaking').length,
120
+ nonBreaking: changes.filter((c) => c.severity === 'non-breaking').length,
121
+ patch: changes.filter((c) => c.severity === 'patch').length,
122
+ unknown: changes.filter((c) => c.severity === 'unknown').length,
123
+ };
124
+ }
125
+ /**
126
+ * Calculate suggested bump from changes
127
+ */
128
+ function calculateSuggestedBump(changes) {
129
+ if (changes.some((c) => c.severity === 'breaking')) {
130
+ return 'major';
131
+ }
132
+ if (changes.some((c) => c.severity === 'non-breaking')) {
133
+ return 'minor';
134
+ }
135
+ if (changes.some((c) => c.severity === 'patch')) {
136
+ return 'patch';
137
+ }
138
+ return 'none';
139
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Re-export governance engines from @contractual/governance
3
+ *
4
+ * This module re-exports the governance registry functions and auto-registers
5
+ * all built-in engines on import.
6
+ */
7
+ import '@contractual/governance';
8
+ export { registerLinter, registerDiffer, getLinter, getDiffer, hasLinter, hasDiffer, getRegisteredLinterTypes, getRegisteredDifferTypes, } from '@contractual/governance';
9
+ export { lintOpenAPI, lintJsonSchema, diffOpenAPI, diffJsonSchema } from '@contractual/governance';
10
+ export { executeCustomCommand, parseCustomLintOutput, parseCustomDiffOutput, } from '@contractual/governance';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/governance/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,yBAAyB,CAAC;AAGjC,OAAO,EACL,cAAc,EACd,cAAc,EACd,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGnG,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Re-export governance engines from @contractual/governance
3
+ *
4
+ * This module re-exports the governance registry functions and auto-registers
5
+ * all built-in engines on import.
6
+ */
7
+ // Import to trigger auto-registration of all engines
8
+ import '@contractual/governance';
9
+ // Re-export registry functions
10
+ export { registerLinter, registerDiffer, getLinter, getDiffer, hasLinter, hasDiffer, getRegisteredLinterTypes, getRegisteredDifferTypes, } from '@contractual/governance';
11
+ // Re-export individual engines for direct use
12
+ export { lintOpenAPI, lintJsonSchema, diffOpenAPI, diffJsonSchema } from '@contractual/governance';
13
+ // Re-export runner utilities for custom commands
14
+ export { executeCustomCommand, parseCustomLintOutput, parseCustomDiffOutput, } from '@contractual/governance';
@@ -0,0 +1,9 @@
1
+ export { loadConfig, ConfigError } from './config/index.js';
2
+ export { registerLinter, registerDiffer, getLinter, getDiffer } from './governance/index.js';
3
+ export { diffContracts } from './core/diff.js';
4
+ export type { DiffOptions, DiffContractsResult } from './core/diff.js';
5
+ export { findContractualDir, getSnapshotPath, copyToSnapshots, CONTRACTUAL_DIR, } from './utils/files.js';
6
+ export { VersionManager, PreReleaseManager, createChangeset, readChangesets, aggregateBumps, generateChangesetName, extractContractChanges, appendChangelog, incrementVersionWithPreRelease, VERSIONS_FILE, SNAPSHOTS_DIR, CHANGESETS_DIR, PRE_RELEASE_FILE, } from '@contractual/changesets';
7
+ export type { BumpOperationResult } from '@contractual/changesets';
8
+ export type * from '@contractual/types';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAG7F,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAGvE,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,EACf,8BAA8B,EAC9B,aAAa,EACb,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGnE,mBAAmB,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // Public API for programmatic use
2
+ export { loadConfig, ConfigError } from './config/index.js';
3
+ export { registerLinter, registerDiffer, getLinter, getDiffer } from './governance/index.js';
4
+ // Core diffing
5
+ export { diffContracts } from './core/diff.js';
6
+ // File utilities
7
+ export { findContractualDir, getSnapshotPath, copyToSnapshots, CONTRACTUAL_DIR, } from './utils/files.js';
8
+ // Re-export from @contractual/changesets
9
+ export { VersionManager, PreReleaseManager, createChangeset, readChangesets, aggregateBumps, generateChangesetName, extractContractChanges, appendChangelog, incrementVersionWithPreRelease, VERSIONS_FILE, SNAPSHOTS_DIR, CHANGESETS_DIR, PRE_RELEASE_FILE, } from '@contractual/changesets';
@@ -0,0 +1,29 @@
1
+ import { type ExecSyncOptions } from 'node:child_process';
2
+ /**
3
+ * Result of executing a command
4
+ */
5
+ export interface ExecResult {
6
+ /** Standard output */
7
+ stdout: string;
8
+ /** Standard error */
9
+ stderr: string;
10
+ /** Exit code */
11
+ exitCode: number;
12
+ }
13
+ /**
14
+ * Substitute placeholders in a command string
15
+ */
16
+ export declare function substitutePlaceholders(command: string, substitutions: Record<string, string>): string;
17
+ /**
18
+ * Check if a string contains placeholders
19
+ */
20
+ export declare function hasPlaceholders(command: string): boolean;
21
+ /**
22
+ * Execute a command and return the result
23
+ */
24
+ export declare function execCommand(command: string, substitutions?: Record<string, string>, options?: ExecSyncOptions): ExecResult;
25
+ /**
26
+ * Execute a command and throw if it fails
27
+ */
28
+ export declare function execCommandOrThrow(command: string, substitutions?: Record<string, string>, options?: ExecSyncOptions): string;
29
+ //# sourceMappingURL=exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAsBD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,MAAM,CAMR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAC1C,OAAO,GAAE,eAAoB,GAC5B,UAAU,CA2BZ;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAC1C,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAMR"}
@@ -0,0 +1,66 @@
1
+ import { execSync } from 'node:child_process';
2
+ /**
3
+ * Type guard for execSync errors
4
+ */
5
+ function isExecSyncError(err) {
6
+ return (typeof err === 'object' &&
7
+ err !== null &&
8
+ ('status' in err || 'stdout' in err || 'stderr' in err));
9
+ }
10
+ /**
11
+ * Substitute placeholders in a command string
12
+ */
13
+ export function substitutePlaceholders(command, substitutions) {
14
+ let result = command;
15
+ for (const [key, value] of Object.entries(substitutions)) {
16
+ result = result.replace(new RegExp(`\\{${key}\\}`, 'g'), value);
17
+ }
18
+ return result;
19
+ }
20
+ /**
21
+ * Check if a string contains placeholders
22
+ */
23
+ export function hasPlaceholders(command) {
24
+ return /\{(spec|old|new)\}/.test(command);
25
+ }
26
+ /**
27
+ * Execute a command and return the result
28
+ */
29
+ export function execCommand(command, substitutions = {}, options = {}) {
30
+ const resolvedCommand = substitutePlaceholders(command, substitutions);
31
+ try {
32
+ const stdout = execSync(resolvedCommand, {
33
+ encoding: 'utf-8',
34
+ stdio: ['pipe', 'pipe', 'pipe'],
35
+ ...options,
36
+ });
37
+ return { stdout, stderr: '', exitCode: 0 };
38
+ }
39
+ catch (err) {
40
+ if (isExecSyncError(err)) {
41
+ const stdout = typeof err.stdout === 'string' ? err.stdout : (err.stdout?.toString() ?? '');
42
+ const stderr = typeof err.stderr === 'string' ? err.stderr : (err.stderr?.toString() ?? '');
43
+ return {
44
+ stdout,
45
+ stderr,
46
+ exitCode: err.status ?? 1,
47
+ };
48
+ }
49
+ // Unknown error type - return generic failure
50
+ return {
51
+ stdout: '',
52
+ stderr: err instanceof Error ? err.message : 'Unknown error',
53
+ exitCode: 1,
54
+ };
55
+ }
56
+ }
57
+ /**
58
+ * Execute a command and throw if it fails
59
+ */
60
+ export function execCommandOrThrow(command, substitutions = {}, options = {}) {
61
+ const result = execCommand(command, substitutions, options);
62
+ if (result.exitCode !== 0) {
63
+ throw new Error(`Command failed with exit code ${result.exitCode}: ${result.stderr}`);
64
+ }
65
+ return result.stdout;
66
+ }