norn-cli 1.3.7 → 1.3.9

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 +20 -0
  2. package/dist/cli.js +103 -20
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to the "Norn" extension will be documented in this file.
4
4
 
5
+ ## [1.3.9] - 2026-02-09
6
+
7
+ ### Added
8
+ - **`pwsh` Script Type**: Added `pwsh` as an alias for `powershell` in script commands
9
+ - `var x = run pwsh "./script.ps1"` now works alongside `run powershell`
10
+ - **Bare Variable Support in Property Assignments**: Variables can be assigned without `{{}}` syntax
11
+ - `payload.userId = dynamicUserId` now works (previously required `{{dynamicUserId}}`)
12
+ - **Request Body in Verbose Output**: CLI `-v` flag now shows the actual request body and headers sent
13
+ - Helps debug payload issues by showing exactly what was transmitted
14
+
15
+ ### Fixed
16
+ - **Script Output Capture**: Fixed variable shadowing bug that could affect JSON parsing of script output
17
+
18
+ ## [1.3.8] - 2026-02-09
19
+
20
+ ### Fixed
21
+ - **Named Requests with Endpoint Syntax**: Fixed `run RequestName` failing when the named request uses `.nornapi` endpoint syntax
22
+ - `[PostFormWithEndpoint]` with `POST HttpBinPost Form` now works correctly when invoked via `run PostFormWithEndpoint`
23
+ - Endpoint is resolved and headers/body are properly applied
24
+
5
25
  ## [1.3.7] - 2026-02-09
6
26
 
7
27
  ### Fixed
