norn-cli 2.4.0 → 2.6.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 (96) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +26 -1
  3. package/dist/cli.js +330 -85
  4. package/package.json +24 -5
  5. package/schemas/norn.config.schema.json +43 -1
  6. package/scripts/__pycache__/reddit_signal_miner.cpython-312.pyc +0 -0
  7. package/scripts/reddit_signal_miner.py +482 -0
  8. package/.claude/settings.local.json +0 -18
  9. package/.claude/skills/norn-social-campaign/SKILL.md +0 -70
  10. package/out/apiResponseIntellisenseCache.js +0 -394
  11. package/out/assertionRunner.js +0 -567
  12. package/out/cacheDir.js +0 -136
  13. package/out/chatParticipant.js +0 -763
  14. package/out/cli/colors.js +0 -127
  15. package/out/cli/formatters/assertion.js +0 -102
  16. package/out/cli/formatters/index.js +0 -23
  17. package/out/cli/formatters/response.js +0 -106
  18. package/out/cli/formatters/summary.js +0 -246
  19. package/out/cli/redaction.js +0 -237
  20. package/out/cli/reporters/html.js +0 -689
  21. package/out/cli/reporters/index.js +0 -22
  22. package/out/cli/reporters/junit.js +0 -226
  23. package/out/codeLensProvider.js +0 -351
  24. package/out/compareContentProvider.js +0 -85
  25. package/out/completionProvider.js +0 -3739
  26. package/out/contractAssertionSummary.js +0 -225
  27. package/out/contractDecorationProvider.js +0 -243
  28. package/out/coverageCalculator.js +0 -879
  29. package/out/coveragePanel.js +0 -597
  30. package/out/debug/breakpointResolver.js +0 -84
  31. package/out/debug/breakpoints.js +0 -52
  32. package/out/debug/nornDebugAdapter.js +0 -166
  33. package/out/debug/nornDebugSession.js +0 -613
  34. package/out/debug/sequenceLocationIndex.js +0 -77
  35. package/out/debug/types.js +0 -3
  36. package/out/deepClone.js +0 -21
  37. package/out/diagnosticProvider.js +0 -2554
  38. package/out/environmentParser.js +0 -736
  39. package/out/environmentProvider.js +0 -544
  40. package/out/environmentTemplates.js +0 -146
  41. package/out/errors/formatError.js +0 -113
  42. package/out/errors/nornError.js +0 -29
  43. package/out/formUrlEncoded.js +0 -89
  44. package/out/httpClient.js +0 -348
  45. package/out/httpRuntimeOptions.js +0 -16
  46. package/out/importErrors.js +0 -31
  47. package/out/inlayHintResolver.js +0 -70
  48. package/out/jsonFileReader.js +0 -323
  49. package/out/mcpClient.js +0 -193
  50. package/out/mcpConfig.js +0 -184
  51. package/out/mcpToolIntellisenseCache.js +0 -96
  52. package/out/mcpToolSchema.js +0 -50
  53. package/out/nornConfig.js +0 -132
  54. package/out/nornHoverProvider.js +0 -124
  55. package/out/nornInlayHintsProvider.js +0 -191
  56. package/out/nornPrompt.js +0 -755
  57. package/out/nornSqlParser.js +0 -286
  58. package/out/nornapiHoverProvider.js +0 -135
  59. package/out/nornapiInlayHintsProvider.js +0 -94
  60. package/out/nornapiParser.js +0 -324
  61. package/out/nornenvCodeActionProvider.js +0 -101
  62. package/out/nornenvDecorationProvider.js +0 -239
  63. package/out/nornenvFoldingProvider.js +0 -63
  64. package/out/nornenvHoverProvider.js +0 -114
  65. package/out/nornenvInlayHintsProvider.js +0 -99
  66. package/out/nornenvLanguageModel.js +0 -187
  67. package/out/nornenvRegionRefactor.js +0 -267
  68. package/out/nornsqlHoverProvider.js +0 -95
  69. package/out/nornsqlInlayHintsProvider.js +0 -114
  70. package/out/parser.js +0 -839
  71. package/out/pathAccess.js +0 -28
  72. package/out/postmanImportPanel.js +0 -732
  73. package/out/postmanImportPlanner.js +0 -1155
  74. package/out/postmanImportSidebarView.js +0 -532
  75. package/out/quotedString.js +0 -35
  76. package/out/requestPreparation.js +0 -179
  77. package/out/requestValidation.js +0 -146
  78. package/out/responsePanel.js +0 -7754
  79. package/out/schemaGenerator.js +0 -562
  80. package/out/scriptRunner.js +0 -419
  81. package/out/secrets/cliSecrets.js +0 -415
  82. package/out/secrets/crypto.js +0 -105
  83. package/out/secrets/envFileSecrets.js +0 -177
  84. package/out/secrets/keyStore.js +0 -259
  85. package/out/sequenceDeclaration.js +0 -15
  86. package/out/sequenceRunner.js +0 -3590
  87. package/out/sqlAdapterRunner.js +0 -122
  88. package/out/sqlBuiltInAdapters.js +0 -604
  89. package/out/sqlConfig.js +0 -184
  90. package/out/starterCatalog.js +0 -554
  91. package/out/stringUtils.js +0 -25
  92. package/out/swaggerBodyIntellisenseCache.js +0 -114
  93. package/out/swaggerParser.js +0 -464
  94. package/out/testProvider.js +0 -767
  95. package/out/theoryCaseLoader.js +0 -113
  96. package/out/validationCache.js +0 -211
