norn-cli 1.3.16 → 1.3.18

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.
@@ -0,0 +1,254 @@
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.HttpCodeLensProvider = void 0;
37
+ exports.updateCodeLensCoverage = updateCodeLensCoverage;
38
+ const vscode = __importStar(require("vscode"));
39
+ const environmentProvider_1 = require("./environmentProvider");
40
+ // Cached coverage percentage for CodeLens display
41
+ let cachedCoveragePercentage = null;
42
+ let cachedCoverageTotal = 0;
43
+ let cachedCoverageCovered = 0;
44
+ /**
45
+ * Update the cached coverage for CodeLens display
46
+ */
47
+ function updateCodeLensCoverage(percentage, total, covered) {
48
+ cachedCoveragePercentage = percentage;
49
+ cachedCoverageTotal = total;
50
+ cachedCoverageCovered = covered;
51
+ }
52
+ /**
53
+ * Checks if a sequence declaration has only optional parameters (all have defaults).
54
+ * Returns true if no parameters or all parameters have defaults.
55
+ */
56
+ function canRunSequenceWithoutArgs(line) {
57
+ // Check if there are parameters
58
+ const parenMatch = line.match(/\(([^)]*)\)/);
59
+ if (!parenMatch) {
60
+ // No parameters - can run
61
+ return true;
62
+ }
63
+ const paramsStr = parenMatch[1].trim();
64
+ if (!paramsStr) {
65
+ // Empty parens - can run
66
+ return true;
67
+ }
68
+ // Split by comma (simple split, not handling quoted strings with commas)
69
+ const params = paramsStr.split(',');
70
+ // Check each parameter has a default (contains =)
71
+ for (const param of params) {
72
+ const trimmed = param.trim();
73
+ if (!trimmed)
74
+ continue;
75
+ // Must contain = for a default value
76
+ if (!trimmed.includes('=')) {
77
+ return false;
78
+ }
79
+ }
80
+ return true;
81
+ }
82
+ /**
83
+ * Checks for @data(...) or @theory(...) annotations directly above a sequence declaration.
84
+ * This allows CodeLens execution for parameterized sequences with required parameters.
85
+ */
86
+ function hasTheoryAnnotationsAbove(document, sequenceLine) {
87
+ const dataOrTheoryPattern = /^@(data|theory)\s*\(/;
88
+ const decoratorPattern = /^@/;
89
+ for (let i = sequenceLine - 1; i >= 0; i--) {
90
+ const line = document.lineAt(i).text.trim();
91
+ // Allow blank lines between decorators and sequence declaration
92
+ if (!line) {
93
+ continue;
94
+ }
95
+ // Stop as soon as the decorator block ends
96
+ if (!decoratorPattern.test(line)) {
97
+ break;
98
+ }
99
+ if (dataOrTheoryPattern.test(line)) {
100
+ return true;
101
+ }
102
+ }
103
+ return false;
104
+ }
105
+ class HttpCodeLensProvider {
106
+ _onDidChangeCodeLenses = new vscode.EventEmitter();
107
+ onDidChangeCodeLenses = this._onDidChangeCodeLenses.event;
108
+ constructor() {
109
+ // Refresh code lenses when environment changes
110
+ vscode.commands.registerCommand('norn.refreshCodeLenses', () => {
111
+ this._onDidChangeCodeLenses.fire();
112
+ });
113
+ }
114
+ /**
115
+ * Gets the environment display text for CodeLens
116
+ * Returns 'add' if no env file exists, environment name if it does
117
+ */
118
+ getEnvDisplay() {
119
+ const envFile = (0, environmentProvider_1.findEnvFile)();
120
+ if (!envFile) {
121
+ return { text: '+ Add env file', hasEnvFile: false };
122
+ }
123
+ const activeEnv = (0, environmentProvider_1.getActiveEnvironment)();
124
+ const availableEnvs = (0, environmentProvider_1.getAvailableEnvironments)();
125
+ if (availableEnvs.length === 0) {
126
+ return { text: 'env: (empty)', hasEnvFile: true };
127
+ }
128
+ return { text: activeEnv ? `env: ${activeEnv}` : 'env: none', hasEnvFile: true };
129
+ }
130
+ provideCodeLenses(document) {
131
+ const codeLenses = [];
132
+ const methodRegex = /^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+/;
133
+ // Match sequence (with optional test keyword) and optional parameters
134
+ const sequenceRegex = /^(?:test\s+)?sequence\s+([a-zA-Z_][a-zA-Z0-9_-]*)(?:\s*\([^)]*\))?$/;
135
+ // Match swagger statement with optional quotes around URL (only in .nornapi files)
136
+ const swaggerRegex = /^swagger\s+["']?(https?:\/\/[^\s"']+)["']?\s*$/;
137
+ // Match matchesSchema assertions: assert $1.body matchesSchema "./schema.json"
138
+ // Note: .+? is non-greedy to not consume matchesSchema
139
+ const matchesSchemaRegex = /^\s*assert\s+.+?\s+matchesSchema\s+["']?([^"']+)["']?/i;
140
+ const envInfo = this.getEnvDisplay();
141
+ const isNornApiFile = document.languageId === 'nornapi';
142
+ const isNornFile = document.languageId === 'norn';
143
+ // Track if we're inside a sequence
144
+ let insideSequence = false;
145
+ for (let i = 0; i < document.lineCount; i++) {
146
+ const line = document.lineAt(i);
147
+ const trimmedText = line.text.trim();
148
+ // Check for swagger statement (only in .nornapi files)
149
+ if (isNornApiFile) {
150
+ const swaggerMatch = trimmedText.match(swaggerRegex);
151
+ if (swaggerMatch) {
152
+ const range = new vscode.Range(i, 0, i, line.text.length);
153
+ codeLenses.push(new vscode.CodeLens(range, {
154
+ title: '$(debug-start) Import Endpoints',
155
+ command: 'norn.importSwagger',
156
+ arguments: [swaggerMatch[1], i],
157
+ tooltip: `Parse OpenAPI spec and generate endpoints`
158
+ }));
159
+ // Add Generate Schemas CodeLens
160
+ codeLenses.push(new vscode.CodeLens(range, {
161
+ title: '$(file-code) Generate Schemas',
162
+ command: 'norn.generateSchemasFromSwagger',
163
+ arguments: [swaggerMatch[1], document.uri.fsPath],
164
+ tooltip: 'Generate JSON Schema files from OpenAPI response definitions'
165
+ }));
166
+ // Add coverage CodeLens if we have coverage data
167
+ if (cachedCoveragePercentage !== null) {
168
+ const coverageIcon = cachedCoveragePercentage >= 80 ? '$(pass)' :
169
+ cachedCoveragePercentage >= 50 ? '$(warning)' : '$(error)';
170
+ codeLenses.push(new vscode.CodeLens(range, {
171
+ title: `${coverageIcon} Coverage: ${cachedCoveragePercentage}% (${cachedCoverageCovered}/${cachedCoverageTotal})`,
172
+ command: 'norn.showCoverage',
173
+ tooltip: `API Coverage: ${cachedCoverageCovered} of ${cachedCoverageTotal} response codes tested. Click to view details.`
174
+ }));
175
+ }
176
+ continue;
177
+ }
178
+ }
179
+ // Check for matchesSchema assertions (in .norn files)
180
+ if (isNornFile) {
181
+ const schemaMatch = trimmedText.match(matchesSchemaRegex);
182
+ if (schemaMatch) {
183
+ const schemaPath = schemaMatch[1];
184
+ const range = new vscode.Range(i, 0, i, line.text.length);
185
+ // Open Contract lens
186
+ codeLenses.push(new vscode.CodeLens(range, {
187
+ title: '$(file-code) Open Contract',
188
+ command: 'norn.openSchemaFile',
189
+ arguments: [schemaPath, document.uri.fsPath],
190
+ tooltip: `Open schema file: ${schemaPath}`
191
+ }));
192
+ // View Contract Report lens
193
+ codeLenses.push(new vscode.CodeLens(range, {
194
+ title: '$(checklist) View Contract',
195
+ command: 'norn.viewContractReport',
196
+ arguments: [i, document.uri.fsPath, schemaPath],
197
+ tooltip: 'Run validation and show contract comparison report'
198
+ }));
199
+ continue;
200
+ }
201
+ }
202
+ // Check for sequence start
203
+ const sequenceMatch = trimmedText.match(sequenceRegex);
204
+ if (sequenceMatch) {
205
+ insideSequence = true;
206
+ const range = new vscode.Range(i, 0, i, line.text.length);
207
+ // Show Run Sequence if parameters are all optional, or values are provided via @data/@theory.
208
+ const canRunWithoutArgs = canRunSequenceWithoutArgs(trimmedText);
209
+ const hasTheoryAnnotations = hasTheoryAnnotationsAbove(document, i);
210
+ if (canRunWithoutArgs || hasTheoryAnnotations) {
211
+ // Run Sequence lens
212
+ codeLenses.push(new vscode.CodeLens(range, {
213
+ title: '▶ Run Sequence',
214
+ command: 'norn.runSequence',
215
+ arguments: [i],
216
+ tooltip: `Run all requests in sequence "${sequenceMatch[1]}"`
217
+ }));
218
+ // Environment lens
219
+ codeLenses.push(new vscode.CodeLens(range, {
220
+ title: envInfo.text,
221
+ command: envInfo.hasEnvFile ? 'norn.selectEnvironmentAndRefresh' : 'norn.createEnvFile',
222
+ tooltip: envInfo.hasEnvFile ? 'Click to change environment' : 'Click to create .nornenv file'
223
+ }));
224
+ }
225
+ continue;
226
+ }
227
+ // Check for sequence end
228
+ if (trimmedText === 'end sequence') {
229
+ insideSequence = false;
230
+ continue;
231
+ }
232
+ // Only show "Send Request" for requests OUTSIDE of sequences
233
+ if (!insideSequence && methodRegex.test(line.text)) {
234
+ const range = new vscode.Range(i, 0, i, line.text.length);
235
+ // Send Request lens
236
+ codeLenses.push(new vscode.CodeLens(range, {
237
+ title: '▶ Send Request',
238
+ command: 'norn.sendRequest',
239
+ arguments: [i],
240
+ tooltip: 'Send this HTTP request'
241
+ }));
242
+ // Environment lens
243
+ codeLenses.push(new vscode.CodeLens(range, {
244
+ title: envInfo.text,
245
+ command: envInfo.hasEnvFile ? 'norn.selectEnvironmentAndRefresh' : 'norn.createEnvFile',
246
+ tooltip: envInfo.hasEnvFile ? 'Click to change environment' : 'Click to create .nornenv file'
247
+ }));
248
+ }
249
+ }
250
+ return codeLenses;
251
+ }
252
+ }
253
+ exports.HttpCodeLensProvider = HttpCodeLensProvider;
254
+ //# sourceMappingURL=codeLensProvider.js.map
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ /**
3
+ * Content provider for response comparison diff view
4
+ * Provides in-memory content for VS Code's built-in diff editor
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.CompareContentProvider = void 0;
41
+ exports.getCompareContentProvider = getCompareContentProvider;
42
+ exports.registerCompareContentProvider = registerCompareContentProvider;
43
+ const vscode = __importStar(require("vscode"));
44
+ class CompareContentProvider {
45
+ static scheme = 'norn-compare';
46
+ _content = new Map();
47
+ _onDidChange = new vscode.EventEmitter();
48
+ onDidChange = this._onDidChange.event;
49
+ /**
50
+ * Set content for a given path (e.g., 'baseline.json' or 'current.json')
51
+ */
52
+ setContent(path, content) {
53
+ this._content.set(path, content);
54
+ const uri = vscode.Uri.parse(`${CompareContentProvider.scheme}:${path}`);
55
+ this._onDidChange.fire(uri);
56
+ return uri;
57
+ }
58
+ /**
59
+ * Clear all stored content
60
+ */
61
+ clear() {
62
+ this._content.clear();
63
+ }
64
+ /**
65
+ * Provider implementation - returns content for the given URI
66
+ */
67
+ provideTextDocumentContent(uri) {
68
+ return this._content.get(uri.path) || '';
69
+ }
70
+ }
71
+ exports.CompareContentProvider = CompareContentProvider;
72
+ // Singleton instance for use across the extension
73
+ let _instance;
74
+ function getCompareContentProvider() {
75
+ if (!_instance) {
76
+ _instance = new CompareContentProvider();
77
+ }
78
+ return _instance;
79
+ }
80
+ function registerCompareContentProvider(context) {
81
+ const provider = getCompareContentProvider();
82
+ const registration = vscode.workspace.registerTextDocumentContentProvider(CompareContentProvider.scheme, provider);
83
+ context.subscriptions.push(registration);
84
+ }
85
+ //# sourceMappingURL=compareContentProvider.js.map