uicontract 0.1.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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/bin/uic.d.ts +9 -0
  4. package/dist/bin/uic.d.ts.map +1 -0
  5. package/dist/bin/uic.js +87 -0
  6. package/dist/bin/uic.js.map +1 -0
  7. package/dist/commands/annotate.d.ts +21 -0
  8. package/dist/commands/annotate.d.ts.map +1 -0
  9. package/dist/commands/annotate.js +236 -0
  10. package/dist/commands/annotate.js.map +1 -0
  11. package/dist/commands/describe.d.ts +19 -0
  12. package/dist/commands/describe.d.ts.map +1 -0
  13. package/dist/commands/describe.js +146 -0
  14. package/dist/commands/describe.js.map +1 -0
  15. package/dist/commands/diff.d.ts +57 -0
  16. package/dist/commands/diff.d.ts.map +1 -0
  17. package/dist/commands/diff.js +404 -0
  18. package/dist/commands/diff.js.map +1 -0
  19. package/dist/commands/find.d.ts +34 -0
  20. package/dist/commands/find.d.ts.map +1 -0
  21. package/dist/commands/find.js +229 -0
  22. package/dist/commands/find.js.map +1 -0
  23. package/dist/commands/index.d.ts +18 -0
  24. package/dist/commands/index.d.ts.map +1 -0
  25. package/dist/commands/index.js +11 -0
  26. package/dist/commands/index.js.map +1 -0
  27. package/dist/commands/list.d.ts +23 -0
  28. package/dist/commands/list.d.ts.map +1 -0
  29. package/dist/commands/list.js +238 -0
  30. package/dist/commands/list.js.map +1 -0
  31. package/dist/commands/name.d.ts +21 -0
  32. package/dist/commands/name.d.ts.map +1 -0
  33. package/dist/commands/name.js +154 -0
  34. package/dist/commands/name.js.map +1 -0
  35. package/dist/commands/scan.d.ts +32 -0
  36. package/dist/commands/scan.d.ts.map +1 -0
  37. package/dist/commands/scan.js +294 -0
  38. package/dist/commands/scan.js.map +1 -0
  39. package/dist/fuzzy-match.d.ts +45 -0
  40. package/dist/fuzzy-match.d.ts.map +1 -0
  41. package/dist/fuzzy-match.js +134 -0
  42. package/dist/fuzzy-match.js.map +1 -0
  43. package/dist/index.d.ts +5 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +5 -0
  46. package/dist/index.js.map +1 -0
  47. package/package.json +63 -0
