norn-cli 1.6.0 → 1.6.2

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 (40) hide show
  1. package/AGENTS.md +9 -1
  2. package/CHANGELOG.md +23 -0
  3. package/dist/cli.js +246 -80
  4. package/package.json +1 -1
  5. package/out/assertionRunner.js +0 -537
  6. package/out/chatParticipant.js +0 -722
  7. package/out/cli/colors.js +0 -129
  8. package/out/cli/formatters/assertion.js +0 -75
  9. package/out/cli/formatters/index.js +0 -23
  10. package/out/cli/formatters/response.js +0 -106
  11. package/out/cli/formatters/summary.js +0 -187
  12. package/out/cli/redaction.js +0 -237
  13. package/out/cli/reporters/html.js +0 -634
  14. package/out/cli/reporters/index.js +0 -22
  15. package/out/cli/reporters/junit.js +0 -211
  16. package/out/cli.js +0 -989
  17. package/out/codeLensProvider.js +0 -248
  18. package/out/compareContentProvider.js +0 -85
  19. package/out/completionProvider.js +0 -2404
  20. package/out/contractDecorationProvider.js +0 -243
  21. package/out/coverageCalculator.js +0 -837
  22. package/out/coveragePanel.js +0 -545
  23. package/out/diagnosticProvider.js +0 -1113
  24. package/out/environmentProvider.js +0 -442
  25. package/out/extension.js +0 -1114
  26. package/out/httpClient.js +0 -269
  27. package/out/jsonFileReader.js +0 -320
  28. package/out/nornPrompt.js +0 -580
  29. package/out/nornapiParser.js +0 -326
  30. package/out/parser.js +0 -725
  31. package/out/responsePanel.js +0 -4674
  32. package/out/schemaGenerator.js +0 -393
  33. package/out/scriptRunner.js +0 -419
  34. package/out/sequenceRunner.js +0 -3046
  35. package/out/swaggerBodyIntellisenseCache.js +0 -147
  36. package/out/swaggerParser.js +0 -419
  37. package/out/test/coverageCalculator.test.js +0 -100
  38. package/out/test/extension.test.js +0 -48
  39. package/out/testProvider.js +0 -658
  40. package/out/validationCache.js +0 -245
