norn-cli 1.3.3 → 1.3.5
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 +22 -0
- package/dist/cli.js +108 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the "Norn" extension will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.3.5] - 2026-02-09
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **Endpoint Syntax Body Extraction**: Fixed form body not being sent with named requests using endpoint syntax
|
|
9
|
+
- `[PostFormWithEndpoint]` followed by `POST HttpBinPost Form` and body lines now works correctly
|
|
10
|
+
- Applies to standalone named requests (outside sequences) using `.nornapi` endpoints
|
|
11
|
+
- **Header Group Syntax Highlighting**: Fixed header group not showing green when on same line as URL
|
|
12
|
+
- `POST {{url}}/post Form` now correctly colors `Form` as header group
|
|
13
|
+
|
|
14
|
+
## [1.3.4] - 2026-02-09
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- **Header Groups with Raw URLs**: Header groups now work with regular URL requests, not just endpoint syntax
|
|
18
|
+
- `GET https://example.com/api Json` now correctly applies the Json header group
|
|
19
|
+
- Header groups on separate lines after URL also work
|
|
20
|
+
- Both extension and CLI support this fix
|
|
21
|
+
- Named requests (`[RequestName]`) also support header groups with raw URLs
|
|
22
|
+
- **CLI Named Requests with Endpoints**: Fixed body not being sent when using endpoint syntax
|
|
23
|
+
- `POST HttpBinPost Form` with body lines now correctly sends the form data
|
|
24
|
+
- **Syntax Highlighting for Form Parameters**: Added proper coloring for URL-encoded form body parameters
|
|
25
|
+
- `firstname=Alice` now shows key as parameter (purple), `=` as operator, value as string
|
|
26
|
+
|
|
5
27
|
## [1.3.3] - 2026-02-08
|
|
6
28
|
|
|
7
29
|
### Fixed
|
package/dist/cli.js
CHANGED
|
@@ -26686,6 +26686,64 @@ function parsePropertyAssignment(line2) {
|
|
|
26686
26686
|
|
|
26687
26687
|
// src/sequenceRunner.ts
|
|
26688
26688
|
init_assertionRunner();
|
|
26689
|
+
function applyHeaderGroupsToRequest(parsed, requestText, headerGroups, variables) {
|
|
26690
|
+
const lines = requestText.split("\n");
|
|
26691
|
+
const headerGroupNames = headerGroups.map((hg) => hg.name);
|
|
26692
|
+
const headerGroupHeaders = {};
|
|
26693
|
+
const foundGroups = [];
|
|
26694
|
+
for (const line2 of lines) {
|
|
26695
|
+
const trimmed = line2.trim();
|
|
26696
|
+
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("var ")) {
|
|
26697
|
+
continue;
|
|
26698
|
+
}
|
|
26699
|
+
const methodMatch = trimmed.match(/^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(.+)$/i);
|
|
26700
|
+
if (methodMatch) {
|
|
26701
|
+
const afterMethod = methodMatch[2];
|
|
26702
|
+
const tokens = afterMethod.split(/\s+/);
|
|
26703
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
26704
|
+
if (headerGroupNames.includes(tokens[i])) {
|
|
26705
|
+
foundGroups.push(tokens[i]);
|
|
26706
|
+
} else {
|
|
26707
|
+
break;
|
|
26708
|
+
}
|
|
26709
|
+
}
|
|
26710
|
+
continue;
|
|
26711
|
+
}
|
|
26712
|
+
if (/^[A-Za-z0-9\-_]+\s*:\s*.+$/.test(trimmed)) {
|
|
26713
|
+
continue;
|
|
26714
|
+
}
|
|
26715
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[") || trimmed.startsWith('"')) {
|
|
26716
|
+
continue;
|
|
26717
|
+
}
|
|
26718
|
+
const potentialGroups = trimmed.split(/\s+/);
|
|
26719
|
+
for (const groupName of potentialGroups) {
|
|
26720
|
+
if (headerGroupNames.includes(groupName)) {
|
|
26721
|
+
foundGroups.push(groupName);
|
|
26722
|
+
}
|
|
26723
|
+
}
|
|
26724
|
+
}
|
|
26725
|
+
for (const groupName of foundGroups) {
|
|
26726
|
+
const group = headerGroups.find((hg) => hg.name === groupName);
|
|
26727
|
+
if (group) {
|
|
26728
|
+
const resolvedHeaders = resolveHeaderValues(group, variables);
|
|
26729
|
+
Object.assign(headerGroupHeaders, resolvedHeaders);
|
|
26730
|
+
}
|
|
26731
|
+
}
|
|
26732
|
+
let modifiedUrl = parsed.url;
|
|
26733
|
+
for (const groupName of foundGroups) {
|
|
26734
|
+
const endPattern = new RegExp(`\\s+${groupName}$`);
|
|
26735
|
+
modifiedUrl = modifiedUrl.replace(endPattern, "");
|
|
26736
|
+
}
|
|
26737
|
+
modifiedUrl = modifiedUrl.trim();
|
|
26738
|
+
const result = {
|
|
26739
|
+
...parsed,
|
|
26740
|
+
url: modifiedUrl
|
|
26741
|
+
};
|
|
26742
|
+
if (Object.keys(headerGroupHeaders).length > 0) {
|
|
26743
|
+
result.headers = { ...headerGroupHeaders, ...parsed.headers };
|
|
26744
|
+
}
|
|
26745
|
+
return result;
|
|
26746
|
+
}
|
|
26689
26747
|
function isRunNamedRequestCommand(line2) {
|
|
26690
26748
|
const trimmed = line2.trim();
|
|
26691
26749
|
if (!trimmed.toLowerCase().startsWith("run ")) {
|
|
@@ -28721,10 +28779,16 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
|
|
|
28721
28779
|
} else {
|
|
28722
28780
|
parsed = parserHttpRequest(step.content, runtimeVariables);
|
|
28723
28781
|
requestDescription = `${parsed.method} ${parsed.url}`;
|
|
28782
|
+
if (apiDefinitions && apiDefinitions.headerGroups.length > 0) {
|
|
28783
|
+
parsed = applyHeaderGroupsToRequest(parsed, step.content, apiDefinitions.headerGroups, runtimeVariables);
|
|
28784
|
+
}
|
|
28724
28785
|
}
|
|
28725
28786
|
} else {
|
|
28726
28787
|
parsed = parserHttpRequest(step.content, runtimeVariables);
|
|
28727
28788
|
requestDescription = `${parsed.method} ${parsed.url}`;
|
|
28789
|
+
if (apiDefinitions && apiDefinitions.headerGroups.length > 0) {
|
|
28790
|
+
parsed = applyHeaderGroupsToRequest(parsed, step.content, apiDefinitions.headerGroups, runtimeVariables);
|
|
28791
|
+
}
|
|
28728
28792
|
}
|
|
28729
28793
|
const { retryCount, backoffMs } = extractRetryOptions(step.content);
|
|
28730
28794
|
const retryOpts = retryCount ?? parsed.retryCount ? {
|
|
@@ -30232,13 +30296,55 @@ async function runSingleRequest(fileContent, variables, cookieJar, apiDefinition
|
|
|
30232
30296
|
method: apiRequest.method,
|
|
30233
30297
|
url: resolvedPath,
|
|
30234
30298
|
headers: combinedHeaders,
|
|
30235
|
-
body:
|
|
30299
|
+
body: apiRequest.body
|
|
30236
30300
|
};
|
|
30237
30301
|
return await sendRequestWithJar(parsed2, cookieJar);
|
|
30238
30302
|
}
|
|
30239
30303
|
}
|
|
30240
30304
|
}
|
|
30241
|
-
|
|
30305
|
+
let parsed = parserHttpRequest(requestContent, variables);
|
|
30306
|
+
if (apiDefinitions && apiDefinitions.headerGroups.length > 0) {
|
|
30307
|
+
const headerGroupNames = apiDefinitions.headerGroups.map((hg) => hg.name);
|
|
30308
|
+
const foundGroups = [];
|
|
30309
|
+
for (const line2 of requestLines) {
|
|
30310
|
+
const trimmed = line2.trim();
|
|
30311
|
+
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("var ")) {
|
|
30312
|
+
continue;
|
|
30313
|
+
}
|
|
30314
|
+
const methodMatch = trimmed.match(/^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(.+)$/i);
|
|
30315
|
+
if (methodMatch) {
|
|
30316
|
+
const afterMethod = methodMatch[2];
|
|
30317
|
+
const tokens = afterMethod.split(/\s+/);
|
|
30318
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
30319
|
+
if (headerGroupNames.includes(tokens[i])) {
|
|
30320
|
+
foundGroups.push(tokens[i]);
|
|
30321
|
+
} else {
|
|
30322
|
+
break;
|
|
30323
|
+
}
|
|
30324
|
+
}
|
|
30325
|
+
continue;
|
|
30326
|
+
}
|
|
30327
|
+
if (/^[A-Za-z0-9\-_]+\s*:\s*.+$/.test(trimmed)) {
|
|
30328
|
+
continue;
|
|
30329
|
+
}
|
|
30330
|
+
const potentialGroups = trimmed.split(/\s+/);
|
|
30331
|
+
for (const groupName of potentialGroups) {
|
|
30332
|
+
if (headerGroupNames.includes(groupName)) {
|
|
30333
|
+
foundGroups.push(groupName);
|
|
30334
|
+
}
|
|
30335
|
+
}
|
|
30336
|
+
}
|
|
30337
|
+
for (const groupName of foundGroups) {
|
|
30338
|
+
const group = apiDefinitions.headerGroups.find((hg) => hg.name === groupName);
|
|
30339
|
+
if (group) {
|
|
30340
|
+
const resolvedHeaders = resolveHeaderValues(group, variables);
|
|
30341
|
+
parsed.headers = { ...resolvedHeaders, ...parsed.headers };
|
|
30342
|
+
}
|
|
30343
|
+
const endPattern = new RegExp(`\\s+${groupName}$`);
|
|
30344
|
+
parsed.url = parsed.url.replace(endPattern, "");
|
|
30345
|
+
}
|
|
30346
|
+
parsed.url = parsed.url.trim();
|
|
30347
|
+
}
|
|
30242
30348
|
return await sendRequestWithJar(parsed, cookieJar);
|
|
30243
30349
|
}
|
|
30244
30350
|
function discoverNornFiles(dirPath) {
|
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.3.
|
|
5
|
+
"version": "1.3.5",
|
|
6
6
|
"publisher": "Norn-PeterKrustanov",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Peter Krastanov"
|