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.
- package/CHANGELOG.md +16 -0
- package/dist/cli.js +110 -10
- 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
|
-
|
|
13514
|
-
|
|
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
|
-
|
|
13522
|
-
|
|
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
|
|
13531
|
-
|
|
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
|
|
13536
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
5
|
+
"version": "1.2.3",
|
|
6
6
|
"publisher": "Norn-PeterKrustanov",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Peter Krastanov"
|