@@ -0,0 +1,57 @@
1
+ /**
2
+ * `uic diff` command — compare two manifests and detect breaking changes.
3
+ *
4
+ * stdout: diff report (human-readable or JSON)
5
+ * stderr: logs, errors, help text
6
+ */
7
+ import type { Manifest, ManifestElement } from '@uicontract/core';
8
+ export declare const DIFF_HELP = "uic diff <old-manifest> <new-manifest> [options]\n\nCompare two manifests and report changes. Exits non-zero if breaking changes found.\n\nARGUMENTS\n <old-manifest> Path to the baseline manifest\n <new-manifest> Path to the new/current manifest\n\nOPTIONS\n --allow-breaking <reason> Override exit code to 0 even with breaking changes\n --config <path> Path to .uicrc.json config file (auto-detected if omitted)\n --json Output diff result as JSON\n --help, -h Show this help message\n\nCHANGE CATEGORIES\n BREAKING: REMOVED, RENAMED, TYPE_CHANGED, ROUTE_CHANGED\n Informational: ADDED, LABEL_CHANGED, HANDLER_CHANGED, MOVED\n\nEXIT CODES\n 0 No breaking changes (or --allow-breaking used with no protected scope violations)\n 1 Breaking changes found, error, or protected scope violation\n\nEXAMPLES\n uic diff baseline.json current.json\n uic diff old.json new.json --json\n uic diff old.json new.json --allow-breaking \"Intentional redesign of nav\"\n uic diff old.json new.json --config ./my-config.json\n\nRun \"uicontract --help\" for the full list of commands.\n";
9
+ export type DiffCategory = 'ADDED' | 'REMOVED' | 'RENAMED' | 'TYPE_CHANGED' | 'ROUTE_CHANGED' | 'LABEL_CHANGED' | 'HANDLER_CHANGED' | 'MOVED';
10
+ export interface DiffChange {
11
+ category: DiffCategory;
12
+ breaking: boolean;
13
+ agentId: string;
14
+ details: string;
15
+ oldElement?: ManifestElement;
16
+ newElement?: ManifestElement;
17
+ }
18
+ export interface DiffSummary {
19
+ added: number;
20
+ removed: number;
21
+ renamed: number;
22
+ typeChanged: number;
23
+ routeChanged: number;
24
+ labelChanged: number;
25
+ handlerChanged: number;
26
+ moved: number;
27
+ total: number;
28
+ breakingCount: number;
29
+ }
30
+ export interface DiffResult {
31
+ changes: DiffChange[];
32
+ breaking: boolean;
33
+ summary: DiffSummary;
34
+ }
35
+ export interface DiffArgs {
36
+ oldManifest: string | undefined;
37
+ newManifest: string | undefined;
38
+ allowBreaking: string | undefined;
39
+ configPath: string | undefined;
40
+ json: boolean;
41
+ help: boolean;
42
+ }
43
+ export interface DiffArgsError {
44
+ error: string;
45
+ }
46
+ export declare function parseDiffArgs(args: string[]): DiffArgs | DiffArgsError;
47
+ /** Compare two manifests and return categorized changes. */
48
+ export declare function diffManifests(oldManifest: Manifest, newManifest: Manifest): DiffResult;
49
+ /**
50
+ * Check which breaking changes touch a protected scope.
51
+ * Returns the subset of breaking changes whose agentId starts with
52
+ * any prefix in `protectedScopes`.
53
+ */
54
+ export declare function findProtectedScopeViolations(changes: DiffChange[], protectedScopes: string[]): DiffChange[];
55
+ export declare function formatDiffReport(result: DiffResult, allowBreaking: string | undefined, protectedViolations?: DiffChange[]): string;
56
+ export declare function diffCommand(args: string[]): Promise<number>;
57
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAa,MAAM,kBAAkB,CAAC;AAM7E,eAAO,MAAM,SAAS,2oCA8BrB,CAAC;AAMF,MAAM,MAAM,YAAY,GACpB,OAAO,GACP,SAAS,GACT,SAAS,GACT,cAAc,GACd,eAAe,GACf,eAAe,GACf,iBAAiB,GACjB,OAAO,CAAC;AAEZ,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;CACtB;AAMD,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,GAAG,aAAa,CA4DtE;AAMD,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,GAAG,UAAU,CAyJtF;AAMD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,UAAU,EAAE,EACrB,eAAe,EAAE,MAAM,EAAE,GACxB,UAAU,EAAE,CAOd;AAMD,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,UAAU,EAClB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,mBAAmB,GAAE,UAAU,EAAO,GACrC,MAAM,CAwDR;AAMD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0GjE"}
@@ -0,0 +1,404 @@
1
+ /**
2
+ * `uic diff` command — compare two manifests and detect breaking changes.
3
+ *
4
+ * stdout: diff report (human-readable or JSON)
5
+ * stderr: logs, errors, help text
6
+ */
7
+ import * as fs from 'node:fs/promises';
8
+ import * as path from 'node:path';
9
+ import { deserializeManifest, loadConfig } from '@uicontract/core';
10
+ // ---------------------------------------------------------------------------
11
+ // Help text
12
+ // ---------------------------------------------------------------------------
13
+ export const DIFF_HELP = `\
14
+ uic diff <old-manifest> <new-manifest> [options]
15
+
16
+ Compare two manifests and report changes. Exits non-zero if breaking changes found.
17
+
18
+ ARGUMENTS
19
+ <old-manifest> Path to the baseline manifest
20
+ <new-manifest> Path to the new/current manifest
21
+
22
+ OPTIONS
23
+ --allow-breaking <reason> Override exit code to 0 even with breaking changes
24
+ --config <path> Path to .uicrc.json config file (auto-detected if omitted)
25
+ --json Output diff result as JSON
26
+ --help, -h Show this help message
27
+
28
+ CHANGE CATEGORIES
29
+ BREAKING: REMOVED, RENAMED, TYPE_CHANGED, ROUTE_CHANGED
30
+ Informational: ADDED, LABEL_CHANGED, HANDLER_CHANGED, MOVED
31
+
32
+ EXIT CODES
33
+ 0 No breaking changes (or --allow-breaking used with no protected scope violations)
34
+ 1 Breaking changes found, error, or protected scope violation
35
+
36
+ EXAMPLES
37
+ uic diff baseline.json current.json
38
+ uic diff old.json new.json --json
39
+ uic diff old.json new.json --allow-breaking "Intentional redesign of nav"
40
+ uic diff old.json new.json --config ./my-config.json
41
+
42
+ Run "uicontract --help" for the full list of commands.
43
+ `;
44
+ export function parseDiffArgs(args) {
45
+ let allowBreaking;
46
+ let configPath;
47
+ let json = false;
48
+ let help = false;
49
+ const positionals = [];
50
+ for (let i = 0; i < args.length; i++) {
51
+ const arg = args[i];
52
+ if (arg === '--help' || arg === '-h') {
53
+ help = true;
54
+ continue;
55
+ }
56
+ if (arg === '--json') {
57
+ json = true;
58
+ continue;
59
+ }
60
+ if (arg === '--allow-breaking') {
61
+ const next = args[i + 1];
62
+ if (next === undefined || next.startsWith('-')) {
63
+ return { error: 'Missing value for --allow-breaking. Provide a reason. Example: --allow-breaking "Intentional redesign"' };
64
+ }
65
+ allowBreaking = next;
66
+ i++;
67
+ continue;
68
+ }
69
+ if (arg === '--config') {
70
+ const next = args[i + 1];
71
+ if (next === undefined || next.startsWith('-')) {
72
+ return { error: 'Missing value for --config. Provide a path. Example: --config .uicrc.json' };
73
+ }
74
+ configPath = next;
75
+ i++;
76
+ continue;
77
+ }
78
+ if (arg !== undefined && arg.startsWith('-')) {
79
+ return { error: `Unknown option: ${arg}. Run "uicontract diff --help" for usage.` };
80
+ }
81
+ if (arg !== undefined) {
82
+ positionals.push(arg);
83
+ }
84
+ }
85
+ if (!help && positionals.length < 2) {
86
+ return { error: 'Missing required arguments. Usage: uic diff <old-manifest> <new-manifest>' };
87
+ }
88
+ if (positionals.length > 2) {
89
+ return { error: `Unexpected argument: "${positionals[2] ?? ''}". Run "uicontract diff --help" for usage.` };
90
+ }
91
+ return {
92
+ oldManifest: positionals[0],
93
+ newManifest: positionals[1],
94
+ allowBreaking,
95
+ configPath,
96
+ json,
97
+ help,
98
+ };
99
+ }
100
+ // ---------------------------------------------------------------------------
101
+ // Diff logic (pure function — no I/O)
102
+ // ---------------------------------------------------------------------------
103
+ /** Compare two manifests and return categorized changes. */
104
+ export function diffManifests(oldManifest, newManifest) {
105
+ const oldById = new Map();
106
+ for (const el of oldManifest.elements) {
107
+ oldById.set(el.agentId, el);
108
+ }
109
+ const newById = new Map();
110
+ for (const el of newManifest.elements) {
111
+ newById.set(el.agentId, el);
112
+ }
113
+ const changes = [];
114
+ // Build location maps for rename detection
115
+ // key: "filePath:line" -> element
116
+ const oldByLocation = new Map();
117
+ for (const el of oldManifest.elements) {
118
+ oldByLocation.set(`${el.filePath}:${String(el.line)}`, el);
119
+ }
120
+ const newByLocation = new Map();
121
+ for (const el of newManifest.elements) {
122
+ newByLocation.set(`${el.filePath}:${String(el.line)}`, el);
123
+ }
124
+ // Track IDs involved in renames to avoid double-counting
125
+ const renamedOldIds = new Set();
126
+ const renamedNewIds = new Set();
127
+ // Detect renames: IDs that were removed where a new ID appeared at the same location
128
+ for (const [oldId, oldEl] of oldById) {
129
+ if (newById.has(oldId))
130
+ continue; // not removed
131
+ const location = `${oldEl.filePath}:${String(oldEl.line)}`;
132
+ const newAtSameLocation = newByLocation.get(location);
133
+ if (newAtSameLocation !== undefined && !oldById.has(newAtSameLocation.agentId)) {
134
+ // New element at same location with a different ID → rename
135
+ renamedOldIds.add(oldId);
136
+ renamedNewIds.add(newAtSameLocation.agentId);
137
+ changes.push({
138
+ category: 'RENAMED',
139
+ breaking: true,
140
+ agentId: oldId,
141
+ details: `Renamed: "${oldId}" → "${newAtSameLocation.agentId}" at ${oldEl.filePath}:${String(oldEl.line)}`,
142
+ oldElement: oldEl,
143
+ newElement: newAtSameLocation,
144
+ });
145
+ }
146
+ }
147
+ // Removed elements (in old, not in new, not renamed)
148
+ for (const [oldId, oldEl] of oldById) {
149
+ if (newById.has(oldId))
150
+ continue;
151
+ if (renamedOldIds.has(oldId))
152
+ continue;
153
+ changes.push({
154
+ category: 'REMOVED',
155
+ breaking: true,
156
+ agentId: oldId,
157
+ details: `Removed: "${oldId}" was in ${oldEl.filePath}:${String(oldEl.line)}`,
158
+ oldElement: oldEl,
159
+ });
160
+ }
161
+ // Added elements (in new, not in old, not from rename)
162
+ for (const [newId, newEl] of newById) {
163
+ if (oldById.has(newId))
164
+ continue;
165
+ if (renamedNewIds.has(newId))
166
+ continue;
167
+ changes.push({
168
+ category: 'ADDED',
169
+ breaking: false,
170
+ agentId: newId,
171
+ details: `Added: "${newId}" in ${newEl.filePath}:${String(newEl.line)}`,
172
+ newElement: newEl,
173
+ });
174
+ }
175
+ // Changed elements (same agentId in both)
176
+ for (const [id, oldEl] of oldById) {
177
+ const newEl = newById.get(id);
178
+ if (newEl === undefined)
179
+ continue;
180
+ if (oldEl.type !== newEl.type) {
181
+ changes.push({
182
+ category: 'TYPE_CHANGED',
183
+ breaking: true,
184
+ agentId: id,
185
+ details: `Type changed: "${oldEl.type}" → "${newEl.type}"`,
186
+ oldElement: oldEl,
187
+ newElement: newEl,
188
+ });
189
+ }
190
+ if (oldEl.route !== newEl.route) {
191
+ changes.push({
192
+ category: 'ROUTE_CHANGED',
193
+ breaking: true,
194
+ agentId: id,
195
+ details: `Route changed: "${oldEl.route ?? '(none)'}" → "${newEl.route ?? '(none)'}"`,
196
+ oldElement: oldEl,
197
+ newElement: newEl,
198
+ });
199
+ }
200
+ if (oldEl.label !== newEl.label) {
201
+ changes.push({
202
+ category: 'LABEL_CHANGED',
203
+ breaking: false,
204
+ agentId: id,
205
+ details: `Label changed: "${oldEl.label ?? '(none)'}" → "${newEl.label ?? '(none)'}"`,
206
+ oldElement: oldEl,
207
+ newElement: newEl,
208
+ });
209
+ }
210
+ if (oldEl.handler !== newEl.handler) {
211
+ changes.push({
212
+ category: 'HANDLER_CHANGED',
213
+ breaking: false,
214
+ agentId: id,
215
+ details: `Handler changed: "${oldEl.handler ?? '(none)'}" → "${newEl.handler ?? '(none)'}"`,
216
+ oldElement: oldEl,
217
+ newElement: newEl,
218
+ });
219
+ }
220
+ if (oldEl.filePath !== newEl.filePath || oldEl.line !== newEl.line) {
221
+ changes.push({
222
+ category: 'MOVED',
223
+ breaking: false,
224
+ agentId: id,
225
+ details: `Moved: ${oldEl.filePath}:${String(oldEl.line)} → ${newEl.filePath}:${String(newEl.line)}`,
226
+ oldElement: oldEl,
227
+ newElement: newEl,
228
+ });
229
+ }
230
+ }
231
+ const summary = {
232
+ added: changes.filter((c) => c.category === 'ADDED').length,
233
+ removed: changes.filter((c) => c.category === 'REMOVED').length,
234
+ renamed: changes.filter((c) => c.category === 'RENAMED').length,
235
+ typeChanged: changes.filter((c) => c.category === 'TYPE_CHANGED').length,
236
+ routeChanged: changes.filter((c) => c.category === 'ROUTE_CHANGED').length,
237
+ labelChanged: changes.filter((c) => c.category === 'LABEL_CHANGED').length,
238
+ handlerChanged: changes.filter((c) => c.category === 'HANDLER_CHANGED').length,
239
+ moved: changes.filter((c) => c.category === 'MOVED').length,
240
+ total: changes.length,
241
+ breakingCount: changes.filter((c) => c.breaking).length,
242
+ };
243
+ return {
244
+ changes,
245
+ breaking: summary.breakingCount > 0,
246
+ summary,
247
+ };
248
+ }
249
+ // ---------------------------------------------------------------------------
250
+ // Protected scope checking (pure function)
251
+ // ---------------------------------------------------------------------------
252
+ /**
253
+ * Check which breaking changes touch a protected scope.
254
+ * Returns the subset of breaking changes whose agentId starts with
255
+ * any prefix in `protectedScopes`.
256
+ */
257
+ export function findProtectedScopeViolations(changes, protectedScopes) {
258
+ if (protectedScopes.length === 0)
259
+ return [];
260
+ return changes.filter((c) => c.breaking &&
261
+ protectedScopes.some((scope) => c.agentId.startsWith(scope)));
262
+ }
263
+ // ---------------------------------------------------------------------------
264
+ // Formatting
265
+ // ---------------------------------------------------------------------------
266
+ export function formatDiffReport(result, allowBreaking, protectedViolations = []) {
267
+ if (result.changes.length === 0) {
268
+ return 'UIC Manifest Diff\n=================\n\nNo changes detected.\n';
269
+ }
270
+ const lines = ['UIC Manifest Diff', '=================', ''];
271
+ // Protected scope violations section (always shown first if any)
272
+ if (protectedViolations.length > 0) {
273
+ lines.push(`PROTECTED SCOPE VIOLATIONS (${String(protectedViolations.length)}):`);
274
+ lines.push(' These changes affect protected scopes and cannot be overridden with --allow-breaking.');
275
+ for (const change of protectedViolations) {
276
+ lines.push(` !! ${change.category} ${change.agentId}`);
277
+ lines.push(` ${change.details}`);
278
+ }
279
+ lines.push('');
280
+ }
281
+ const protectedIds = new Set(protectedViolations.map((c) => `${c.category}:${c.agentId}`));
282
+ const breakingNonProtected = result.changes.filter((c) => c.breaking && !protectedIds.has(`${c.category}:${c.agentId}`));
283
+ const nonBreaking = result.changes.filter((c) => !c.breaking);
284
+ if (breakingNonProtected.length > 0) {
285
+ lines.push(`BREAKING CHANGES (${String(breakingNonProtected.length)}):`);
286
+ for (const change of breakingNonProtected) {
287
+ lines.push(` \u2717 ${change.category} ${change.agentId}`);
288
+ lines.push(` ${change.details}`);
289
+ }
290
+ lines.push('');
291
+ }
292
+ if (nonBreaking.length > 0) {
293
+ lines.push(`NON-BREAKING CHANGES (${String(nonBreaking.length)}):`);
294
+ for (const change of nonBreaking) {
295
+ const prefix = change.category === 'ADDED' ? '+' : '~';
296
+ lines.push(` ${prefix} ${change.category} ${change.agentId}`);
297
+ lines.push(` ${change.details}`);
298
+ }
299
+ lines.push('');
300
+ }
301
+ lines.push(`Summary: ${String(result.summary.total)} change(s) (${String(result.summary.breakingCount)} breaking, ${String(result.summary.total - result.summary.breakingCount)} non-breaking)`);
302
+ if (allowBreaking !== undefined && result.breaking) {
303
+ lines.push(`\nBreaking changes allowed: "${allowBreaking}"`);
304
+ }
305
+ return lines.join('\n') + '\n';
306
+ }
307
+ // ---------------------------------------------------------------------------
308
+ // Main command
309
+ // ---------------------------------------------------------------------------
310
+ export async function diffCommand(args) {
311
+ const parsed = parseDiffArgs(args);
312
+ if ('error' in parsed) {
313
+ process.stderr.write(`Error: ${parsed.error}\n`);
314
+ return 1;
315
+ }
316
+ if (parsed.help) {
317
+ process.stderr.write(DIFF_HELP);
318
+ return 0;
319
+ }
320
+ const oldPath = path.resolve(parsed.oldManifest);
321
+ const newPath = path.resolve(parsed.newManifest);
322
+ // Load config
323
+ let config;
324
+ if (parsed.configPath !== undefined) {
325
+ // Explicit config path: read and validate directly
326
+ const configFilePath = path.resolve(parsed.configPath);
327
+ try {
328
+ const raw = await fs.readFile(configFilePath, 'utf-8');
329
+ const { validateConfig } = await import('@uicontract/core');
330
+ const jsonParsed = JSON.parse(raw);
331
+ config = validateConfig(jsonParsed);
332
+ }
333
+ catch (err) {
334
+ const message = err instanceof Error ? err.message : String(err);
335
+ process.stderr.write(`Error: Failed to load config "${configFilePath}": ${message}\n`);
336
+ return 1;
337
+ }
338
+ }
339
+ else {
340
+ try {
341
+ config = await loadConfig(process.cwd());
342
+ }
343
+ catch (err) {
344
+ const message = err instanceof Error ? err.message : String(err);
345
+ process.stderr.write(`Error: Failed to load config: ${message}\n`);
346
+ return 1;
347
+ }
348
+ }
349
+ // Load old manifest
350
+ let oldManifest;
351
+ try {
352
+ const raw = await fs.readFile(oldPath, 'utf-8');
353
+ oldManifest = deserializeManifest(raw);
354
+ }
355
+ catch (err) {
356
+ const message = err instanceof Error ? err.message : String(err);
357
+ process.stderr.write(`Error: Failed to load old manifest "${oldPath}": ${message}\n`);
358
+ return 1;
359
+ }
360
+ // Load new manifest
361
+ let newManifest;
362
+ try {
363
+ const raw = await fs.readFile(newPath, 'utf-8');
364
+ newManifest = deserializeManifest(raw);
365
+ }
366
+ catch (err) {
367
+ const message = err instanceof Error ? err.message : String(err);
368
+ process.stderr.write(`Error: Failed to load new manifest "${newPath}": ${message}\n`);
369
+ return 1;
370
+ }
371
+ const result = diffManifests(oldManifest, newManifest);
372
+ // Check protected scope violations
373
+ const protectedViolations = findProtectedScopeViolations(result.changes, config.protectedScopes);
374
+ if (parsed.json) {
375
+ const jsonOutput = {
376
+ ...result,
377
+ protectedScopeViolations: protectedViolations.map((c) => c.agentId),
378
+ };
379
+ process.stdout.write(JSON.stringify(jsonOutput, null, 2) + '\n');
380
+ }
381
+ else {
382
+ process.stdout.write(formatDiffReport(result, parsed.allowBreaking, protectedViolations));
383
+ }
384
+ // Exit code logic:
385
+ // 1. Protected scope violations ALWAYS exit 1 (--allow-breaking does NOT override)
386
+ if (protectedViolations.length > 0) {
387
+ return 1;
388
+ }
389
+ // 2. Breaking changes follow policy
390
+ if (result.breaking) {
391
+ if (parsed.allowBreaking !== undefined) {
392
+ // --allow-breaking overrides the policy
393
+ return 0;
394
+ }
395
+ if (config.breakingChangePolicy === 'warn') {
396
+ // "warn" policy: print (already done above) but exit 0
397
+ return 0;
398
+ }
399
+ // "block" policy (default): exit 1
400
+ return 1;
401
+ }
402
+ return 0;
403
+ }
404
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `uic find` command -- fuzzy search for elements in a manifest.
3
+ *
4
+ * stdout: matching elements (human-readable or JSON)
5
+ * stderr: logs, errors, help text
6
+ */
7
+ import type { ManifestElement } from '@uicontract/core';
8
+ export declare const FIND_HELP = "uic find <query> [options]\n\nSearch for interactive UI elements in a manifest by name, label, route, or handler.\n\nARGUMENTS\n <query> Text to search for (case-insensitive)\n\nOPTIONS\n --manifest <path> Path to manifest file (default: manifest.json)\n --type <type> Filter results to a specific element type\n --exact Use exact substring matching (no fuzzy matching)\n --fuzzy Use fuzzy matching (default)\n --json Output matching elements as JSON array\n --help, -h Show this help message\n\nEXAMPLES\n uic find \"login\"\n uic find \"pase subscribtion\" # fuzzy match finds \"pause-subscription\"\n uic find \"button\" --type button\n uic find \"settings\" --exact # strict substring match only\n uic find \"settings\" --manifest dist/manifest.json --json\n\nRun \"uicontract --help\" for the full list of commands.\n";
9
+ export interface FindArgs {
10
+ query: string | undefined;
11
+ manifest: string;
12
+ type: string | undefined;
13
+ json: boolean;
14
+ help: boolean;
15
+ exact: boolean;
16
+ }
17
+ export interface FindArgsError {
18
+ error: string;
19
+ }
20
+ export declare function parseFindArgs(args: string[]): FindArgs | FindArgsError;
21
+ /** Check if an element matches the query (case-insensitive substring). */
22
+ export declare function elementMatchesQuery(el: ManifestElement, query: string): boolean;
23
+ /** Scored search result for fuzzy mode. */
24
+ export interface ScoredElement {
25
+ element: ManifestElement;
26
+ score: number;
27
+ }
28
+ /**
29
+ * Score an element against a query using fuzzy matching.
30
+ * Returns null if the element does not meet the threshold.
31
+ */
32
+ export declare function scoreElement(el: ManifestElement, query: string): ScoredElement | null;
33
+ export declare function findCommand(args: string[]): Promise<number>;
34
+ //# sourceMappingURL=find.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../src/commands/find.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAOxD,eAAO,MAAM,SAAS,i7BAwBrB,CAAC;AAMF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,GAAG,aAAa,CA8DtE;AAmBD,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAS/E;AAED,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAKrF;AAaD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4FjE"}