norn-cli 1.2.2 → 1.2.3

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 (3) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cli.js +110 -10
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  All notable changes to the "Norn" extension will be documented in this file.
4
4
 
5
+ ## [1.2.3] - 2026-02-07
6
+
7
+ ### Added
8
+ - **Duplicate import detection**: Errors shown when importing files with duplicate definitions
9
+ - Header groups and endpoints from `.nornapi` files
10
+ - Named requests and sequences from `.norn` files
11
+ - Blocks execution in CLI, VS Code, and Test Explorer
12
+ - Red squiggly on import line with descriptive error message
13
+
14
+ ### Fixed
15
+ - **.nornenv validation**: `secret var = value` now shows error (use `secret name = value` instead)
16
+ - Syntax highlighting marks invalid pattern in red
17
+ - Diagnostic message explains correct usage
18
+ - **IntelliSense context**: Script types (`bash`, `powershell`, `js`, `readJson`) only appear after `run` keyword
19
+ - **var keyword highlighting**: `var` keyword stays colored while typing variable name
20
+
5
21
  ## [1.2.2] - 2026-02-05
6
22
 
7
23
  ### Added
package/dist/cli.js CHANGED
@@ -13493,6 +13493,10 @@ async function resolveImports(text, baseDir, readFile2, alreadyImported = /* @__
13493
13493
  const resolvedPaths = [];
13494
13494
  const headerGroups = [];
13495
13495
  const endpoints = [];
13496
+ const headerGroupSources = /* @__PURE__ */ new Map();
13497
+ const endpointSources = /* @__PURE__ */ new Map();
13498
+ const namedRequestSources = /* @__PURE__ */ new Map();
13499
+ const sequenceSources = /* @__PURE__ */ new Map();
13496
13500
  for (const imp of imports) {
13497
13501
  const path4 = await import("path");
13498
13502
  const absolutePath = path4.resolve(baseDir, imp.path);
@@ -13510,16 +13514,64 @@ async function resolveImports(text, baseDir, readFile2, alreadyImported = /* @__
13510
13514
  resolvedPaths.push(absolutePath);
13511
13515
  if (imp.path.endsWith(".nornapi")) {
13512
13516
  const apiDef = parseNornApiFile(content);
13513
- headerGroups.push(...apiDef.headerGroups);
13514
- endpoints.push(...apiDef.endpoints);
13517
+ for (const group of apiDef.headerGroups) {
13518
+ const existingSource = headerGroupSources.get(group.name);
13519
+ if (existingSource) {
13520
+ errors.push({
13521
+ path: imp.path,
13522
+ error: `Duplicate header group '${group.name}': already defined in '${existingSource}'`,
13523
+ lineNumber: imp.lineNumber
13524
+ });
13525
+ } else {
13526
+ headerGroupSources.set(group.name, imp.path);
13527
+ headerGroups.push(group);
13528
+ }
13529
+ }
13530
+ for (const endpoint of apiDef.endpoints) {
13531
+ const existingSource = endpointSources.get(endpoint.name);
13532
+ if (existingSource) {
13533
+ errors.push({
13534
+ path: imp.path,
13535
+ error: `Duplicate endpoint '${endpoint.name}': already defined in '${existingSource}'`,
13536
+ lineNumber: imp.lineNumber
13537
+ });
13538
+ } else {
13539
+ endpointSources.set(endpoint.name, imp.path);
13540
+ endpoints.push(endpoint);
13541
+ }
13542
+ }
13515
13543
  continue;
13516
13544
  }
13517
13545
  const importDir = path4.dirname(absolutePath);
13518
13546
  const nestedResult = await resolveImports(content, importDir, readFile2, alreadyImported);
13519
13547
  errors.push(...nestedResult.errors);
13520
13548
  resolvedPaths.push(...nestedResult.resolvedPaths);
13521
- headerGroups.push(...nestedResult.headerGroups);
13522
- endpoints.push(...nestedResult.endpoints);
13549
+ for (const group of nestedResult.headerGroups) {
13550
+ const existingSource = headerGroupSources.get(group.name);
13551
+ if (existingSource) {
13552
+ errors.push({
13553
+ path: imp.path,
13554
+ error: `Duplicate header group '${group.name}': already defined in '${existingSource}'`,
13555
+ lineNumber: imp.lineNumber
13556
+ });
13557
+ } else {
13558
+ headerGroupSources.set(group.name, imp.path);
13559
+ headerGroups.push(group);
13560
+ }
13561
+ }
13562
+ for (const endpoint of nestedResult.endpoints) {
13563
+ const existingSource = endpointSources.get(endpoint.name);
13564
+ if (existingSource) {
13565
+ errors.push({
13566
+ path: imp.path,
13567
+ error: `Duplicate endpoint '${endpoint.name}': already defined in '${existingSource}'`,
13568
+ lineNumber: imp.lineNumber
13569
+ });
13570
+ } else {
13571
+ endpointSources.set(endpoint.name, imp.path);
13572
+ endpoints.push(endpoint);
13573
+ }
13574
+ }
13523
13575
  if (nestedResult.importedContent) {
13524
13576
  importedContents.push(nestedResult.importedContent);
13525
13577
  }
@@ -13527,15 +13579,37 @@ async function resolveImports(text, baseDir, readFile2, alreadyImported = /* @__
13527
13579
  const importedNamedRequests = extractNamedRequests(content);
13528
13580
  const importedSequences = extractSequencesFromText(content);
13529
13581
  for (const req of importedNamedRequests) {
13530
- const resolvedContent = substituteVariables(req.content, importedVariables);
13531
- importedContents.push(`[${req.name}]
13582
+ const lowerName = req.name.toLowerCase();
13583
+ const existingSource = namedRequestSources.get(lowerName);
13584
+ if (existingSource) {
13585
+ errors.push({
13586
+ path: imp.path,
13587
+ error: `Duplicate named request '${req.name}': already defined in '${existingSource}'`,
13588
+ lineNumber: imp.lineNumber
13589
+ });
13590
+ } else {
13591
+ namedRequestSources.set(lowerName, imp.path);
13592
+ const resolvedContent = substituteVariables(req.content, importedVariables);
13593
+ importedContents.push(`[${req.name}]
13532
13594
  ${resolvedContent}`);
13595
+ }
13533
13596
  }
13534
13597
  for (const seq of importedSequences) {
13535
- const resolvedContent = substituteVariables(seq.content, importedVariables);
13536
- importedContents.push(`sequence ${seq.name}
13598
+ const lowerName = seq.name.toLowerCase();
13599
+ const existingSource = sequenceSources.get(lowerName);
13600
+ if (existingSource) {
13601
+ errors.push({
13602
+ path: imp.path,
13603
+ error: `Duplicate sequence '${seq.name}': already defined in '${existingSource}'`,
13604
+ lineNumber: imp.lineNumber
13605
+ });
13606
+ } else {
13607
+ sequenceSources.set(lowerName, imp.path);
13608
+ const resolvedContent = substituteVariables(seq.content, importedVariables);
13609
+ importedContents.push(`sequence ${seq.name}
13537
13610
  ${resolvedContent}
13538
13611
  end sequence`);
13612
+ }
13539
13613
  }
13540
13614
  } catch (error) {
13541
13615
  errors.push({
@@ -23403,9 +23477,22 @@ async function main() {
23403
23477
  workingDir,
23404
23478
  async (importPath) => fsPromises.readFile(importPath, "utf-8")
23405
23479
  );
23406
- for (const err of importResult.errors) {
23480
+ const duplicateErrors = importResult.errors.filter(
23481
+ (err) => err.error.includes("Duplicate header group") || err.error.includes("Duplicate endpoint") || err.error.includes("Duplicate named request") || err.error.includes("Duplicate sequence")
23482
+ );
23483
+ const otherErrors = importResult.errors.filter(
23484
+ (err) => !err.error.includes("Duplicate header group") && !err.error.includes("Duplicate endpoint") && !err.error.includes("Duplicate named request") && !err.error.includes("Duplicate sequence")
23485
+ );
23486
+ for (const err of otherErrors) {
23407
23487
  console.error(colors.warning(`Import warning: ${err.path} - ${err.error}`));
23408
23488
  }
23489
+ if (duplicateErrors.length > 0) {
23490
+ console.error(colors.error("Cannot execute - duplicate definitions found:"));
23491
+ for (const err of duplicateErrors) {
23492
+ console.error(colors.error(` ${err.path}: ${err.error}`));
23493
+ }
23494
+ process.exit(1);
23495
+ }
23409
23496
  const fileContentWithImports = importResult.importedContent ? `${importResult.importedContent}
23410
23497
 
23411
23498
  ${fileContent}` : fileContent;
@@ -23512,9 +23599,22 @@ ${fileContent}` : fileContent;
23512
23599
  workingDir,
23513
23600
  async (importPath) => fsPromises.readFile(importPath, "utf-8")
23514
23601
  );
23515
- for (const err of importResult.errors) {
23602
+ const duplicateErrors2 = importResult.errors.filter(
23603
+ (err) => err.error.includes("Duplicate header group") || err.error.includes("Duplicate endpoint") || err.error.includes("Duplicate named request") || err.error.includes("Duplicate sequence")
23604
+ );
23605
+ const otherErrors2 = importResult.errors.filter(
23606
+ (err) => !err.error.includes("Duplicate header group") && !err.error.includes("Duplicate endpoint") && !err.error.includes("Duplicate named request") && !err.error.includes("Duplicate sequence")
23607
+ );
23608
+ for (const err of otherErrors2) {
23516
23609
  console.error(colors.warning(`Import warning: ${err.path} - ${err.error}`));
23517
23610
  }
23611
+ if (duplicateErrors2.length > 0) {
23612
+ console.error(colors.error("Cannot execute - duplicate definitions found:"));
23613
+ for (const err of duplicateErrors2) {
23614
+ console.error(colors.error(` ${err.path}: ${err.error}`));
23615
+ }
23616
+ process.exit(1);
23617
+ }
23518
23618
  const fileContentWithImports = importResult.importedContent ? `${importResult.importedContent}
23519
23619
 
23520
23620
  ${fileContent}` : fileContent;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "norn-cli",
3
3
  "displayName": "Norn - REST Client",
4
4
  "description": "A powerful REST client for making HTTP requests with sequences, variables, scripts, and cookie support",
5
- "version": "1.2.2",
5
+ "version": "1.2.3",
6
6
  "publisher": "Norn-PeterKrustanov",
7
7
  "author": {
8
8
  "name": "Peter Krastanov"