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,554 @@
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.STARTER_CATALOG_ITEMS = void 0;
37
+ exports.getStarterCatalogItem = getStarterCatalogItem;
38
+ exports.createStarterCatalogItem = createStarterCatalogItem;
39
+ const path = __importStar(require("path"));
40
+ const vscode = __importStar(require("vscode"));
41
+ const simpleRequestsNorn = `# Simple named requests and a sequence that uses them.
42
+ # Run from VS Code or with the Norn CLI from this folder.
43
+
44
+ [GetTodo]
45
+ GET https://jsonplaceholder.typicode.com/todos/1
46
+
47
+ [CreatePost]
48
+ POST https://jsonplaceholder.typicode.com/posts
49
+ Content-Type: application/json
50
+ Accept: application/json
51
+ {
52
+ "title": "Norn starter post",
53
+ "body": "Created from a named request",
54
+ "userId": 1
55
+ }
56
+
57
+ test sequence SimpleRequestFlow
58
+ var todo = run GetTodo
59
+ assert todo.status == 200
60
+ assert todo.body.id == 1
61
+ assert todo.body.title isType string
62
+
63
+ var created = run CreatePost
64
+ assert created.status == 201
65
+ assert created.body.title == "Norn starter post"
66
+ assert created.body.userId == 1
67
+
68
+ print "Created post" | "id={{created.body.id}}, title={{created.body.title}}"
69
+ end sequence
70
+ `;
71
+ const scriptsJsonNorn = `# Script execution and JSON runtime editing.
72
+ # Run from VS Code or with the Norn CLI from this folder.
73
+
74
+ test sequence ScriptsAndJsonWorkflow
75
+ run bash ./scripts/echo.sh first second
76
+
77
+ var signature = run js ./scripts/sign.js "starter-payload"
78
+ assert signature isType string
79
+
80
+ var payload = run readJson ./data/payload.json
81
+ assert payload.title == "Original starter payload"
82
+
83
+ payload.title = "Updated by Norn"
84
+ payload.signature = signature
85
+ payload.userId = 42
86
+
87
+ POST https://httpbin.org/post
88
+ Content-Type: application/json
89
+ Accept: application/json
90
+
91
+ payload
92
+
93
+ assert $1.status == 200
94
+ assert $1.body.json.title == "Updated by Norn"
95
+ assert $1.body.json.signature == "{{signature}}"
96
+ assert $1.body.json.userId == 42
97
+
98
+ print "Payload" | "title={{$1.body.json.title}}, signature={{signature}}"
99
+ end sequence
100
+
101
+ # Run this sequence when PowerShell or pwsh is available on your machine.
102
+ sequence PowerShellDataExample
103
+ var users = run powershell ./scripts/user-data.ps1
104
+ assert users[0].id == 101
105
+ assert users[0].role == "admin"
106
+ return users
107
+ end sequence
108
+ `;
109
+ const echoScript = `#!/bin/bash
110
+ echo "Hello from bash"
111
+ echo "Arguments: $@"
112
+ echo "First: $1"
113
+ echo "Second: $2"
114
+ `;
115
+ const signScript = `const input = process.argv[2] || 'starter-payload';
116
+ const signature = Buffer.from(input + ':signed').toString('base64');
117
+ console.log(signature);
118
+ `;
119
+ const userDataPowerShell = `$users = @(
120
+ [PSCustomObject]@{ id = 101; name = "Ada"; role = "admin" }
121
+ [PSCustomObject]@{ id = 102; name = "Lin"; role = "tester" }
122
+ )
123
+
124
+ $users | ConvertTo-Json -Compress
125
+ `;
126
+ const payloadJson = `{
127
+ "title": "Original starter payload",
128
+ "body": "This JSON file is loaded, edited at runtime, and sent as a request body.",
129
+ "userId": 1,
130
+ "tags": ["starter", "json"]
131
+ }
132
+ `;
133
+ const sqlDemoNorn = `import "./queries.nornsql"
134
+
135
+ # Run from VS Code or with the Norn CLI from this folder.
136
+
137
+ test sequence SqlDemoFlow
138
+ var users = run sql ListDemoUsers
139
+ assert users[0].Email == "qa@example.com"
140
+ assert users[1].Id == 2
141
+
142
+ var user = run sql GetDemoUserByEmail("qa@example.com")
143
+ assert user[0].FirstName == "QA"
144
+
145
+ var createResult = run sql CreateDemoUser("new@example.com", "New", "User")
146
+ assert createResult.affectedRows == 1
147
+
148
+ print "SQL demo" | "first={{users[0].Name}}, created={{createResult.affectedRows}}"
149
+ end sequence
150
+ `;
151
+ const sqlDemoOperations = `connection demoDb
152
+
153
+ query ListDemoUsers
154
+ select Id, Email, Name
155
+ from DemoUsers
156
+ end query
157
+
158
+ query GetDemoUserByEmail(email)
159
+ select Id, Email, FirstName, LastName
160
+ from DemoUsers
161
+ where Email = :email
162
+ end query
163
+
164
+ command CreateDemoUser(email, firstName, lastName)
165
+ insert into DemoUsers (Email, FirstName, LastName)
166
+ values (:email, :firstName, :lastName)
167
+ end command
168
+ `;
169
+ const sqlDemoEnv = `var demoDb_server = starter-demo
170
+ var demoDb_database = StarterDemoDb
171
+ var demoDb_user = norn_demo
172
+ var demoDb_password = demo_password
173
+
174
+ [env:demo]
175
+ var demoDb_database = StarterDemoDb
176
+ `;
177
+ const sqlDemoConfig = `${JSON.stringify({
178
+ version: 1,
179
+ sql: {
180
+ connections: {
181
+ demoDb: {
182
+ adapter: 'starter-fake-sql-adapter',
183
+ profile: 'demoDb'
184
+ }
185
+ },
186
+ adapters: {
187
+ 'starter-fake-sql-adapter': {
188
+ command: ['node', './adapters/fake-sql-adapter.js']
189
+ }
190
+ }
191
+ }
192
+ }, null, '\t')}\n`;
193
+ const fakeSqlAdapter = `const chunks = [];
194
+
195
+ process.stdin.on('data', chunk => {
196
+ chunks.push(chunk);
197
+ });
198
+
199
+ process.stdin.on('end', () => {
200
+ try {
201
+ const request = JSON.parse(Buffer.concat(chunks).toString('utf8'));
202
+ const values = request.connection && request.connection.values ? request.connection.values : {};
203
+
204
+ if (!values.server || !values.database || !values.user || !values.password) {
205
+ process.stdout.write(JSON.stringify({
206
+ success: false,
207
+ error: 'Missing expected demoDb connection values'
208
+ }));
209
+ return;
210
+ }
211
+
212
+ switch (request.operation.name) {
213
+ case 'ListDemoUsers':
214
+ process.stdout.write(JSON.stringify({
215
+ success: true,
216
+ result: {
217
+ kind: 'rows',
218
+ rowCount: 2,
219
+ rows: [
220
+ { Id: 1, Email: 'qa@example.com', Name: 'QA User' },
221
+ { Id: 2, Email: 'second@example.com', Name: 'Second User' }
222
+ ]
223
+ }
224
+ }));
225
+ return;
226
+
227
+ case 'GetDemoUserByEmail':
228
+ process.stdout.write(JSON.stringify({
229
+ success: true,
230
+ result: {
231
+ kind: 'rows',
232
+ rowCount: 1,
233
+ rows: [
234
+ { Id: 1, Email: request.params.email, FirstName: 'QA', LastName: 'User' }
235
+ ]
236
+ }
237
+ }));
238
+ return;
239
+
240
+ case 'CreateDemoUser':
241
+ process.stdout.write(JSON.stringify({
242
+ success: true,
243
+ result: {
244
+ kind: 'exec',
245
+ affectedRows: 1
246
+ }
247
+ }));
248
+ return;
249
+
250
+ default:
251
+ process.stdout.write(JSON.stringify({
252
+ success: false,
253
+ error: 'Unknown fake SQL operation: ' + request.operation.name
254
+ }));
255
+ }
256
+ } catch (error) {
257
+ process.stdout.write(JSON.stringify({
258
+ success: false,
259
+ error: error instanceof Error ? error.message : String(error)
260
+ }));
261
+ }
262
+ });
263
+ `;
264
+ const realSqlNorn = `import "./sample.nornsql"
265
+
266
+ # Fill in .nornenv before running this file against your database.
267
+ # Example CLI run from this folder: norn real-db-starter.norn -e dev
268
+
269
+ test sequence VerifyRealDatabaseConnection
270
+ var activeUsers = run sql ListUsersByStatus("active")
271
+ assert activeUsers isType array
272
+ print "Active users" | activeUsers
273
+
274
+ var updateResult = run sql UpdateUserStatus(1, "active")
275
+ assert updateResult.affectedRows >= 0
276
+ end sequence
277
+ `;
278
+ const realSqlOperations = `# Starter SQL operations for Norn.
279
+ # Keep the connection name aligned with norn.config.json.
280
+
281
+ connection appDb
282
+
283
+ query ListUsersByStatus(status)
284
+ select Id, Email, Status
285
+ from Users
286
+ where Status = :status
287
+ end query
288
+
289
+ command UpdateUserStatus(id, status)
290
+ update Users
291
+ set Status = :status
292
+ where Id = :id
293
+ end command
294
+ `;
295
+ const realSqlEnv = `# Choose the connection string that matches your adapter and environment.
296
+ # Built-in adapters supported by Norn: postgres, sqlserver, sqlserver-windows.
297
+
298
+ connectionString appDb = postgresql://user:password@localhost:5432/app_db
299
+
300
+ [env:dev]
301
+ connectionString appDb = postgresql://dev_user:dev_password@localhost:5432/app_dev
302
+
303
+ # For production, prefer encrypted secrets once you have a real value.
304
+ # [env:prod]
305
+ # secret connectionString appDb = ENC[paste-encrypted-value-here]
306
+ `;
307
+ const realSqlConfig = `${JSON.stringify({
308
+ _comment: [
309
+ 'Change sql.connections.appDb.adapter to postgres, sqlserver, or sqlserver-windows.',
310
+ 'The profile name appDb maps to connectionString appDb = ... in .nornenv.',
311
+ 'sqlserver-windows is for Windows / Trusted authentication.'
312
+ ],
313
+ version: 1,
314
+ sql: {
315
+ connections: {
316
+ appDb: {
317
+ adapter: 'postgres',
318
+ profile: 'appDb'
319
+ }
320
+ }
321
+ }
322
+ }, null, '\t')}\n`;
323
+ const realSqlReadme = `# Real SQL Connection Starter
324
+
325
+ This starter is for wiring Norn to a real database.
326
+
327
+ Files:
328
+ - norn.config.json maps the appDb connection to a built-in SQL adapter.
329
+ - .nornenv stores connectionString appDb values for each environment.
330
+ - sample.nornsql contains reusable query and command definitions.
331
+ - real-db-starter.norn shows how to call those operations from a sequence.
332
+
333
+ Before running:
334
+ 1. Pick the adapter in norn.config.json: postgres, sqlserver, or sqlserver-windows.
335
+ 2. Replace the connectionString appDb values in .nornenv.
336
+ 3. Update sample.nornsql so table and column names match your database.
337
+ 4. Run the sample with the local CLI or from VS Code.
338
+ `;
339
+ const advancedEnv = `var primaryUserId = 1
340
+
341
+ [env:demo]
342
+ var baseUrl = https://jsonplaceholder.typicode.com
343
+ var postTitle = Norn advanced flow
344
+ `;
345
+ const advancedApi = `headers Json
346
+ Content-Type: application/json
347
+ Accept: application/json
348
+ end headers
349
+
350
+ endpoints
351
+ GetUser: GET {{baseUrl}}/users/{id}
352
+ GetUserPosts: GET {{baseUrl}}/users/{userId}/posts
353
+ CreatePost: POST {{baseUrl}}/posts
354
+ end endpoints
355
+ `;
356
+ const advancedHelpers = `import "./api.nornapi"
357
+
358
+ sequence LoadUser(userId = 1)
359
+ var userResponse = GET GetUser({{userId}}) Json
360
+ assert userResponse.status == 200
361
+ assert userResponse.body matchesSchema "./schemas/user.schema.json"
362
+ return userResponse.body
363
+ end sequence
364
+
365
+ sequence LoadPostsForUser(userId = 1)
366
+ var postsResponse = GET GetUserPosts({{userId}}) Json
367
+ assert postsResponse.status == 200
368
+ assert postsResponse.body isType array
369
+ assert postsResponse.body[0] matchesSchema "./schemas/post.schema.json"
370
+ return postsResponse.body
371
+ end sequence
372
+
373
+ sequence CreateWorkflowPost(userId = 1)
374
+ var createResponse = POST CreatePost Json
375
+ {
376
+ "title": "{{postTitle}}",
377
+ "body": "Created by an advanced Norn flow",
378
+ "userId": {{userId}}
379
+ }
380
+
381
+ assert createResponse.status == 201
382
+ assert createResponse.body matchesSchema "./schemas/post.schema.json"
383
+ return createResponse.body
384
+ end sequence
385
+ `;
386
+ const advancedFlow = `import "./helpers.norn"
387
+
388
+ # Run from VS Code or with the Norn CLI from this folder using the demo environment.
389
+
390
+ test sequence AdvancedEndToEndFlow
391
+ var user = run LoadUser({{primaryUserId}})
392
+ assert user.id == {{primaryUserId}}
393
+ assert user.email isType string
394
+
395
+ var posts = run LoadPostsForUser(user.id)
396
+ assert posts[0].userId == user.id
397
+ assert posts[0] matchesSchema "./schemas/post.schema.json"
398
+
399
+ var createdPost = run CreateWorkflowPost(user.id)
400
+ assert createdPost.userId == user.id
401
+ assert createdPost.title == "{{postTitle}}"
402
+ assert createdPost matchesSchema "./schemas/post.schema.json"
403
+
404
+ print "Advanced flow" | "user={{user.name}}, existingPosts={{posts[0].id}}, created={{createdPost.id}}"
405
+ end sequence
406
+ `;
407
+ const userSchema = `{
408
+ "$schema": "http://json-schema.org/draft-07/schema#",
409
+ "title": "JSONPlaceholder user response",
410
+ "type": "object",
411
+ "properties": {
412
+ "id": { "type": "integer" },
413
+ "name": { "type": "string" },
414
+ "username": { "type": "string" },
415
+ "email": { "type": "string" },
416
+ "address": { "type": "object" },
417
+ "phone": { "type": "string" },
418
+ "website": { "type": "string" },
419
+ "company": { "type": "object" }
420
+ },
421
+ "required": ["id", "name", "username", "email"],
422
+ "additionalProperties": true
423
+ }
424
+ `;
425
+ const postSchema = `{
426
+ "$schema": "http://json-schema.org/draft-07/schema#",
427
+ "title": "JSONPlaceholder post response",
428
+ "type": "object",
429
+ "properties": {
430
+ "userId": { "type": "integer" },
431
+ "id": { "type": "integer" },
432
+ "title": { "type": "string" },
433
+ "body": { "type": "string" }
434
+ },
435
+ "required": ["userId", "id", "title"],
436
+ "additionalProperties": true
437
+ }
438
+ `;
439
+ exports.STARTER_CATALOG_ITEMS = [
440
+ {
441
+ id: 'simple-requests',
442
+ label: 'Simple Requests and Sequences',
443
+ description: 'Named GET and POST requests called from one sequence.',
444
+ detail: 'No env file, just direct public URLs and assertions.',
445
+ folderName: 'norn-simple-requests',
446
+ openFile: 'requests.norn',
447
+ files: [
448
+ { path: 'requests.norn', content: simpleRequestsNorn }
449
+ ]
450
+ },
451
+ {
452
+ id: 'scripts-json',
453
+ label: 'Scripts and JSON Workflow',
454
+ description: 'Bash, JavaScript, PowerShell, readJson, and JSON body mutation.',
455
+ detail: 'Loads JSON, edits it at runtime, and sends it to httpbin.',
456
+ folderName: 'norn-scripts-json',
457
+ openFile: 'scripts-json.norn',
458
+ files: [
459
+ { path: 'scripts-json.norn', content: scriptsJsonNorn },
460
+ { path: 'scripts/echo.sh', content: echoScript },
461
+ { path: 'scripts/sign.js', content: signScript },
462
+ { path: 'scripts/user-data.ps1', content: userDataPowerShell },
463
+ { path: 'data/payload.json', content: payloadJson }
464
+ ]
465
+ },
466
+ {
467
+ id: 'sql-demo',
468
+ label: 'SQL Demo',
469
+ description: 'Runnable SQL-shaped flow with a local fake adapter.',
470
+ detail: 'Shows query and command results without needing a real database.',
471
+ folderName: 'norn-sql-demo',
472
+ openFile: 'sql-demo.norn',
473
+ files: [
474
+ { path: 'sql-demo.norn', content: sqlDemoNorn },
475
+ { path: 'queries.nornsql', content: sqlDemoOperations },
476
+ { path: '.nornenv', content: sqlDemoEnv },
477
+ { path: 'norn.config.json', content: sqlDemoConfig },
478
+ { path: 'adapters/fake-sql-adapter.js', content: fakeSqlAdapter }
479
+ ]
480
+ },
481
+ {
482
+ id: 'sql-connection',
483
+ label: 'Real SQL Connection Starter',
484
+ description: 'Config, env, and commented SQL files for a real database.',
485
+ detail: 'Fill in connection details for postgres, sqlserver, or sqlserver-windows.',
486
+ folderName: 'norn-sql-connection-starter',
487
+ openFile: 'real-db-starter.norn',
488
+ files: [
489
+ { path: 'real-db-starter.norn', content: realSqlNorn },
490
+ { path: 'sample.nornsql', content: realSqlOperations },
491
+ { path: '.nornenv', content: realSqlEnv },
492
+ { path: 'norn.config.json', content: realSqlConfig },
493
+ { path: 'README.md', content: realSqlReadme }
494
+ ]
495
+ },
496
+ {
497
+ id: 'advanced-flow',
498
+ label: 'Advanced End-to-End Flow',
499
+ description: 'Env, API definitions, helper sequences, tests, and contracts.',
500
+ detail: 'A complete flow with sequence composition and schema validation.',
501
+ folderName: 'norn-advanced-flow',
502
+ openFile: 'advanced-flow.norn',
503
+ files: [
504
+ { path: 'advanced-flow.norn', content: advancedFlow },
505
+ { path: 'helpers.norn', content: advancedHelpers },
506
+ { path: 'api.nornapi', content: advancedApi },
507
+ { path: '.nornenv', content: advancedEnv },
508
+ { path: 'schemas/user.schema.json', content: userSchema },
509
+ { path: 'schemas/post.schema.json', content: postSchema }
510
+ ]
511
+ }
512
+ ];
513
+ function getStarterCatalogItem(id) {
514
+ return exports.STARTER_CATALOG_ITEMS.find((starterItem) => starterItem.id === id);
515
+ }
516
+ async function createStarterCatalogItem(parentFolderUri, starterItem) {
517
+ const folderUri = await resolveUniqueFolderUri(parentFolderUri, starterItem.folderName);
518
+ await vscode.workspace.fs.createDirectory(folderUri);
519
+ const createdFiles = [];
520
+ for (const starterFile of starterItem.files) {
521
+ const targetUri = vscode.Uri.joinPath(folderUri, ...starterFile.path.split('/'));
522
+ const directoryName = path.posix.dirname(starterFile.path);
523
+ if (directoryName !== '.') {
524
+ await vscode.workspace.fs.createDirectory(vscode.Uri.joinPath(folderUri, ...directoryName.split('/')));
525
+ }
526
+ await vscode.workspace.fs.writeFile(targetUri, Buffer.from(starterFile.content, 'utf8'));
527
+ createdFiles.push(starterFile.path);
528
+ }
529
+ return {
530
+ item: starterItem,
531
+ folderUri,
532
+ openFileUri: vscode.Uri.joinPath(folderUri, ...starterItem.openFile.split('/')),
533
+ createdFiles
534
+ };
535
+ }
536
+ async function resolveUniqueFolderUri(parentFolderUri, baseFolderName) {
537
+ let candidateName = baseFolderName;
538
+ let suffix = 2;
539
+ while (await uriExists(vscode.Uri.joinPath(parentFolderUri, candidateName))) {
540
+ candidateName = `${baseFolderName}-${suffix}`;
541
+ suffix += 1;
542
+ }
543
+ return vscode.Uri.joinPath(parentFolderUri, candidateName);
544
+ }
545
+ async function uriExists(uri) {
546
+ try {
547
+ await vscode.workspace.fs.stat(uri);
548
+ return true;
549
+ }
550
+ catch {
551
+ return false;
552
+ }
553
+ }
554
+ //# sourceMappingURL=starterCatalog.js.map
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stripInlineComment = stripInlineComment;
4
+ function stripInlineComment(line) {
5
+ let inSingleQuote = false;
6
+ let inDoubleQuote = false;
7
+ for (let index = 0; index < line.length; index++) {
8
+ const char = line[index];
9
+ const previousChar = index > 0 ? line[index - 1] : '';
10
+ if (previousChar === '\\') {
11
+ continue;
12
+ }
13
+ if (char === '"' && !inSingleQuote) {
14
+ inDoubleQuote = !inDoubleQuote;
15
+ }
16
+ else if (char === "'" && !inDoubleQuote) {
17
+ inSingleQuote = !inSingleQuote;
18
+ }
19
+ else if (char === '#' && !inSingleQuote && !inDoubleQuote) {
20
+ return line.substring(0, index).trimEnd();
21
+ }
22
+ }
23
+ return line;
24
+ }
25
+ //# sourceMappingURL=stringUtils.js.map
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ /**
3
+ * Swagger Body IntelliSense Cache
4
+ *
5
+ * Persists request-body schemas extracted from Swagger/OpenAPI specs.
6
+ * The cache is used by completionProvider to provide endpoint request-body
7
+ * templates and inline key suggestions without fetching remote specs.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.loadSwaggerBodyCache = loadSwaggerBodyCache;
44
+ exports.getCachedRequestBodySchemasForUrl = getCachedRequestBodySchemasForUrl;
45
+ exports.saveRequestBodySchemasForUrl = saveRequestBodySchemasForUrl;
46
+ exports.invalidateSwaggerBodyCache = invalidateSwaggerBodyCache;
47
+ const vscode = __importStar(require("vscode"));
48
+ const cacheDir_1 = require("./cacheDir");
49
+ const CACHE_VERSION = 1;
50
+ const CACHE_FILE = 'swagger-body-intellisense.json';
51
+ function getWorkspaceRoot() {
52
+ const workspaceFolders = vscode.workspace.workspaceFolders;
53
+ if (workspaceFolders && workspaceFolders.length > 0) {
54
+ return workspaceFolders[0].uri.fsPath;
55
+ }
56
+ return undefined;
57
+ }
58
+ function getCachePath() {
59
+ const root = getWorkspaceRoot();
60
+ if (!root) {
61
+ return undefined;
62
+ }
63
+ return (0, cacheDir_1.getNornCacheFilePath)(root, CACHE_FILE);
64
+ }
65
+ function ensureCacheDir() {
66
+ const root = getWorkspaceRoot();
67
+ if (!root) {
68
+ return false;
69
+ }
70
+ return !!(0, cacheDir_1.ensureNornCacheDir)(root);
71
+ }
72
+ function loadSwaggerBodyCache() {
73
+ return (0, cacheDir_1.loadVersionedJsonCache)({
74
+ cachePath: getCachePath(),
75
+ version: CACHE_VERSION,
76
+ createDefault: () => ({ version: CACHE_VERSION, urls: {} }),
77
+ isValid: cache => typeof cache.urls === 'object' && cache.urls !== null
78
+ });
79
+ }
80
+ function saveSwaggerBodyCache(cache) {
81
+ return (0, cacheDir_1.saveVersionedJsonCache)(getCachePath(), cache, ensureCacheDir);
82
+ }
83
+ function getCachedRequestBodySchemasForUrl(url) {
84
+ const cache = loadSwaggerBodyCache();
85
+ return cache.urls[url];
86
+ }
87
+ function saveRequestBodySchemasForUrl(url, baseUrl, schemas) {
88
+ const cache = loadSwaggerBodyCache();
89
+ cache.urls[url] = {
90
+ baseUrl,
91
+ fetchedAt: new Date().toISOString(),
92
+ schemas: schemas.map(schema => ({
93
+ operationId: schema.operationId,
94
+ method: schema.method.toUpperCase(),
95
+ path: schema.path,
96
+ required: Array.isArray(schema.required) ? schema.required : [],
97
+ schema: schema.schema
98
+ }))
99
+ };
100
+ saveSwaggerBodyCache(cache);
101
+ }
102
+ function invalidateSwaggerBodyCache(url) {
103
+ if (url) {
104
+ const cache = loadSwaggerBodyCache();
105
+ delete cache.urls[url];
106
+ saveSwaggerBodyCache(cache);
107
+ return;
108
+ }
109
+ saveSwaggerBodyCache({
110
+ version: CACHE_VERSION,
111
+ urls: {}
112
+ });
113
+ }
114
+ //# sourceMappingURL=swaggerBodyIntellisenseCache.js.map