@@ -1,597 +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: linear-gradient(135deg,
125
- rgba(78, 201, 176, 0.12) 0%,
126
- rgba(86, 156, 214, 0.14) 50%,
127
- rgba(197, 134, 192, 0.08) 100%);
128
- border: 1px solid rgba(78, 201, 176, 0.15);
129
- border-radius: 10px;
130
- margin-bottom: 20px;
131
- position: relative;
132
- overflow: hidden;
133
- }
134
- .coverage-header::before {
135
- content: '';
136
- position: absolute;
137
- top: 0;
138
- left: 0;
139
- right: 0;
140
- bottom: 0;
141
- background: radial-gradient(ellipse at 20% 50%, rgba(78, 201, 176, 0.1) 0%, transparent 50%),
142
- radial-gradient(ellipse at 80% 50%, rgba(86, 156, 214, 0.08) 0%, transparent 50%);
143
- pointer-events: none;
144
- }
145
-
146
- .coverage-title {
147
- font-size: 1.3em;
148
- font-weight: bold;
149
- background: linear-gradient(135deg, #4ec9b0 0%, #569cd6 100%);
150
- -webkit-background-clip: text;
151
- -webkit-text-fill-color: transparent;
152
- background-clip: text;
153
- position: relative;
154
- }
155
-
156
- .coverage-percentage {
157
- font-size: 2em;
158
- font-weight: bold;
159
- margin-left: auto;
160
- position: relative;
161
- }
162
-
163
- .coverage-percentage.high { color: #4ec9b0; }
164
- .coverage-percentage.medium { color: #cca700; }
165
- .coverage-percentage.low { color: #f14c4c; }
166
-
167
- .coverage-stats {
168
- color: var(--vscode-descriptionForeground);
169
- font-size: 0.9em;
170
- }
171
-
172
- /* Progress bar */
173
- .progress-container {
174
- margin: 16px 0;
175
- position: relative;
176
- }
177
-
178
- .progress-bar {
179
- height: 8px;
180
- background: linear-gradient(90deg, #4ec9b0 0%, #569cd6 100%);
181
- border-radius: 4px;
182
- transition: width 0.3s ease;
183
- box-shadow: 0 0 8px rgba(78, 201, 176, 0.4);
184
- }
185
-
186
- .progress-track {
187
- height: 8px;
188
- background: rgba(0, 0, 0, 0.2);
189
- border-radius: 4px;
190
- overflow: hidden;
191
- border: 1px solid rgba(78, 201, 176, 0.1);
192
- }
193
-
194
- /* Refresh button */
195
- .refresh-btn {
196
- background: linear-gradient(135deg, #4ec9b0 0%, #3eb89f 100%);
197
- color: #000;
198
- border: none;
199
- padding: 8px 16px;
200
- border-radius: 6px;
201
- cursor: pointer;
202
- font-family: var(--vscode-font-family);
203
- font-size: var(--vscode-font-size);
204
- display: flex;
205
- align-items: center;
206
- gap: 6px;
207
- font-weight: 600;
208
- box-shadow: 0 2px 8px rgba(78, 201, 176, 0.3);
209
- transition: transform 0.15s, box-shadow 0.15s;
210
- }
211
-
212
- .refresh-btn:hover {
213
- transform: translateY(-1px);
214
- box-shadow: 0 4px 12px rgba(78, 201, 176, 0.4);
215
- }
216
-
217
- /* Spec sections */
218
- .spec-section {
219
- margin-bottom: 24px;
220
- }
221
-
222
- .spec-header {
223
- display: flex;
224
- align-items: center;
225
- gap: 12px;
226
- padding: 12px 16px;
227
- background: linear-gradient(135deg, rgba(86, 156, 214, 0.12) 0%, rgba(78, 201, 176, 0.08) 100%);
228
- border: 1px solid rgba(86, 156, 214, 0.2);
229
- border-radius: 8px;
230
- margin-bottom: 12px;
231
- cursor: pointer;
232
- transition: background 0.2s;
233
- }
234
-
235
- .spec-header:hover {
236
- background: linear-gradient(135deg, rgba(86, 156, 214, 0.18) 0%, rgba(78, 201, 176, 0.12) 100%);
237
- }
238
-
239
- .spec-title {
240
- font-weight: bold;
241
- flex: 1;
242
- color: rgba(86, 156, 214, 0.95);
243
- }
244
-
245
- .spec-url {
246
- font-family: var(--vscode-editor-font-family);
247
- font-size: 0.85em;
248
- color: var(--vscode-descriptionForeground);
249
- max-width: 300px;
250
- overflow: hidden;
251
- text-overflow: ellipsis;
252
- white-space: nowrap;
253
- }
254
-
255
- .spec-coverage {
256
- font-weight: bold;
257
- padding: 4px 12px;
258
- border-radius: 4px;
259
- }
260
-
261
- .spec-coverage.high { background: rgba(78, 201, 176, 0.2); color: #4ec9b0; }
262
- .spec-coverage.medium { background: rgba(204, 167, 0, 0.2); color: #cca700; }
263
- .spec-coverage.low { background: rgba(241, 76, 76, 0.2); color: #f14c4c; }
264
-
265
- /* Tag groups */
266
- .tag-group {
267
- margin-bottom: 16px;
268
- }
269
-
270
- .tag-header {
271
- display: flex;
272
- align-items: center;
273
- gap: 8px;
274
- padding: 8px 12px;
275
- background: linear-gradient(135deg, rgba(197, 134, 192, 0.08) 0%, rgba(86, 156, 214, 0.06) 100%);
276
- border: 1px solid rgba(197, 134, 192, 0.15);
277
- border-radius: 6px;
278
- margin-bottom: 8px;
279
- cursor: pointer;
280
- transition: background 0.2s;
281
- }
282
-
283
- .tag-header:hover {
284
- background: linear-gradient(135deg, rgba(197, 134, 192, 0.14) 0%, rgba(86, 156, 214, 0.1) 100%);
285
- }
286
-
287
- .tag-name {
288
- font-weight: 600;
289
- text-transform: capitalize;
290
- color: rgba(197, 134, 192, 0.9);
291
- }
292
-
293
- .tag-stats {
294
- color: var(--vscode-descriptionForeground);
295
- font-size: 0.9em;
296
- margin-left: auto;
297
- }
298
-
299
- .expand-icon {
300
- transition: transform 0.2s;
301
- }
302
-
303
- .expand-icon.collapsed {
304
- transform: rotate(-90deg);
305
- }
306
-
307
- /* Endpoint items */
308
- .endpoint-item {
309
- border: 1px solid rgba(78, 201, 176, 0.15);
310
- border-radius: 8px;
311
- margin-bottom: 8px;
312
- overflow: hidden;
313
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
314
- }
315
-
316
- .endpoint-header {
317
- display: flex;
318
- align-items: center;
319
- gap: 12px;
320
- padding: 10px 12px;
321
- background: linear-gradient(135deg, rgba(78, 201, 176, 0.06) 0%, rgba(86, 156, 214, 0.04) 100%);
322
- }
323
-
324
- .endpoint-method {
325
- font-family: var(--vscode-editor-font-family);
326
- font-weight: bold;
327
- padding: 2px 8px;
328
- border-radius: 3px;
329
- font-size: 0.85em;
330
- min-width: 60px;
331
- text-align: center;
332
- }
333
-
334
- .method-get { background: #61affe22; color: #61affe; }
335
- .method-post { background: #49cc9022; color: #49cc90; }
336
- .method-put { background: #fca13022; color: #fca130; }
337
- .method-delete { background: #f9393922; color: #f93e3e; }
338
- .method-patch { background: #50e3c222; color: #50e3c2; }
339
- .method-head, .method-options { background: #9012fe22; color: #9012fe; }
340
-
341
- .endpoint-path {
342
- font-family: var(--vscode-editor-font-family);
343
- flex: 1;
344
- }
345
-
346
- .endpoint-summary {
347
- color: var(--vscode-descriptionForeground);
348
- font-size: 0.85em;
349
- max-width: 200px;
350
- overflow: hidden;
351
- text-overflow: ellipsis;
352
- white-space: nowrap;
353
- }
354
-
355
- .endpoint-progress {
356
- font-size: 0.85em;
357
- color: var(--vscode-descriptionForeground);
358
- }
359
-
360
- /* Response codes */
361
- .response-codes {
362
- display: flex;
363
- flex-wrap: wrap;
364
- gap: 8px;
365
- padding: 12px 14px;
366
- background: linear-gradient(135deg, rgba(78, 201, 176, 0.04) 0%, rgba(86, 156, 214, 0.02) 100%);
367
- border-top: 1px solid rgba(78, 201, 176, 0.1);
368
- }
369
-
370
- .response-code {
371
- display: flex;
372
- align-items: center;
373
- gap: 6px;
374
- padding: 5px 12px;
375
- border-radius: 6px;
376
- font-family: var(--vscode-editor-font-family);
377
- font-size: 0.9em;
378
- transition: transform 0.15s, box-shadow 0.15s;
379
- }
380
-
381
- .response-code:hover {
382
- transform: translateY(-1px);
383
- }
384
-
385
- .response-code.covered {
386
- background: linear-gradient(135deg, rgba(78, 201, 176, 0.18) 0%, rgba(78, 201, 176, 0.1) 100%);
387
- border: 1px solid rgba(78, 201, 176, 0.35);
388
- box-shadow: 0 2px 6px rgba(78, 201, 176, 0.15);
389
- }
390
-
391
- .response-code.uncovered {
392
- background: rgba(241, 76, 76, 0.08);
393
- border: 1px solid rgba(241, 76, 76, 0.2);
394
- color: var(--vscode-descriptionForeground);
395
- }
396
-
397
- .code-icon {
398
- font-size: 0.9em;
399
- }
400
-
401
- .code-icon.success { color: #4ec9b0; }
402
- .code-icon.missing { color: #f14c4c; }
403
-
404
- .code-value {
405
- font-weight: bold;
406
- }
407
-
408
- .covered-by {
409
- font-size: 0.8em;
410
- color: var(--vscode-descriptionForeground);
411
- margin-left: 4px;
412
- }
413
-
414
- /* Empty state */
415
- .empty-state {
416
- text-align: center;
417
- padding: 48px 24px;
418
- color: var(--vscode-descriptionForeground);
419
- background: linear-gradient(135deg, rgba(78, 201, 176, 0.05) 0%, rgba(86, 156, 214, 0.04) 100%);
420
- border: 1px solid rgba(78, 201, 176, 0.1);
421
- border-radius: 12px;
422
- margin: 20px 0;
423
- }
424
-
425
- .empty-state-icon {
426
- font-size: 3em;
427
- margin-bottom: 16px;
428
- filter: drop-shadow(0 0 8px rgba(78, 201, 176, 0.3));
429
- }
430
-
431
- .empty-state-title {
432
- font-size: 1.2em;
433
- font-weight: bold;
434
- color: var(--vscode-foreground);
435
- margin-bottom: 8px;
436
- background: linear-gradient(135deg, #4ec9b0 0%, #569cd6 100%);
437
- -webkit-background-clip: text;
438
- -webkit-text-fill-color: transparent;
439
- background-clip: text;
440
- }
441
-
442
- /* Collapsible content */
443
- .collapsible-content {
444
- overflow: hidden;
445
- transition: max-height 0.3s ease;
446
- }
447
-
448
- .collapsible-content.collapsed {
449
- max-height: 0 !important;
450
- }
451
- </style>
452
- </head>
453
- <body>
454
- <div class="container">
455
- ${this._renderHeader(coverage)}
456
- ${coverage.hasSwagger ? this._renderSpecs(coverage) : this._renderEmptyState()}
457
- </div>
458
-
459
- <script>
460
- const vscode = acquireVsCodeApi();
461
-
462
- function refresh() {
463
- vscode.postMessage({ type: 'refresh' });
464
- }
465
-
466
- function toggleSection(id) {
467
- const content = document.getElementById(id);
468
- const icon = document.getElementById(id + '-icon');
469
- if (content && icon) {
470
- content.classList.toggle('collapsed');
471
- icon.classList.toggle('collapsed');
472
- }
473
- }
474
- </script>
475
- </body>
476
- </html>`;
477
- }
478
- _renderHeader(coverage) {
479
- const percentClass = coverage.percentage >= 80 ? 'high' : coverage.percentage >= 50 ? 'medium' : 'low';
480
- return /*html*/ `
481
- <div class="coverage-header">
482
- <div>
483
- <div class="coverage-title">API Coverage</div>
484
- <div class="coverage-stats">${coverage.covered} of ${coverage.total} response codes covered</div>
485
- <div class="progress-container">
486
- <div class="progress-track">
487
- <div class="progress-bar" style="width: ${coverage.percentage}%"></div>
488
- </div>
489
- </div>
490
- </div>
491
- <div class="coverage-percentage ${percentClass}">${coverage.percentage}%</div>
492
- <button class="refresh-btn" onclick="refresh()">
493
- ↻ Refresh
494
- </button>
495
- </div>`;
496
- }
497
- _renderSpecs(coverage) {
498
- if (coverage.specs.length === 0) {
499
- return this._renderEmptyState();
500
- }
501
- return coverage.specs.map((spec, index) => this._renderSpec(spec, index)).join('');
502
- }
503
- _renderSpec(spec, index) {
504
- const percentClass = spec.percentage >= 80 ? 'high' : spec.percentage >= 50 ? 'medium' : 'low';
505
- // Group endpoints by tag
506
- const tagGroups = new Map();
507
- for (const endpoint of spec.endpoints) {
508
- if (!tagGroups.has(endpoint.tag)) {
509
- tagGroups.set(endpoint.tag, []);
510
- }
511
- tagGroups.get(endpoint.tag).push(endpoint);
512
- }
513
- const tagsHtml = Array.from(tagGroups.entries())
514
- .map(([tag, endpoints], tagIndex) => this._renderTagGroup(tag, endpoints, `spec-${index}-tag-${tagIndex}`))
515
- .join('');
516
- return /*html*/ `
517
- <div class="spec-section">
518
- <div class="spec-header" onclick="toggleSection('spec-${index}')">
519
- <span class="expand-icon" id="spec-${index}-icon">▼</span>
520
- <span class="spec-title">${this._escapeHtml(spec.swaggerTitle)}</span>
521
- <span class="spec-url" title="${this._escapeHtml(spec.swaggerUrl)}">${this._escapeHtml(spec.swaggerUrl)}</span>
522
- <span class="spec-coverage ${percentClass}">${spec.percentage}%</span>
523
- </div>
524
- <div class="collapsible-content" id="spec-${index}">
525
- ${tagsHtml}
526
- </div>
527
- </div>`;
528
- }
529
- _renderTagGroup(tag, endpoints, id) {
530
- const totalCodes = endpoints.reduce((sum, e) => sum + e.totalCodes, 0);
531
- const coveredCodes = endpoints.reduce((sum, e) => sum + e.coveredCodes, 0);
532
- const endpointsHtml = endpoints.map(e => this._renderEndpoint(e)).join('');
533
- return /*html*/ `
534
- <div class="tag-group">
535
- <div class="tag-header" onclick="toggleSection('${id}')">
536
- <span class="expand-icon" id="${id}-icon">▼</span>
537
- <span class="tag-name">${this._escapeHtml(tag)}</span>
538
- <span class="tag-stats">${coveredCodes}/${totalCodes} codes</span>
539
- </div>
540
- <div class="collapsible-content" id="${id}">
541
- ${endpointsHtml}
542
- </div>
543
- </div>`;
544
- }
545
- _renderEndpoint(endpoint) {
546
- const methodClass = `method-${endpoint.method.toLowerCase()}`;
547
- const codesHtml = endpoint.responseCodes
548
- .map(rc => {
549
- const coveredClass = rc.covered ? 'covered' : 'uncovered';
550
- const iconClass = rc.covered ? 'success' : 'missing';
551
- const icon = rc.covered ? '✓' : '✗';
552
- const coveredByText = rc.covered && rc.coveredBy.length > 0
553
- ? `<span class="covered-by">via ${rc.coveredBy.join(', ')}</span>`
554
- : '';
555
- return /*html*/ `
556
- <div class="response-code ${coveredClass}">
557
- <span class="code-icon ${iconClass}">${icon}</span>
558
- <span class="code-value">${rc.code}</span>
559
- ${coveredByText}
560
- </div>`;
561
- })
562
- .join('');
563
- return /*html*/ `
564
- <div class="endpoint-item">
565
- <div class="endpoint-header">
566
- <span class="endpoint-method ${methodClass}">${endpoint.method}</span>
567
- <span class="endpoint-path">${this._escapeHtml(endpoint.path)}</span>
568
- ${endpoint.summary ? `<span class="endpoint-summary" title="${this._escapeHtml(endpoint.summary)}">${this._escapeHtml(endpoint.summary)}</span>` : ''}
569
- <span class="endpoint-progress">${endpoint.coveredCodes}/${endpoint.totalCodes}</span>
570
- </div>
571
- <div class="response-codes">
572
- ${codesHtml}
573
- </div>
574
- </div>`;
575
- }
576
- _renderEmptyState() {
577
- return /*html*/ `
578
- <div class="empty-state">
579
- <div class="empty-state-icon">📊</div>
580
- <div class="empty-state-title">No Swagger Specs Found</div>
581
- <div>Add a <code>swagger</code> statement to a .nornapi file to track API coverage.</div>
582
- <div style="margin-top: 16px; font-family: var(--vscode-editor-font-family);">
583
- swagger "https://api.example.com/swagger.json"
584
- </div>
585
- </div>`;
586
- }
587
- _escapeHtml(text) {
588
- return text
589
- .replace(/&/g, '&amp;')
590
- .replace(/</g, '&lt;')
591
- .replace(/>/g, '&gt;')
592
- .replace(/"/g, '&quot;')
593
- .replace(/'/g, '&#039;');
594
- }
595
- }
596
- exports.CoveragePanel = CoveragePanel;
597
- //# sourceMappingURL=coveragePanel.js.map
@@ -1,84 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.resolveBreakpointsForFile = resolveBreakpointsForFile;
37
- const fs = __importStar(require("fs/promises"));
38
- const sequenceRunner_1 = require("../sequenceRunner");
39
- const sequenceDeclaration_1 = require("../sequenceDeclaration");
40
- async function resolveBreakpointsForFile(filePath, requestedLines) {
41
- const content = await fs.readFile(filePath, 'utf-8');
42
- const lines = content.split('\n');
43
- const sequences = (0, sequenceRunner_1.extractSequences)(content);
44
- const bySequence = sequences.map(seq => {
45
- const declarationLine = (0, sequenceDeclaration_1.findSequenceDeclarationLine)(lines, seq.startLine, seq.endLine);
46
- const steps = (0, sequenceRunner_1.extractStepsFromSequence)(seq.content);
47
- const executableLines = steps
48
- .map(step => declarationLine + 1 + step.lineNumber)
49
- .filter(line => line >= 0);
50
- return {
51
- declarationLine,
52
- endLine: seq.endLine,
53
- executableLines
54
- };
55
- });
56
- const sortedRequested = [...requestedLines].sort((a, b) => a - b);
57
- return sortedRequested.map((requestedLine) => {
58
- const requestedZero = Math.max(0, requestedLine - 1);
59
- const container = bySequence.find(seq => requestedZero >= seq.declarationLine && requestedZero <= seq.endLine);
60
- if (!container) {
61
- return {
62
- requestedLine,
63
- line: requestedLine,
64
- verified: false,
65
- message: 'Line is outside a sequence block'
66
- };
67
- }
68
- const candidate = container.executableLines.find(line => line >= requestedZero);
69
- if (candidate === undefined) {
70
- return {
71
- requestedLine,
72
- line: requestedLine,
73
- verified: false,
74
- message: 'No executable steps found at or after this line in sequence'
75
- };
76
- }
77
- return {
78
- requestedLine,
79
- line: candidate + 1,
80
- verified: true
81
- };
82
- });
83
- }
84
- //# sourceMappingURL=breakpointResolver.js.map