package/dist/cli.js CHANGED
@@ -26192,6 +26192,8 @@ async function sendRequestWithJar(request, jar, retryOptions) {
26192
26192
  let currentMethod = request.method;
26193
26193
  let currentBody = request.body;
26194
26194
  let finalResponse = null;
26195
+ let sentRequestBody = void 0;
26196
+ let sentRequestHeaders = {};
26195
26197
  try {
26196
26198
  while (redirectCount <= maxRedirects) {
26197
26199
  const existingCookies = await jar.getCookies(currentUrl);
@@ -26238,6 +26240,8 @@ async function sendRequestWithJar(request, jar, retryOptions) {
26238
26240
  }
26239
26241
  }
26240
26242
  }
26243
+ sentRequestBody = data;
26244
+ sentRequestHeaders = { ...headers };
26241
26245
  const response = await axios_default({
26242
26246
  method: currentMethod,
26243
26247
  url: currentUrl,
@@ -26290,7 +26294,9 @@ async function sendRequestWithJar(request, jar, retryOptions) {
26290
26294
  headers: finalResponse.headers,
26291
26295
  body: finalResponse.data,
26292
26296
  duration: Date.now() - startTime,
26293
- cookies
26297
+ cookies,
26298
+ requestBody: sentRequestBody,
26299
+ requestHeaders: sentRequestHeaders
26294
26300
  };
26295
26301
  if (attemptsMade > 1 || totalAttempts > 1) {
26296
26302
  result.retryInfo = {
@@ -26453,23 +26459,25 @@ function isPwshAvailable() {
26453
26459
  }
26454
26460
  function parseRunCommand(line2) {
26455
26461
  const trimmed = line2.trim();
26456
- const captureMatch = trimmed.match(/^var\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*run\s+(bash|powershell|js)\s+(.+)$/i);
26462
+ const captureMatch = trimmed.match(/^var\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*run\s+(bash|powershell|pwsh|js)\s+(.+)$/i);
26457
26463
  if (captureMatch) {
26458
26464
  const [, varName, type, rest] = captureMatch;
26459
26465
  const { scriptPath, args } = parsePathAndArgs(rest);
26466
+ const normalizedType = type.toLowerCase() === "pwsh" ? "powershell" : type.toLowerCase();
26460
26467
  return {
26461
- type: type.toLowerCase(),
26468
+ type: normalizedType,
26462
26469
  scriptPath,
26463
26470
  args,
26464
26471
  captureAs: varName
26465
26472
  };
26466
26473
  }
26467
- const runMatch = trimmed.match(/^run\s+(bash|powershell|js)\s+(.+)$/i);
26474
+ const runMatch = trimmed.match(/^run\s+(bash|powershell|pwsh|js)\s+(.+)$/i);
26468
26475
  if (runMatch) {
26469
26476
  const [, type, rest] = runMatch;
26470
26477
  const { scriptPath, args } = parsePathAndArgs(rest);
26478
+ const normalizedType = type.toLowerCase() === "pwsh" ? "powershell" : type.toLowerCase();
26471
26479
  return {
26472
- type: type.toLowerCase(),
26480
+ type: normalizedType,
26473
26481
  scriptPath,
26474
26482
  args
26475
26483
  };
@@ -26507,7 +26515,7 @@ function parsePathAndArgs(rest) {
26507
26515
  }
26508
26516
  function isRunCommand(line2) {
26509
26517
  const trimmed = line2.trim();
26510
- return /^(var\s+[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*)?run\s+(bash|powershell|js)\s+/i.test(trimmed);
26518
+ return /^(var\s+[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*)?run\s+(bash|powershell|pwsh|js)\s+/i.test(trimmed);
26511
26519
  }
26512
26520
  async function runScript(type, scriptPath, args, workingDir, variables = {}, captureVar) {
26513
26521
  const startTime = Date.now();
@@ -28021,9 +28029,7 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
28021
28029
  continue;
28022
28030
  }
28023
28031
  if (step.type === "propAssign") {
28024
- const bareResolved = resolveBareVariables(step.content, runtimeVariables);
28025
- const substitutedContent = substituteVariables(bareResolved, runtimeVariables);
28026
- const parsed = parsePropertyAssignment(substitutedContent);
28032
+ const parsed = parsePropertyAssignment(step.content);
28027
28033
  if (!parsed) {
28028
28034
  errors.push(`Step ${stepIdx + 1}: Invalid property assignment: ${step.content}`);
28029
28035
  return {
@@ -28066,9 +28072,11 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
28066
28072
  duration: Date.now() - startTime
28067
28073
  };
28068
28074
  }
28069
- let newValue = parsed.value;
28075
+ const bareResolvedValue = resolveBareVariables(parsed.value, runtimeVariables);
28076
+ const resolvedValue = substituteVariables(bareResolvedValue, runtimeVariables);
28077
+ let newValue = resolvedValue;
28070
28078
  try {
28071
- newValue = JSON.parse(parsed.value);
28079
+ newValue = JSON.parse(resolvedValue);
28072
28080
  } catch {
28073
28081
  }
28074
28082
  const success = setNestedValue(jsonObj, parsed.propertyPath, newValue);
@@ -28305,9 +28313,9 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
28305
28313
  if (parsed.captureAs) {
28306
28314
  let outputValue = result.output;
28307
28315
  try {
28308
- const parsed2 = JSON.parse(result.output);
28309
- if (typeof parsed2 === "object" && parsed2 !== null) {
28310
- outputValue = parsed2;
28316
+ const jsonParsed = JSON.parse(result.output);
28317
+ if (typeof jsonParsed === "object" && jsonParsed !== null) {
28318
+ outputValue = jsonParsed;
28311
28319
  }
28312
28320
  } catch {
28313
28321
  }
@@ -28462,9 +28470,68 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
28462
28470
  let requestUrl = "";
28463
28471
  let requestMethod = "";
28464
28472
  try {
28465
- let requestParsed = parserHttpRequest(namedRequest.content, runtimeVariables);
28466
- if (apiDefinitions && apiDefinitions.headerGroups.length > 0) {
28467
- requestParsed = applyHeaderGroupsToRequest(requestParsed, namedRequest.content, apiDefinitions.headerGroups, runtimeVariables);
28473
+ let requestParsed;
28474
+ if (apiDefinitions && apiDefinitions.endpoints.length > 0 && isApiRequestLine(namedRequest.content, apiDefinitions.endpoints)) {
28475
+ const apiRequest = parseApiRequest(
28476
+ namedRequest.content,
28477
+ apiDefinitions.endpoints,
28478
+ apiDefinitions.headerGroups
28479
+ );
28480
+ if (apiRequest) {
28481
+ const endpoint = getEndpoint(
28482
+ { headerGroups: apiDefinitions.headerGroups, endpoints: apiDefinitions.endpoints },
28483
+ apiRequest.endpointName
28484
+ );
28485
+ if (endpoint) {
28486
+ let resolvedPath = endpoint.path;
28487
+ resolvedPath = resolvedPath.replace(/\{\{([a-zA-Z_][a-zA-Z0-9_]*)\}\}/g, (_, varName) => {
28488
+ return runtimeVariables[varName] !== void 0 ? String(runtimeVariables[varName]) : `{{${varName}}}`;
28489
+ });
28490
+ for (const [paramName, paramValue] of Object.entries(apiRequest.params)) {
28491
+ let resolvedValue = paramValue;
28492
+ if (runtimeVariables[paramValue] !== void 0) {
28493
+ resolvedValue = String(runtimeVariables[paramValue]);
28494
+ } else if (paramValue.startsWith("{{") && paramValue.endsWith("}}")) {
28495
+ const varName = paramValue.slice(2, -2);
28496
+ if (runtimeVariables[varName] !== void 0) {
28497
+ resolvedValue = String(runtimeVariables[varName]);
28498
+ }
28499
+ }
28500
+ resolvedPath = resolvedPath.replace(`{${paramName}}`, resolvedValue);
28501
+ }
28502
+ const combinedHeaders = {};
28503
+ for (const groupName of apiRequest.headerGroupNames) {
28504
+ const group = getHeaderGroup(apiDefinitions, groupName);
28505
+ if (group) {
28506
+ const resolvedHeaders = resolveHeaderValues(group, runtimeVariables);
28507
+ Object.assign(combinedHeaders, resolvedHeaders);
28508
+ }
28509
+ }
28510
+ for (const [headerName, headerValue] of Object.entries(apiRequest.inlineHeaders)) {
28511
+ let resolved = headerValue;
28512
+ resolved = resolved.replace(/\{\{([a-zA-Z_][a-zA-Z0-9_]*)\}\}/g, (_, varName) => {
28513
+ return runtimeVariables[varName] !== void 0 ? String(runtimeVariables[varName]) : `{{${varName}}}`;
28514
+ });
28515
+ combinedHeaders[headerName] = resolved;
28516
+ }
28517
+ const bodyParsed = parserHttpRequest(namedRequest.content, runtimeVariables);
28518
+ requestParsed = {
28519
+ method: apiRequest.method,
28520
+ url: resolvedPath,
28521
+ headers: combinedHeaders,
28522
+ body: bodyParsed.body
28523
+ };
28524
+ } else {
28525
+ throw new Error(`Unknown endpoint: ${apiRequest.endpointName}`);
28526
+ }
28527
+ } else {
28528
+ requestParsed = parserHttpRequest(namedRequest.content, runtimeVariables);
28529
+ }
28530
+ } else {
28531
+ requestParsed = parserHttpRequest(namedRequest.content, runtimeVariables);
28532
+ if (apiDefinitions && apiDefinitions.headerGroups.length > 0) {
28533
+ requestParsed = applyHeaderGroupsToRequest(requestParsed, namedRequest.content, apiDefinitions.headerGroups, runtimeVariables);
28534
+ }
28468
28535
  }
28469
28536
  requestUrl = requestParsed.url;
28470
28537
  requestMethod = requestParsed.method;
@@ -28798,6 +28865,20 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
28798
28865
  if (apiDefinitions && apiDefinitions.headerGroups.length > 0) {
28799
28866
  parsed = applyHeaderGroupsToRequest(parsed, step.content, apiDefinitions.headerGroups, runtimeVariables);
28800
28867
  }
28868
+ if (parsed.body) {
28869
+ const bodyTrimmed = parsed.body.trim();
28870
+ const bareVarMatch = bodyTrimmed.match(/^([a-zA-Z_][a-zA-Z0-9_]*)$/);
28871
+ if (bareVarMatch && bareVarMatch[1] in runtimeVariables) {
28872
+ const varValue = runtimeVariables[bareVarMatch[1]];
28873
+ if (typeof varValue === "object" && varValue !== null) {
28874
+ parsed.body = JSON.stringify(varValue);
28875
+ } else if (typeof varValue === "string") {
28876
+ parsed.body = varValue;
28877
+ } else {
28878
+ parsed.body = String(varValue);
28879
+ }
28880
+ }
28881
+ }
28801
28882
  }
28802
28883
  const { retryCount, backoffMs } = extractRetryOptions(step.content);
28803
28884
  const retryOpts = retryCount ?? parsed.retryCount ? {
@@ -29316,11 +29397,13 @@ function formatRequestStep(step, options) {
29316
29397
  colors,
29317
29398
  redaction,
29318
29399
  verbose,
29319
- showDetails: !isSuccess,
29320
- // Show request details on failure
29400
+ showDetails: !isSuccess || verbose,
29401
+ // Show request details on failure or verbose
29321
29402
  index: requestIndex,
29322
29403
  method: step.requestMethod,
29323
- url: step.requestUrl
29404
+ url: step.requestUrl,
29405
+ requestBody: step.response.requestBody,
29406
+ requestHeaders: step.response.requestHeaders
29324
29407
  });
29325
29408
  }
29326
29409
  function formatAssertionStep(step, options) {
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.7",
5
+ "version": "1.3.9",
6
6
  "publisher": "Norn-PeterKrustanov",
7
7
  "author": {
8
8
  "name": "Peter Krastanov"