@@ -1,545 +0,0 @@
1
- "use strict";
2
- /**
3
- * Coverage Panel - Webview for displaying API coverage details
4
- */
5
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- var desc = Object.getOwnPropertyDescriptor(m, k);
8
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
- desc = { enumerable: true, get: function() { return m[k]; } };
10
- }
11
- Object.defineProperty(o, k2, desc);
12
- }) : (function(o, m, k, k2) {
13
- if (k2 === undefined) k2 = k;
14
- o[k2] = m[k];
15
- }));
16
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
- Object.defineProperty(o, "default", { enumerable: true, value: v });
18
- }) : function(o, v) {
19
- o["default"] = v;
20
- });
21
- var __importStar = (this && this.__importStar) || (function () {
22
- var ownKeys = function(o) {
23
- ownKeys = Object.getOwnPropertyNames || function (o) {
24
- var ar = [];
25
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
- return ar;
27
- };
28
- return ownKeys(o);
29
- };
30
- return function (mod) {
31
- if (mod && mod.__esModule) return mod;
32
- var result = {};
33
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
- __setModuleDefault(result, mod);
35
- return result;
36
- };
37
- })();
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.CoveragePanel = void 0;
40
- const vscode = __importStar(require("vscode"));
41
- class CoveragePanel {
42
- static currentPanel;
43
- _panel;
44
- _disposables = [];
45
- _scopeNornapiFilePath;
46
- constructor(panel, scopeNornapiFilePath) {
47
- this._panel = panel;
48
- this._scopeNornapiFilePath = scopeNornapiFilePath;
49
- this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
50
- }
51
- static show(coverage, scopeNornapiFilePath) {
52
- const column = vscode.ViewColumn.Beside;
53
- if (CoveragePanel.currentPanel) {
54
- CoveragePanel.currentPanel._panel.reveal(column);
55
- CoveragePanel.currentPanel._scopeNornapiFilePath = scopeNornapiFilePath;
56
- CoveragePanel.currentPanel._update(coverage);
57
- return;
58
- }
59
- const panel = vscode.window.createWebviewPanel('nornCoverage', 'API Coverage', column, {
60
- enableScripts: true,
61
- retainContextWhenHidden: true,
62
- });
63
- CoveragePanel.currentPanel = new CoveragePanel(panel, scopeNornapiFilePath);
64
- CoveragePanel.currentPanel._update(coverage);
65
- }
66
- dispose() {
67
- CoveragePanel.currentPanel = undefined;
68
- this._panel.dispose();
69
- while (this._disposables.length) {
70
- const d = this._disposables.pop();
71
- if (d) {
72
- d.dispose();
73
- }
74
- }
75
- }
76
- _update(coverage) {
77
- this._panel.title = `API Coverage: ${coverage.percentage}%`;
78
- this._panel.webview.html = this._getHtmlContent(coverage);
79
- // Handle messages from webview
80
- this._panel.webview.onDidReceiveMessage(async (message) => {
81
- switch (message.type) {
82
- case 'refresh':
83
- vscode.commands.executeCommand('norn.refreshCoverage', this._scopeNornapiFilePath);
84
- break;
85
- }
86
- }, null, this._disposables);
87
- }
88
- /**
89
- * Update the panel content (called when coverage is refreshed)
90
- */
91
- static updateContent(coverage) {
92
- if (CoveragePanel.currentPanel) {
93
- CoveragePanel.currentPanel._update(coverage);
94
- }
95
- }
96
- _getHtmlContent(coverage) {
97
- return /*html*/ `
98
- <!DOCTYPE html>
99
- <html lang="en">
100
- <head>
101
- <meta charset="UTF-8">
102
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
103
- <title>API Coverage</title>
104
- <style>
105
- * { box-sizing: border-box; }
106
-
107
- body {
108
- font-family: var(--vscode-font-family);
109
- font-size: var(--vscode-font-size);
110
- color: var(--vscode-foreground);
111
- background-color: var(--vscode-editor-background);
112
- padding: 0;
113
- margin: 0;
114
- }
115
-
116
- .container { padding: 16px; }
117
-
118
- /* Header with overall stats */
119
- .coverage-header {
120
- display: flex;
121
- align-items: center;
122
- gap: 16px;
123
- padding: 20px;
124
- background: var(--vscode-editor-inactiveSelectionBackground);
125
- border-radius: 8px;
126
- margin-bottom: 20px;
127
- }
128
-
129
- .coverage-title {
130
- font-size: 1.3em;
131
- font-weight: bold;
132
- }
133
-
134
- .coverage-percentage {
135
- font-size: 2em;
136
- font-weight: bold;
137
- margin-left: auto;
138
- }
139
-
140
- .coverage-percentage.high { color: #4ec9b0; }
141
- .coverage-percentage.medium { color: #cca700; }
142
- .coverage-percentage.low { color: #f14c4c; }
143
-
144
- .coverage-stats {
145
- color: var(--vscode-descriptionForeground);
146
- font-size: 0.9em;
147
- }
148
-
149
- /* Progress bar */
150
- .progress-container {
151
- margin: 16px 0;
152
- }
153
-
154
- .progress-bar {
155
- height: 8px;
156
- background: var(--vscode-progressBar-background, #0e70c0);
157
- border-radius: 4px;
158
- transition: width 0.3s ease;
159
- }
160
-
161
- .progress-track {
162
- height: 8px;
163
- background: var(--vscode-input-background);
164
- border-radius: 4px;
165
- overflow: hidden;
166
- }
167
-
168
- /* Refresh button */
169
- .refresh-btn {
170
- background: var(--vscode-button-background);
171
- color: var(--vscode-button-foreground);
172
- border: none;
173
- padding: 8px 16px;
174
- border-radius: 4px;
175
- cursor: pointer;
176
- font-family: var(--vscode-font-family);
177
- font-size: var(--vscode-font-size);
178
- display: flex;
179
- align-items: center;
180
- gap: 6px;
181
- }
182
-
183
- .refresh-btn:hover {
184
- background: var(--vscode-button-hoverBackground);
185
- }
186
-
187
- /* Spec sections */
188
- .spec-section {
189
- margin-bottom: 24px;
190
- }
191
-
192
- .spec-header {
193
- display: flex;
194
- align-items: center;
195
- gap: 12px;
196
- padding: 12px 16px;
197
- background: var(--vscode-sideBar-background, var(--vscode-editor-inactiveSelectionBackground));
198
- border-radius: 6px;
199
- margin-bottom: 12px;
200
- cursor: pointer;
201
- }
202
-
203
- .spec-header:hover {
204
- background: var(--vscode-list-hoverBackground);
205
- }
206
-
207
- .spec-title {
208
- font-weight: bold;
209
- flex: 1;
210
- }
211
-
212
- .spec-url {
213
- font-family: var(--vscode-editor-font-family);
214
- font-size: 0.85em;
215
- color: var(--vscode-descriptionForeground);
216
- max-width: 300px;
217
- overflow: hidden;
218
- text-overflow: ellipsis;
219
- white-space: nowrap;
220
- }
221
-
222
- .spec-coverage {
223
- font-weight: bold;
224
- padding: 4px 12px;
225
- border-radius: 4px;
226
- }
227
-
228
- .spec-coverage.high { background: rgba(78, 201, 176, 0.2); color: #4ec9b0; }
229
- .spec-coverage.medium { background: rgba(204, 167, 0, 0.2); color: #cca700; }
230
- .spec-coverage.low { background: rgba(241, 76, 76, 0.2); color: #f14c4c; }
231
-
232
- /* Tag groups */
233
- .tag-group {
234
- margin-bottom: 16px;
235
- }
236
-
237
- .tag-header {
238
- display: flex;
239
- align-items: center;
240
- gap: 8px;
241
- padding: 8px 12px;
242
- background: var(--vscode-textBlockQuote-background);
243
- border-radius: 4px;
244
- margin-bottom: 8px;
245
- cursor: pointer;
246
- }
247
-
248
- .tag-header:hover {
249
- background: var(--vscode-list-hoverBackground);
250
- }
251
-
252
- .tag-name {
253
- font-weight: 600;
254
- text-transform: capitalize;
255
- }
256
-
257
- .tag-stats {
258
- color: var(--vscode-descriptionForeground);
259
- font-size: 0.9em;
260
- margin-left: auto;
261
- }
262
-
263
- .expand-icon {
264
- transition: transform 0.2s;
265
- }
266
-
267
- .expand-icon.collapsed {
268
- transform: rotate(-90deg);
269
- }
270
-
271
- /* Endpoint items */
272
- .endpoint-item {
273
- border: 1px solid var(--vscode-panel-border);
274
- border-radius: 6px;
275
- margin-bottom: 8px;
276
- overflow: hidden;
277
- }
278
-
279
- .endpoint-header {
280
- display: flex;
281
- align-items: center;
282
- gap: 12px;
283
- padding: 10px 12px;
284
- background: var(--vscode-editor-inactiveSelectionBackground);
285
- }
286
-
287
- .endpoint-method {
288
- font-family: var(--vscode-editor-font-family);
289
- font-weight: bold;
290
- padding: 2px 8px;
291
- border-radius: 3px;
292
- font-size: 0.85em;
293
- min-width: 60px;
294
- text-align: center;
295
- }
296
-
297
- .method-get { background: #61affe22; color: #61affe; }
298
- .method-post { background: #49cc9022; color: #49cc90; }
299
- .method-put { background: #fca13022; color: #fca130; }
300
- .method-delete { background: #f9393922; color: #f93e3e; }
301
- .method-patch { background: #50e3c222; color: #50e3c2; }
302
- .method-head, .method-options { background: #9012fe22; color: #9012fe; }
303
-
304
- .endpoint-path {
305
- font-family: var(--vscode-editor-font-family);
306
- flex: 1;
307
- }
308
-
309
- .endpoint-summary {
310
- color: var(--vscode-descriptionForeground);
311
- font-size: 0.85em;
312
- max-width: 200px;
313
- overflow: hidden;
314
- text-overflow: ellipsis;
315
- white-space: nowrap;
316
- }
317
-
318
- .endpoint-progress {
319
- font-size: 0.85em;
320
- color: var(--vscode-descriptionForeground);
321
- }
322
-
323
- /* Response codes */
324
- .response-codes {
325
- display: flex;
326
- flex-wrap: wrap;
327
- gap: 8px;
328
- padding: 10px 12px;
329
- background: var(--vscode-editor-background);
330
- border-top: 1px solid var(--vscode-panel-border);
331
- }
332
-
333
- .response-code {
334
- display: flex;
335
- align-items: center;
336
- gap: 6px;
337
- padding: 4px 10px;
338
- border-radius: 4px;
339
- font-family: var(--vscode-editor-font-family);
340
- font-size: 0.9em;
341
- }
342
-
343
- .response-code.covered {
344
- background: rgba(78, 201, 176, 0.15);
345
- border: 1px solid rgba(78, 201, 176, 0.3);
346
- }
347
-
348
- .response-code.uncovered {
349
- background: rgba(241, 76, 76, 0.1);
350
- border: 1px solid rgba(241, 76, 76, 0.2);
351
- color: var(--vscode-descriptionForeground);
352
- }
353
-
354
- .code-icon {
355
- font-size: 0.9em;
356
- }
357
-
358
- .code-icon.success { color: #4ec9b0; }
359
- .code-icon.missing { color: #f14c4c; }
360
-
361
- .code-value {
362
- font-weight: bold;
363
- }
364
-
365
- .covered-by {
366
- font-size: 0.8em;
367
- color: var(--vscode-descriptionForeground);
368
- margin-left: 4px;
369
- }
370
-
371
- /* Empty state */
372
- .empty-state {
373
- text-align: center;
374
- padding: 48px 24px;
375
- color: var(--vscode-descriptionForeground);
376
- }
377
-
378
- .empty-state-icon {
379
- font-size: 3em;
380
- margin-bottom: 16px;
381
- }
382
-
383
- .empty-state-title {
384
- font-size: 1.2em;
385
- font-weight: bold;
386
- color: var(--vscode-foreground);
387
- margin-bottom: 8px;
388
- }
389
-
390
- /* Collapsible content */
391
- .collapsible-content {
392
- overflow: hidden;
393
- transition: max-height 0.3s ease;
394
- }
395
-
396
- .collapsible-content.collapsed {
397
- max-height: 0 !important;
398
- }
399
- </style>
400
- </head>
401
- <body>
402
- <div class="container">
403
- ${this._renderHeader(coverage)}
404
- ${coverage.hasSwagger ? this._renderSpecs(coverage) : this._renderEmptyState()}
405
- </div>
406
-
407
- <script>
408
- const vscode = acquireVsCodeApi();
409
-
410
- function refresh() {
411
- vscode.postMessage({ type: 'refresh' });
412
- }
413
-
414
- function toggleSection(id) {
415
- const content = document.getElementById(id);
416
- const icon = document.getElementById(id + '-icon');
417
- if (content && icon) {
418
- content.classList.toggle('collapsed');
419
- icon.classList.toggle('collapsed');
420
- }
421
- }
422
- </script>
423
- </body>
424
- </html>`;
425
- }
426
- _renderHeader(coverage) {
427
- const percentClass = coverage.percentage >= 80 ? 'high' : coverage.percentage >= 50 ? 'medium' : 'low';
428
- return /*html*/ `
429
- <div class="coverage-header">
430
- <div>
431
- <div class="coverage-title">API Coverage</div>
432
- <div class="coverage-stats">${coverage.covered} of ${coverage.total} response codes covered</div>
433
- <div class="progress-container">
434
- <div class="progress-track">
435
- <div class="progress-bar" style="width: ${coverage.percentage}%"></div>
436
- </div>
437
- </div>
438
- </div>
439
- <div class="coverage-percentage ${percentClass}">${coverage.percentage}%</div>
440
- <button class="refresh-btn" onclick="refresh()">
441
- ↻ Refresh
442
- </button>
443
- </div>`;
444
- }
445
- _renderSpecs(coverage) {
446
- if (coverage.specs.length === 0) {
447
- return this._renderEmptyState();
448
- }
449
- return coverage.specs.map((spec, index) => this._renderSpec(spec, index)).join('');
450
- }
451
- _renderSpec(spec, index) {
452
- const percentClass = spec.percentage >= 80 ? 'high' : spec.percentage >= 50 ? 'medium' : 'low';
453
- // Group endpoints by tag
454
- const tagGroups = new Map();
455
- for (const endpoint of spec.endpoints) {
456
- if (!tagGroups.has(endpoint.tag)) {
457
- tagGroups.set(endpoint.tag, []);
458
- }
459
- tagGroups.get(endpoint.tag).push(endpoint);
460
- }
461
- const tagsHtml = Array.from(tagGroups.entries())
462
- .map(([tag, endpoints], tagIndex) => this._renderTagGroup(tag, endpoints, `spec-${index}-tag-${tagIndex}`))
463
- .join('');
464
- return /*html*/ `
465
- <div class="spec-section">
466
- <div class="spec-header" onclick="toggleSection('spec-${index}')">
467
- <span class="expand-icon" id="spec-${index}-icon">▼</span>
468
- <span class="spec-title">${this._escapeHtml(spec.swaggerTitle)}</span>
469
- <span class="spec-url" title="${this._escapeHtml(spec.swaggerUrl)}">${this._escapeHtml(spec.swaggerUrl)}</span>
470
- <span class="spec-coverage ${percentClass}">${spec.percentage}%</span>
471
- </div>
472
- <div class="collapsible-content" id="spec-${index}">
473
- ${tagsHtml}
474
- </div>
475
- </div>`;
476
- }
477
- _renderTagGroup(tag, endpoints, id) {
478
- const totalCodes = endpoints.reduce((sum, e) => sum + e.totalCodes, 0);
479
- const coveredCodes = endpoints.reduce((sum, e) => sum + e.coveredCodes, 0);
480
- const endpointsHtml = endpoints.map(e => this._renderEndpoint(e)).join('');
481
- return /*html*/ `
482
- <div class="tag-group">
483
- <div class="tag-header" onclick="toggleSection('${id}')">
484
- <span class="expand-icon" id="${id}-icon">▼</span>
485
- <span class="tag-name">${this._escapeHtml(tag)}</span>
486
- <span class="tag-stats">${coveredCodes}/${totalCodes} codes</span>
487
- </div>
488
- <div class="collapsible-content" id="${id}">
489
- ${endpointsHtml}
490
- </div>
491
- </div>`;
492
- }
493
- _renderEndpoint(endpoint) {
494
- const methodClass = `method-${endpoint.method.toLowerCase()}`;
495
- const codesHtml = endpoint.responseCodes
496
- .map(rc => {
497
- const coveredClass = rc.covered ? 'covered' : 'uncovered';
498
- const iconClass = rc.covered ? 'success' : 'missing';
499
- const icon = rc.covered ? '✓' : '✗';
500
- const coveredByText = rc.covered && rc.coveredBy.length > 0
501
- ? `<span class="covered-by">via ${rc.coveredBy.join(', ')}</span>`
502
- : '';
503
- return /*html*/ `
504
- <div class="response-code ${coveredClass}">
505
- <span class="code-icon ${iconClass}">${icon}</span>
506
- <span class="code-value">${rc.code}</span>
507
- ${coveredByText}
508
- </div>`;
509
- })
510
- .join('');
511
- return /*html*/ `
512
- <div class="endpoint-item">
513
- <div class="endpoint-header">
514
- <span class="endpoint-method ${methodClass}">${endpoint.method}</span>
515
- <span class="endpoint-path">${this._escapeHtml(endpoint.path)}</span>
516
- ${endpoint.summary ? `<span class="endpoint-summary" title="${this._escapeHtml(endpoint.summary)}">${this._escapeHtml(endpoint.summary)}</span>` : ''}
517
- <span class="endpoint-progress">${endpoint.coveredCodes}/${endpoint.totalCodes}</span>
518
- </div>
519
- <div class="response-codes">
520
- ${codesHtml}
521
- </div>
522
- </div>`;
523
- }
524
- _renderEmptyState() {
525
- return /*html*/ `
526
- <div class="empty-state">
527
- <div class="empty-state-icon">📊</div>
528
- <div class="empty-state-title">No Swagger Specs Found</div>
529
- <div>Add a <code>swagger</code> statement to a .nornapi file to track API coverage.</div>
530
- <div style="margin-top: 16px; font-family: var(--vscode-editor-font-family);">
531
- swagger "https://api.example.com/swagger.json"
532
- </div>
533
- </div>`;
534
- }
535
- _escapeHtml(text) {
536
- return text
537
- .replace(/&/g, '&amp;')
538
- .replace(/</g, '&lt;')
539
- .replace(/>/g, '&gt;')
540
- .replace(/"/g, '&quot;')
541
- .replace(/'/g, '&#039;');
542
- }
543
- }
544
- exports.CoveragePanel = CoveragePanel;
545
- //# sourceMappingURL=coveragePanel.js.map