norn-cli 2.3.0 → 2.4.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 (92) hide show
  1. package/.claude/skills/norn-social-campaign/SKILL.md +70 -0
  2. package/CHANGELOG.md +6 -0
  3. package/demos/nornenv-region-refactor/README.md +64 -0
  4. package/dist/cli.js +360 -1
  5. package/out/apiResponseIntellisenseCache.js +394 -0
  6. package/out/assertionRunner.js +567 -0
  7. package/out/cacheDir.js +136 -0
  8. package/out/chatParticipant.js +763 -0
  9. package/out/cli/colors.js +127 -0
  10. package/out/cli/formatters/assertion.js +102 -0
  11. package/out/cli/formatters/index.js +23 -0
  12. package/out/cli/formatters/response.js +106 -0
  13. package/out/cli/formatters/summary.js +246 -0
  14. package/out/cli/redaction.js +237 -0
  15. package/out/cli/reporters/html.js +689 -0
  16. package/out/cli/reporters/index.js +22 -0
  17. package/out/cli/reporters/junit.js +226 -0
  18. package/out/codeLensProvider.js +351 -0
  19. package/out/compareContentProvider.js +85 -0
  20. package/out/completionProvider.js +3739 -0
  21. package/out/contractAssertionSummary.js +225 -0
  22. package/out/contractDecorationProvider.js +243 -0
  23. package/out/coverageCalculator.js +879 -0
  24. package/out/coveragePanel.js +597 -0
  25. package/out/debug/breakpointResolver.js +84 -0
  26. package/out/debug/breakpoints.js +52 -0
  27. package/out/debug/nornDebugAdapter.js +166 -0
  28. package/out/debug/nornDebugSession.js +613 -0
  29. package/out/debug/sequenceLocationIndex.js +77 -0
  30. package/out/debug/types.js +3 -0
  31. package/out/deepClone.js +21 -0
  32. package/out/diagnosticProvider.js +2554 -0
  33. package/out/environmentParser.js +736 -0
  34. package/out/environmentProvider.js +544 -0
  35. package/out/environmentTemplates.js +146 -0
  36. package/out/errors/formatError.js +113 -0
  37. package/out/errors/nornError.js +29 -0
  38. package/out/formUrlEncoded.js +89 -0
  39. package/out/httpClient.js +348 -0
  40. package/out/httpRuntimeOptions.js +16 -0
  41. package/out/importErrors.js +31 -0
  42. package/out/inlayHintResolver.js +70 -0
  43. package/out/jsonFileReader.js +323 -0
  44. package/out/mcpClient.js +193 -0
  45. package/out/mcpConfig.js +184 -0
  46. package/out/mcpToolIntellisenseCache.js +96 -0
  47. package/out/mcpToolSchema.js +50 -0
  48. package/out/nornConfig.js +132 -0
  49. package/out/nornHoverProvider.js +124 -0
  50. package/out/nornInlayHintsProvider.js +191 -0
  51. package/out/nornPrompt.js +755 -0
  52. package/out/nornSqlParser.js +286 -0
  53. package/out/nornapiHoverProvider.js +135 -0
  54. package/out/nornapiInlayHintsProvider.js +94 -0
  55. package/out/nornapiParser.js +324 -0
  56. package/out/nornenvCodeActionProvider.js +101 -0
  57. package/out/nornenvDecorationProvider.js +239 -0
  58. package/out/nornenvFoldingProvider.js +63 -0
  59. package/out/nornenvHoverProvider.js +114 -0
  60. package/out/nornenvInlayHintsProvider.js +99 -0
  61. package/out/nornenvLanguageModel.js +187 -0
  62. package/out/nornenvRegionRefactor.js +267 -0
  63. package/out/nornsqlHoverProvider.js +95 -0
  64. package/out/nornsqlInlayHintsProvider.js +114 -0
  65. package/out/parser.js +839 -0
  66. package/out/pathAccess.js +28 -0
  67. package/out/postmanImportPanel.js +732 -0
  68. package/out/postmanImportPlanner.js +1155 -0
  69. package/out/postmanImportSidebarView.js +532 -0
  70. package/out/quotedString.js +35 -0
  71. package/out/requestPreparation.js +179 -0
  72. package/out/requestValidation.js +146 -0
  73. package/out/responsePanel.js +7754 -0
  74. package/out/schemaGenerator.js +562 -0
  75. package/out/scriptRunner.js +419 -0
  76. package/out/secrets/cliSecrets.js +415 -0
  77. package/out/secrets/crypto.js +105 -0
  78. package/out/secrets/envFileSecrets.js +177 -0
  79. package/out/secrets/keyStore.js +259 -0
  80. package/out/sequenceDeclaration.js +15 -0
  81. package/out/sequenceRunner.js +3590 -0
  82. package/out/sqlAdapterRunner.js +122 -0
  83. package/out/sqlBuiltInAdapters.js +604 -0
  84. package/out/sqlConfig.js +184 -0
  85. package/out/starterCatalog.js +554 -0
  86. package/out/stringUtils.js +25 -0
  87. package/out/swaggerBodyIntellisenseCache.js +114 -0
  88. package/out/swaggerParser.js +464 -0
  89. package/out/testProvider.js +767 -0
  90. package/out/theoryCaseLoader.js +113 -0
  91. package/out/validationCache.js +211 -0
  92. package/package.json +6 -1
@@ -0,0 +1,464 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.getCachedSwaggerSpec = getCachedSwaggerSpec;
40
+ exports.clearSwaggerCache = clearSwaggerCache;
41
+ exports.invalidateSwaggerCache = invalidateSwaggerCache;
42
+ exports.parseSwaggerSpec = parseSwaggerSpec;
43
+ exports.generateNornapiContent = generateNornapiContent;
44
+ exports.extractResponseSchemas = extractResponseSchemas;
45
+ exports.extractRequestBodySchemas = extractRequestBodySchemas;
46
+ exports.generateSchemaFilename = generateSchemaFilename;
47
+ const axios_1 = __importDefault(require("axios"));
48
+ const https = __importStar(require("https"));
49
+ const httpRuntimeOptions_1 = require("./httpRuntimeOptions");
50
+ /**
51
+ * Cache for parsed swagger specs (cleared when extension deactivates)
52
+ */
53
+ const swaggerCache = new Map();
54
+ const rawSwaggerSpecCache = new Map();
55
+ const insecureHttpsAgent = new https.Agent({ rejectUnauthorized: false });
56
+ function getHttpsAgent() {
57
+ return (0, httpRuntimeOptions_1.getVerifyTlsCertificates)() ? undefined : insecureHttpsAgent;
58
+ }
59
+ async function getRawSwaggerSpec(url) {
60
+ if (rawSwaggerSpecCache.has(url)) {
61
+ return rawSwaggerSpecCache.get(url);
62
+ }
63
+ const response = await axios_1.default.get(url, {
64
+ adapter: 'http',
65
+ headers: {
66
+ 'Accept': 'application/json'
67
+ },
68
+ timeout: 30000,
69
+ httpsAgent: getHttpsAgent()
70
+ });
71
+ rawSwaggerSpecCache.set(url, response.data);
72
+ return response.data;
73
+ }
74
+ function isOpenApi3Spec(spec) {
75
+ return typeof spec?.openapi === 'string' && spec.openapi.startsWith('3.');
76
+ }
77
+ function resolveRef(ref, root) {
78
+ if (!ref.startsWith('#/')) {
79
+ return undefined;
80
+ }
81
+ const parts = ref.slice(2).split('/');
82
+ let current = root;
83
+ for (const part of parts) {
84
+ if (current === undefined) {
85
+ return undefined;
86
+ }
87
+ current = current[part];
88
+ }
89
+ return current;
90
+ }
91
+ function resolveSchemaRefs(schema, root, visited = new Set()) {
92
+ if (!schema || typeof schema !== 'object') {
93
+ return schema;
94
+ }
95
+ if (schema.$ref && typeof schema.$ref === 'string') {
96
+ if (visited.has(schema.$ref)) {
97
+ return { type: 'object' };
98
+ }
99
+ visited.add(schema.$ref);
100
+ const resolved = resolveRef(schema.$ref, root);
101
+ if (resolved) {
102
+ return resolveSchemaRefs(resolved, root, visited);
103
+ }
104
+ return schema;
105
+ }
106
+ const result = Array.isArray(schema) ? [] : {};
107
+ for (const key of Object.keys(schema)) {
108
+ if (key === '$ref') {
109
+ continue;
110
+ }
111
+ const value = schema[key];
112
+ if (typeof value === 'object' && value !== null) {
113
+ result[key] = resolveSchemaRefs(value, root, new Set(visited));
114
+ }
115
+ else {
116
+ result[key] = value;
117
+ }
118
+ }
119
+ return result;
120
+ }
121
+ function getPreferredJsonSchema(content) {
122
+ if (!content) {
123
+ return undefined;
124
+ }
125
+ if (content['application/json']?.schema) {
126
+ return content['application/json'].schema;
127
+ }
128
+ const jsonKey = Object.keys(content).find(key => key.toLowerCase().includes('json') && content[key]?.schema);
129
+ if (jsonKey) {
130
+ return content[jsonKey].schema;
131
+ }
132
+ if (content['*/*']?.schema) {
133
+ return content['*/*'].schema;
134
+ }
135
+ const firstSchemaKey = Object.keys(content).find(key => content[key]?.schema);
136
+ return firstSchemaKey ? content[firstSchemaKey].schema : undefined;
137
+ }
138
+ function addJsonSchemaMeta(schema, title) {
139
+ return {
140
+ '$schema': 'http://json-schema.org/draft-07/schema#',
141
+ title,
142
+ ...schema
143
+ };
144
+ }
145
+ /**
146
+ * Get a cached swagger spec, or fetch and parse if not cached
147
+ */
148
+ async function getCachedSwaggerSpec(url) {
149
+ if (swaggerCache.has(url)) {
150
+ return swaggerCache.get(url);
151
+ }
152
+ const spec = await parseSwaggerSpec(url);
153
+ swaggerCache.set(url, spec);
154
+ return spec;
155
+ }
156
+ /**
157
+ * Clear the swagger cache (call on extension deactivation)
158
+ */
159
+ function clearSwaggerCache() {
160
+ swaggerCache.clear();
161
+ rawSwaggerSpecCache.clear();
162
+ }
163
+ /**
164
+ * Invalidate a specific URL from the cache (for manual refresh)
165
+ */
166
+ function invalidateSwaggerCache(url) {
167
+ if (url) {
168
+ swaggerCache.delete(url);
169
+ rawSwaggerSpecCache.delete(url);
170
+ }
171
+ else {
172
+ swaggerCache.clear();
173
+ rawSwaggerSpecCache.clear();
174
+ }
175
+ }
176
+ /**
177
+ * Fetches and parses an OpenAPI/Swagger specification from a URL.
178
+ */
179
+ async function parseSwaggerSpec(url) {
180
+ const spec = await getRawSwaggerSpec(url);
181
+ // Determine if it's OpenAPI 3.x or Swagger 2.0
182
+ const isOpenAPI3 = isOpenApi3Spec(spec);
183
+ // Extract base URL
184
+ let baseUrl = '';
185
+ if (isOpenAPI3) {
186
+ // OpenAPI 3.x uses servers array
187
+ if (spec.servers && spec.servers.length > 0) {
188
+ baseUrl = spec.servers[0].url;
189
+ }
190
+ }
191
+ else {
192
+ // Swagger 2.0 uses host + basePath + schemes
193
+ const scheme = spec.schemes?.[0] || 'https';
194
+ const host = spec.host || '';
195
+ const basePath = spec.basePath || '';
196
+ if (host) {
197
+ baseUrl = `${scheme}://${host}${basePath}`;
198
+ }
199
+ }
200
+ // Extract title and version
201
+ const title = spec.info?.title || 'API';
202
+ const version = spec.info?.version || '1.0.0';
203
+ // Group endpoints by tag
204
+ const sectionMap = new Map();
205
+ // Parse paths
206
+ const paths = spec.paths || {};
207
+ for (const [path, pathItem] of Object.entries(paths)) {
208
+ const pathObj = pathItem;
209
+ for (const method of ['get', 'post', 'put', 'delete', 'patch', 'head', 'options']) {
210
+ const operation = pathObj[method];
211
+ if (!operation) {
212
+ continue;
213
+ }
214
+ // Get operation details
215
+ const operationId = operation.operationId || generateOperationId(method, path);
216
+ const tags = operation.tags || ['default'];
217
+ const summary = operation.summary;
218
+ // Extract path parameters
219
+ const parameters = [];
220
+ const pathParams = path.match(/\{([^}]+)\}/g);
221
+ if (pathParams) {
222
+ for (const param of pathParams) {
223
+ parameters.push(param.replace(/[{}]/g, ''));
224
+ }
225
+ }
226
+ // Also check query parameters that are required
227
+ const paramDefs = operation.parameters;
228
+ if (paramDefs) {
229
+ for (const param of paramDefs) {
230
+ if (param.in === 'query' && param.required) {
231
+ parameters.push(param.name);
232
+ }
233
+ }
234
+ }
235
+ // Extract response codes from operation.responses
236
+ const responseCodes = [];
237
+ const responses = operation.responses;
238
+ if (responses) {
239
+ for (const code of Object.keys(responses)) {
240
+ // Include numeric status codes (skip 'default')
241
+ if (/^\d{3}$/.test(code)) {
242
+ responseCodes.push(code);
243
+ }
244
+ }
245
+ // Sort numerically
246
+ responseCodes.sort((a, b) => parseInt(a) - parseInt(b));
247
+ }
248
+ const endpoint = {
249
+ name: sanitizeOperationId(operationId),
250
+ method: method.toUpperCase(),
251
+ path,
252
+ parameters,
253
+ tag: tags[0] || 'default',
254
+ summary,
255
+ responseCodes: responseCodes.length > 0 ? responseCodes : ['200'] // Default to 200 if no responses defined
256
+ };
257
+ // Add to section
258
+ const tag = endpoint.tag;
259
+ if (!sectionMap.has(tag)) {
260
+ sectionMap.set(tag, []);
261
+ }
262
+ sectionMap.get(tag).push(endpoint);
263
+ }
264
+ }
265
+ // Convert to sections array
266
+ const sections = [];
267
+ // Get tag descriptions if available
268
+ const tagDescriptions = new Map();
269
+ if (spec.tags) {
270
+ for (const tag of spec.tags) {
271
+ if (tag.description) {
272
+ tagDescriptions.set(tag.name, tag.description);
273
+ }
274
+ }
275
+ }
276
+ for (const [name, endpoints] of sectionMap) {
277
+ sections.push({
278
+ name,
279
+ description: tagDescriptions.get(name),
280
+ endpoints
281
+ });
282
+ }
283
+ // Sort sections alphabetically
284
+ sections.sort((a, b) => a.name.localeCompare(b.name));
285
+ return {
286
+ title,
287
+ version,
288
+ baseUrl,
289
+ sections
290
+ };
291
+ }
292
+ /**
293
+ * Generate an operation ID from method and path if not provided
294
+ */
295
+ function generateOperationId(method, path) {
296
+ // Convert /pet/{petId} to getPetByPetId
297
+ const parts = path.split('/').filter(p => p && !p.startsWith('{'));
298
+ const pathName = parts.map(p => p.charAt(0).toUpperCase() + p.slice(1)).join('');
299
+ return method.toLowerCase() + pathName;
300
+ }
301
+ /**
302
+ * Sanitize operation ID to be a valid identifier
303
+ */
304
+ function sanitizeOperationId(operationId) {
305
+ // Remove invalid characters and ensure it starts with a letter
306
+ let sanitized = operationId
307
+ .replace(/[^a-zA-Z0-9_]/g, '_')
308
+ .replace(/_+/g, '_')
309
+ .replace(/^_+|_+$/g, '');
310
+ // Ensure it starts with a capital letter
311
+ if (sanitized && /^[a-z]/.test(sanitized)) {
312
+ sanitized = sanitized.charAt(0).toUpperCase() + sanitized.slice(1);
313
+ }
314
+ return sanitized || 'Endpoint';
315
+ }
316
+ /**
317
+ * Generate .nornapi content for selected sections
318
+ */
319
+ function generateNornapiContent(spec, selectedSections, customBaseUrl) {
320
+ const lines = [];
321
+ const baseUrl = customBaseUrl || spec.baseUrl;
322
+ // Add endpoints section
323
+ lines.push('endpoints');
324
+ const sectionsToInclude = selectedSections.includes('All')
325
+ ? spec.sections
326
+ : spec.sections.filter(s => selectedSections.includes(s.name));
327
+ for (const section of sectionsToInclude) {
328
+ // Add section comment
329
+ lines.push(` # ${section.name}${section.description ? ` - ${section.description}` : ''}`);
330
+ for (const endpoint of section.endpoints) {
331
+ // Build the endpoint line with explicit method for full parser/editor support
332
+ const path = endpoint.path;
333
+ lines.push(` ${endpoint.name}: ${endpoint.method} ${baseUrl}${path}`);
334
+ }
335
+ lines.push('');
336
+ }
337
+ lines.push('end endpoints');
338
+ return lines.join('\n');
339
+ }
340
+ /**
341
+ * Extract response schemas from an OpenAPI/Swagger spec
342
+ * Resolves $ref references to inline schemas
343
+ * @param url URL of the OpenAPI spec
344
+ * @returns Array of response schemas
345
+ */
346
+ async function extractResponseSchemas(url) {
347
+ const spec = await getRawSwaggerSpec(url);
348
+ const schemas = [];
349
+ const isOpenAPI3 = isOpenApi3Spec(spec);
350
+ // Parse paths
351
+ const paths = spec.paths || {};
352
+ for (const [pathStr, pathItem] of Object.entries(paths)) {
353
+ const pathObj = pathItem;
354
+ for (const method of ['get', 'post', 'put', 'delete', 'patch', 'head', 'options']) {
355
+ const operation = pathObj[method];
356
+ if (!operation) {
357
+ continue;
358
+ }
359
+ const operationId = operation.operationId || generateOperationId(method, pathStr);
360
+ const responses = operation.responses;
361
+ if (!responses) {
362
+ continue;
363
+ }
364
+ for (const [statusCode, responseObj] of Object.entries(responses)) {
365
+ // Skip non-numeric status codes like 'default'
366
+ if (!/^\d{3}$/.test(statusCode)) {
367
+ continue;
368
+ }
369
+ let schema = null;
370
+ if (isOpenAPI3) {
371
+ // OpenAPI 3.x: responses[code].content["application/json"].schema
372
+ const content = responseObj.content;
373
+ schema = getPreferredJsonSchema(content);
374
+ }
375
+ else {
376
+ // Swagger 2.0: responses[code].schema
377
+ if (responseObj.schema) {
378
+ schema = responseObj.schema;
379
+ }
380
+ }
381
+ if (schema) {
382
+ // Resolve all $ref references
383
+ const resolvedSchema = resolveSchemaRefs(schema, spec);
384
+ // Add JSON Schema meta properties
385
+ const jsonSchema = addJsonSchemaMeta(resolvedSchema, `${sanitizeOperationId(operationId)} ${statusCode} Response`);
386
+ schemas.push({
387
+ operationId: sanitizeOperationId(operationId),
388
+ method: method.toUpperCase(),
389
+ path: pathStr,
390
+ statusCode,
391
+ schema: jsonSchema
392
+ });
393
+ }
394
+ }
395
+ }
396
+ }
397
+ return schemas;
398
+ }
399
+ /**
400
+ * Extract request body schemas from an OpenAPI/Swagger spec
401
+ * Resolves $ref references to inline schemas
402
+ * @param url URL of the OpenAPI spec
403
+ * @returns Array of request body schemas
404
+ */
405
+ async function extractRequestBodySchemas(url) {
406
+ const spec = await getRawSwaggerSpec(url);
407
+ const schemas = [];
408
+ const isOpenAPI3 = isOpenApi3Spec(spec);
409
+ const paths = spec.paths || {};
410
+ for (const [pathStr, pathItem] of Object.entries(paths)) {
411
+ const pathObj = pathItem;
412
+ for (const method of ['get', 'post', 'put', 'delete', 'patch', 'head', 'options']) {
413
+ const operation = pathObj[method];
414
+ if (!operation) {
415
+ continue;
416
+ }
417
+ let schema = null;
418
+ if (isOpenAPI3) {
419
+ // OpenAPI 3.x request body:
420
+ // operation.requestBody.content["application/json"].schema
421
+ let requestBody = operation.requestBody;
422
+ if (requestBody && typeof requestBody.$ref === 'string') {
423
+ requestBody = resolveRef(requestBody.$ref, spec);
424
+ }
425
+ const content = requestBody?.content;
426
+ schema = getPreferredJsonSchema(content);
427
+ }
428
+ else {
429
+ // Swagger 2.0 request body:
430
+ // operation.parameters[] with in: "body"
431
+ const pathParameters = Array.isArray(pathObj.parameters) ? pathObj.parameters : [];
432
+ const operationParameters = Array.isArray(operation.parameters) ? operation.parameters : [];
433
+ const allParameters = [...pathParameters, ...operationParameters];
434
+ const bodyParameter = allParameters.find((param) => param?.in === 'body' && param?.schema);
435
+ if (bodyParameter?.schema) {
436
+ schema = bodyParameter.schema;
437
+ }
438
+ }
439
+ if (!schema) {
440
+ continue;
441
+ }
442
+ const operationId = sanitizeOperationId(operation.operationId || generateOperationId(method, pathStr));
443
+ const resolvedSchema = resolveSchemaRefs(schema, spec);
444
+ const required = Array.isArray(resolvedSchema?.required)
445
+ ? resolvedSchema.required.filter((name) => typeof name === 'string')
446
+ : [];
447
+ schemas.push({
448
+ operationId,
449
+ method: method.toUpperCase(),
450
+ path: pathStr,
451
+ required,
452
+ schema: addJsonSchemaMeta(resolvedSchema, `${operationId} Request`)
453
+ });
454
+ }
455
+ }
456
+ return schemas;
457
+ }
458
+ /**
459
+ * Generate schema filename from operation details
460
+ */
461
+ function generateSchemaFilename(operationId, statusCode) {
462
+ return `${operationId}-${statusCode}.schema.json`;
463
+ }
464
+ //# sourceMappingURL=swaggerParser.js.map