norn-cli 1.8.0 → 1.9.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 (2) hide show
  1. package/dist/cli.js +183 -176
  2. package/package.json +7 -1
package/dist/cli.js CHANGED
@@ -109395,16 +109395,16 @@ var BUILT_IN_SQL_ADAPTERS = [
109395
109395
  {
109396
109396
  id: "postgres",
109397
109397
  label: "PostgreSQL",
109398
- description: "Built-in PostgreSQL adapter using either a connection string or split connection values.",
109399
- connectionSetupSummary: "connectionString OR host/server + database + user + password",
109400
- optionalConnectionKeys: ["port", "ssl", "rejectUnauthorized", "schema", "applicationName"]
109398
+ description: "Built-in PostgreSQL adapter using a connection string.",
109399
+ connectionSetupSummary: "connectionString",
109400
+ optionalConnectionKeys: []
109401
109401
  },
109402
109402
  {
109403
109403
  id: "sqlserver",
109404
109404
  label: "SQL Server",
109405
- description: "Built-in SQL Server adapter using either a connection string or split connection values.",
109406
- connectionSetupSummary: "connectionString OR host/server + database + user + password",
109407
- optionalConnectionKeys: ["port", "encrypt", "trustServerCertificate", "instanceName", "connectionTimeout", "requestTimeout", "appName", "domain"]
109405
+ description: "Built-in SQL Server adapter using a connection string.",
109406
+ connectionSetupSummary: "connectionString",
109407
+ optionalConnectionKeys: []
109408
109408
  }
109409
109409
  ];
109410
109410
  var BUILT_IN_SQL_ADAPTER_MAP = new Map(
@@ -109426,31 +109426,48 @@ function getConnectionValue(values, ...keys) {
109426
109426
  function getConnectionString(values) {
109427
109427
  return getConnectionValue(values, "connectionString");
109428
109428
  }
109429
- function parseBoolean(value, defaultValue) {
109430
- if (value === void 0 || value === null || value === "") {
109431
- return defaultValue;
109432
- }
109433
- const normalized = value.trim().toLowerCase();
109434
- if (["true", "1", "yes", "on"].includes(normalized)) {
109435
- return true;
109436
- }
109437
- if (["false", "0", "no", "off"].includes(normalized)) {
109429
+ function buildMissingConnectionError(adapterLabel, profile) {
109430
+ return `Missing required ${adapterLabel} connection string. Expected 'connectionString ${profile} = ...' in .nornenv.`;
109431
+ }
109432
+ function shouldPassThroughError(error) {
109433
+ if (!(error instanceof Error)) {
109438
109434
  return false;
109439
109435
  }
109440
- return defaultValue;
109436
+ return /^(Missing required|Missing SQL parameter|Invalid )/.test(error.message);
109441
109437
  }
109442
- function parseOptionalNumber(value, label) {
109443
- if (value === void 0 || value === null || value.trim() === "") {
109444
- return void 0;
109445
- }
109446
- const parsed = Number(value);
109447
- if (!Number.isFinite(parsed)) {
109448
- fail(`Invalid ${label} '${value}'`);
109438
+ function formatBuiltInDriverError(adapterLabel, error) {
109439
+ if (shouldPassThroughError(error)) {
109440
+ return error;
109449
109441
  }
109450
- return parsed;
109451
- }
109452
- function buildMissingConnectionError(adapterLabel) {
109453
- return `Missing required ${adapterLabel} connection values. Expected connectionString or host/server, database, user, and password.`;
109442
+ const candidate = error;
109443
+ const baseMessage = error instanceof Error ? error.message : typeof error === "string" ? error : "Unknown database error";
109444
+ const details = [];
109445
+ const append2 = (label, value) => {
109446
+ if (value === void 0 || value === null || `${value}`.trim() === "") {
109447
+ return;
109448
+ }
109449
+ details.push(`${label}: ${value}`);
109450
+ };
109451
+ append2("code", candidate?.code);
109452
+ append2("number", candidate?.number);
109453
+ append2("state", candidate?.state);
109454
+ append2("severity", candidate?.severity ?? candidate?.class);
109455
+ append2("detail", candidate?.detail);
109456
+ append2("hint", candidate?.hint);
109457
+ append2("schema", candidate?.schema);
109458
+ append2("table", candidate?.table);
109459
+ append2("column", candidate?.column);
109460
+ append2("constraint", candidate?.constraint);
109461
+ append2("routine", candidate?.routine);
109462
+ append2("line", candidate?.lineNumber);
109463
+ append2("procedure", candidate?.procName);
109464
+ append2("server", candidate?.serverName);
109465
+ const precedingErrors = Array.isArray(candidate?.precedingErrors) ? (candidate?.precedingErrors).map((item) => item?.message).filter((message) => message !== void 0 && message !== null && `${message}`.trim() !== "") : [];
109466
+ if (precedingErrors.length > 0) {
109467
+ details.push(`precedingErrors: ${precedingErrors.join(" | ")}`);
109468
+ }
109469
+ const suffix = details.length > 0 ? ` (${details.join(", ")})` : "";
109470
+ return new Error(`${adapterLabel} driver error: ${baseMessage}${suffix}`);
109454
109471
  }
109455
109472
  function compilePostgresSql(sql, params) {
109456
109473
  const values = [];
@@ -109485,31 +109502,12 @@ function compileSqlServerSql(sql, params) {
109485
109502
  async function runBuiltInPostgresAdapter(request) {
109486
109503
  const values = request.connection.values;
109487
109504
  const connectionString = getConnectionString(values);
109488
- const host = getConnectionValue(values, "host", "server");
109489
- const database = getConnectionValue(values, "database");
109490
- const user = getConnectionValue(values, "user");
109491
- const password = getConnectionValue(values, "password");
109492
- const client = connectionString ? new Client(connectionString) : (() => {
109493
- if (!host || !database || !user || !password) {
109494
- fail(buildMissingConnectionError("Postgres"));
109495
- }
109496
- const port = parseOptionalNumber(values.port, "Postgres port") ?? 5432;
109497
- return new Client({
109498
- host,
109499
- port,
109500
- database,
109501
- user,
109502
- password,
109503
- ssl: parseBoolean(values.ssl, false) ? { rejectUnauthorized: parseBoolean(values.rejectUnauthorized, false) } : false,
109504
- application_name: values.applicationName || "norn-sql"
109505
- });
109506
- })();
109505
+ if (!connectionString) {
109506
+ fail(buildMissingConnectionError("Postgres", request.connection.profile));
109507
+ }
109508
+ const client = new Client(connectionString);
109507
109509
  try {
109508
109510
  await client.connect();
109509
- if (values.schema) {
109510
- const safeSchema = values.schema.replace(/"/g, '""');
109511
- await client.query(`set search_path to "${safeSchema}"`);
109512
- }
109513
109511
  const compiled = compilePostgresSql(request.operation.sql, request.params || {});
109514
109512
  const result = await client.query(compiled.text, compiled.values);
109515
109513
  if (request.mode === "query") {
@@ -109529,6 +109527,8 @@ async function runBuiltInPostgresAdapter(request) {
109529
109527
  affectedRows: result.rowCount ?? 0
109530
109528
  }
109531
109529
  };
109530
+ } catch (error) {
109531
+ throw formatBuiltInDriverError("Postgres", error);
109532
109532
  } finally {
109533
109533
  await client.end().catch(() => void 0);
109534
109534
  }
@@ -109536,53 +109536,10 @@ async function runBuiltInPostgresAdapter(request) {
109536
109536
  async function runBuiltInSqlServerAdapter(request) {
109537
109537
  const values = request.connection.values;
109538
109538
  const connectionString = getConnectionString(values);
109539
- const pool = connectionString ? new mssql.ConnectionPool(connectionString) : (() => {
109540
- const server = getConnectionValue(values, "server", "host");
109541
- const database = getConnectionValue(values, "database");
109542
- const user = getConnectionValue(values, "user");
109543
- const password = getConnectionValue(values, "password");
109544
- if (!server || !database || !user || !password) {
109545
- fail(buildMissingConnectionError("SQL Server"));
109546
- }
109547
- const port = parseOptionalNumber(values.port, "SQL Server port");
109548
- const connectionTimeout = parseOptionalNumber(values.connectionTimeout, "SQL Server connectionTimeout");
109549
- const requestTimeout = parseOptionalNumber(values.requestTimeout, "SQL Server requestTimeout");
109550
- const config = {
109551
- server,
109552
- database,
109553
- user,
109554
- password,
109555
- options: {
109556
- encrypt: parseBoolean(values.encrypt, false),
109557
- trustServerCertificate: parseBoolean(values.trustServerCertificate, false)
109558
- }
109559
- };
109560
- if (port !== void 0) {
109561
- config.port = port;
109562
- }
109563
- if (values.instanceName) {
109564
- config.options = {
109565
- ...config.options,
109566
- instanceName: values.instanceName
109567
- };
109568
- }
109569
- if (values.appName) {
109570
- config.options = {
109571
- ...config.options,
109572
- appName: values.appName
109573
- };
109574
- }
109575
- if (values.domain) {
109576
- config.domain = values.domain;
109577
- }
109578
- if (connectionTimeout !== void 0) {
109579
- config.connectionTimeout = connectionTimeout;
109580
- }
109581
- if (requestTimeout !== void 0) {
109582
- config.requestTimeout = requestTimeout;
109583
- }
109584
- return new mssql.ConnectionPool(config);
109585
- })();
109539
+ if (!connectionString) {
109540
+ fail(buildMissingConnectionError("SQL Server", request.connection.profile));
109541
+ }
109542
+ const pool = new mssql.ConnectionPool(connectionString);
109586
109543
  try {
109587
109544
  await pool.connect();
109588
109545
  const compiled = compileSqlServerSql(request.operation.sql, request.params || {});
@@ -109610,6 +109567,8 @@ async function runBuiltInSqlServerAdapter(request) {
109610
109567
  affectedRows
109611
109568
  }
109612
109569
  };
109570
+ } catch (error) {
109571
+ throw formatBuiltInDriverError("SQL Server", error);
109613
109572
  } finally {
109614
109573
  await pool.close().catch(() => void 0);
109615
109574
  }
@@ -110161,23 +110120,35 @@ function splitNamedArgumentList(argsStr) {
110161
110120
  }
110162
110121
  return parts;
110163
110122
  }
110164
- function parseNamedSqlArguments(argsStr) {
110123
+ function parseSqlArguments(argsStr) {
110165
110124
  if (!argsStr.trim()) {
110166
110125
  return { args: [] };
110167
110126
  }
110168
110127
  const parts = splitNamedArgumentList(argsStr);
110169
110128
  const args = [];
110129
+ let sawNamedArgument = false;
110170
110130
  for (const part of parts) {
110171
- const match = part.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*:\s*(.+)$/);
110172
- if (!match) {
110131
+ const trimmed = part.trim();
110132
+ if (!trimmed) {
110133
+ continue;
110134
+ }
110135
+ const match = trimmed.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*:\s*(.+)$/);
110136
+ if (match) {
110137
+ sawNamedArgument = true;
110138
+ args.push({
110139
+ name: match[1],
110140
+ valueExpression: match[2].trim()
110141
+ });
110142
+ continue;
110143
+ }
110144
+ if (sawNamedArgument) {
110173
110145
  return {
110174
110146
  args: [],
110175
- error: "SQL arguments must use named syntax: run sql Name(param: value)"
110147
+ error: "Positional SQL arguments cannot follow named arguments."
110176
110148
  };
110177
110149
  }
110178
110150
  args.push({
110179
- name: match[1],
110180
- valueExpression: match[2].trim()
110151
+ valueExpression: trimmed
110181
110152
  });
110182
110153
  }
110183
110154
  return { args };
@@ -110191,7 +110162,7 @@ function parseRunSqlCommand(line2) {
110191
110162
  if (!match) {
110192
110163
  return null;
110193
110164
  }
110194
- const parsedArgs = parseNamedSqlArguments(match[3] || "");
110165
+ const parsedArgs = parseSqlArguments(match[3] || "");
110195
110166
  if (parsedArgs.error) {
110196
110167
  return {
110197
110168
  variableName: match[1],
@@ -110206,6 +110177,52 @@ function parseRunSqlCommand(line2) {
110206
110177
  args: parsedArgs.args
110207
110178
  };
110208
110179
  }
110180
+ function bindSqlArguments(parameterNames, args, runtimeVariables) {
110181
+ const resolvedParams = {};
110182
+ const boundParams = /* @__PURE__ */ new Set();
110183
+ let positionalIndex = 0;
110184
+ let sawNamedArgument = false;
110185
+ for (const arg of args) {
110186
+ if (arg.name) {
110187
+ sawNamedArgument = true;
110188
+ const declaredParam2 = parameterNames.find((param) => param.toLowerCase() === arg.name.toLowerCase());
110189
+ if (!declaredParam2) {
110190
+ return { error: `Unknown SQL parameter '${arg.name}'.` };
110191
+ }
110192
+ const declaredLower = declaredParam2.toLowerCase();
110193
+ if (boundParams.has(declaredLower)) {
110194
+ return { error: `Duplicate SQL parameter '${declaredParam2}' in run sql call.` };
110195
+ }
110196
+ const valueResult2 = evaluateSqlArgumentExpression(arg.valueExpression, runtimeVariables);
110197
+ if (valueResult2.error) {
110198
+ return { error: valueResult2.error };
110199
+ }
110200
+ resolvedParams[declaredParam2] = valueResult2.value;
110201
+ boundParams.add(declaredLower);
110202
+ continue;
110203
+ }
110204
+ if (sawNamedArgument) {
110205
+ return { error: "Positional SQL arguments cannot follow named arguments." };
110206
+ }
110207
+ if (positionalIndex >= parameterNames.length) {
110208
+ return { error: `Too many SQL arguments: expected ${parameterNames.length}.` };
110209
+ }
110210
+ const declaredParam = parameterNames[positionalIndex];
110211
+ const valueResult = evaluateSqlArgumentExpression(arg.valueExpression, runtimeVariables);
110212
+ if (valueResult.error) {
110213
+ return { error: valueResult.error };
110214
+ }
110215
+ resolvedParams[declaredParam] = valueResult.value;
110216
+ boundParams.add(declaredParam.toLowerCase());
110217
+ positionalIndex++;
110218
+ }
110219
+ for (const param of parameterNames) {
110220
+ if (!boundParams.has(param.toLowerCase())) {
110221
+ return { error: `Missing required SQL parameter '${param}'.` };
110222
+ }
110223
+ }
110224
+ return { params: resolvedParams };
110225
+ }
110209
110226
  function isVarRunSequenceCommand(line2) {
110210
110227
  const trimmed = line2.trim();
110211
110228
  if (!/^var\s+[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*run\s+[a-zA-Z_][a-zA-Z0-9_-]*(?:\s*\([^)]*\))?(?:\s+retry\s+\d+)?(?:\s+backoff\s+\d+(?:\.\d+)?\s*(?:s|ms|seconds?|milliseconds?)?)?\s*$/i.test(trimmed)) {
@@ -111719,78 +111736,25 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
111719
111736
  duration: Date.now() - startTime
111720
111737
  };
111721
111738
  }
111722
- const providedArgs = /* @__PURE__ */ new Map();
111723
- const declaredParams = new Set(operation.parameters.map((param) => param.toLowerCase()));
111724
- for (const arg of parsed.args) {
111725
- const lowerName = arg.name.toLowerCase();
111726
- if (providedArgs.has(lowerName)) {
111727
- errors.push(`Duplicate SQL parameter '${arg.name}' in run sql call.`);
111728
- return {
111729
- name: "",
111730
- success: false,
111731
- responses,
111732
- scriptResults,
111733
- assertionResults,
111734
- steps: orderedSteps,
111735
- errors,
111736
- duration: Date.now() - startTime
111737
- };
111738
- }
111739
- if (!declaredParams.has(lowerName)) {
111740
- errors.push(`Unknown SQL parameter '${arg.name}'.`);
111741
- return {
111742
- name: "",
111743
- success: false,
111744
- responses,
111745
- scriptResults,
111746
- assertionResults,
111747
- steps: orderedSteps,
111748
- errors,
111749
- duration: Date.now() - startTime
111750
- };
111751
- }
111752
- const valueResult = evaluateSqlArgumentExpression(arg.valueExpression, runtimeVariables);
111753
- if (valueResult.error) {
111754
- errors.push(`Step ${stepIdx + 1}: ${valueResult.error}`);
111755
- return {
111756
- name: "",
111757
- success: false,
111758
- responses,
111759
- scriptResults,
111760
- assertionResults,
111761
- steps: orderedSteps,
111762
- errors,
111763
- duration: Date.now() - startTime
111764
- };
111765
- }
111766
- providedArgs.set(lowerName, valueResult.value);
111767
- }
111768
- for (const param of operation.parameters) {
111769
- if (!providedArgs.has(param.toLowerCase())) {
111770
- errors.push(`Missing required SQL parameter '${param}'.`);
111771
- return {
111772
- name: "",
111773
- success: false,
111774
- responses,
111775
- scriptResults,
111776
- assertionResults,
111777
- steps: orderedSteps,
111778
- errors,
111779
- duration: Date.now() - startTime
111780
- };
111781
- }
111739
+ const boundArgs = bindSqlArguments(operation.parameters, parsed.args, runtimeVariables);
111740
+ if ("error" in boundArgs) {
111741
+ errors.push(`Step ${stepIdx + 1}: ${boundArgs.error}`);
111742
+ return {
111743
+ name: "",
111744
+ success: false,
111745
+ responses,
111746
+ scriptResults,
111747
+ assertionResults,
111748
+ steps: orderedSteps,
111749
+ errors,
111750
+ duration: Date.now() - startTime
111751
+ };
111782
111752
  }
111783
111753
  const adapterWorkingDir = workingDir || process.cwd();
111784
111754
  try {
111785
111755
  const connection = resolveSqlConnection(executionContext?.filePath || adapterWorkingDir, operation.connectionName);
111786
111756
  const adapterTarget = resolveSqlAdapterTarget(executionContext?.filePath || adapterWorkingDir, connection.adapter);
111787
111757
  const connectionValues = getSqlConnectionValues(connection.profile, runtimeVariables);
111788
- const paramPayload = Object.fromEntries(
111789
- Array.from(providedArgs.entries()).map(([lowerName, value]) => {
111790
- const declaredName = operation.parameters.find((param) => param.toLowerCase() === lowerName) || lowerName;
111791
- return [declaredName, value];
111792
- })
111793
- );
111794
111758
  const adapterResponse = await runSqlAdapter(
111795
111759
  adapterTarget,
111796
111760
  {
@@ -111804,7 +111768,7 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
111804
111768
  connectionName: operation.connectionName,
111805
111769
  sourcePath: operation.sourcePath
111806
111770
  },
111807
- params: paramPayload,
111771
+ params: boundArgs.params,
111808
111772
  connection: {
111809
111773
  name: connection.alias,
111810
111774
  profile: connection.profile,
@@ -114326,7 +114290,9 @@ var ENV_FILENAME = ".nornenv";
114326
114290
  var importRegex = /^import\s+["']?(.+?)["']?\s*$/;
114327
114291
  var envRegex = /^\[env:([a-zA-Z_][a-zA-Z0-9_-]*)\]$/;
114328
114292
  var varRegex = /^var\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.+)$/;
114293
+ var connectionStringRegex = /^connectionString\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.+)$/;
114329
114294
  var secretRegex = /^secret\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.+)$/;
114295
+ var secretConnectionStringRegex = /^secret\s+connectionString\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.+)$/;
114330
114296
  function parseEnvFile(content, sourceFilePath) {
114331
114297
  const lines = content.split("\n");
114332
114298
  const config = {
@@ -114367,6 +114333,27 @@ function parseEnvFile(content, sourceFilePath) {
114367
114333
  config.environments.push(currentEnv);
114368
114334
  continue;
114369
114335
  }
114336
+ const secretConnectionStringMatch = trimmed.match(secretConnectionStringRegex);
114337
+ if (secretConnectionStringMatch) {
114338
+ const profileName = secretConnectionStringMatch[1];
114339
+ const varName = `${profileName}_connectionString`;
114340
+ const varValue = secretConnectionStringMatch[2].trim();
114341
+ config.secretDeclarations.push({
114342
+ name: varName,
114343
+ value: varValue,
114344
+ envName: currentEnv?.name,
114345
+ lineNumber: i,
114346
+ filePath: sourceFilePath
114347
+ });
114348
+ config.secretNames.add(varName);
114349
+ config.secretValues.set(varName, varValue);
114350
+ if (currentEnv) {
114351
+ currentEnv.variables[varName] = varValue;
114352
+ } else {
114353
+ config.common[varName] = varValue;
114354
+ }
114355
+ continue;
114356
+ }
114370
114357
  const secretMatch = trimmed.match(secretRegex);
114371
114358
  if (secretMatch) {
114372
114359
  const varName = secretMatch[1];
@@ -114387,6 +114374,18 @@ function parseEnvFile(content, sourceFilePath) {
114387
114374
  }
114388
114375
  continue;
114389
114376
  }
114377
+ const connectionStringMatch = trimmed.match(connectionStringRegex);
114378
+ if (connectionStringMatch) {
114379
+ const profileName = connectionStringMatch[1];
114380
+ const varName = `${profileName}_connectionString`;
114381
+ const varValue = connectionStringMatch[2].trim();
114382
+ if (currentEnv) {
114383
+ currentEnv.variables[varName] = varValue;
114384
+ } else {
114385
+ config.common[varName] = varValue;
114386
+ }
114387
+ continue;
114388
+ }
114390
114389
  const varMatch = trimmed.match(varRegex);
114391
114390
  if (varMatch) {
114392
114391
  const varName = varMatch[1];
@@ -114661,6 +114660,7 @@ var import_process = require("process");
114661
114660
  var fs14 = __toESM(require("fs"));
114662
114661
  var path10 = __toESM(require("path"));
114663
114662
  var envRegex2 = /^\s*\[env:([a-zA-Z_][a-zA-Z0-9_-]*)\]\s*$/;
114663
+ var secretConnectionStringRegex2 = /^(\s*secret\s+connectionString\s+)([a-zA-Z_][a-zA-Z0-9_]*)(\s*=\s*)(.+)$/;
114664
114664
  var secretRegex2 = /^(\s*secret\s+)([a-zA-Z_][a-zA-Z0-9_]*)(\s*=\s*)(.+)$/;
114665
114665
  function splitContentLines(content) {
114666
114666
  return content.split(/\r?\n/);
@@ -114686,11 +114686,13 @@ function extractSecretLines(content, filePath) {
114686
114686
  currentEnv = envMatch[1];
114687
114687
  continue;
114688
114688
  }
114689
+ const secretConnectionStringMatch = line2.match(secretConnectionStringRegex2);
114689
114690
  const secretMatch = line2.match(secretRegex2);
114690
- if (!secretMatch) {
114691
+ if (!secretConnectionStringMatch && !secretMatch) {
114691
114692
  continue;
114692
114693
  }
114693
- const value = secretMatch[4].trim();
114694
+ const secretName = secretConnectionStringMatch ? `${secretConnectionStringMatch[2]}_connectionString` : secretMatch[2];
114695
+ const value = (secretConnectionStringMatch?.[4] ?? secretMatch[4]).trim();
114694
114696
  const encrypted = isEncryptedSecretValue(value);
114695
114697
  let kid;
114696
114698
  if (encrypted) {
@@ -114703,7 +114705,7 @@ function extractSecretLines(content, filePath) {
114703
114705
  filePath,
114704
114706
  lineNumber: i,
114705
114707
  envName: currentEnv,
114706
- name: secretMatch[2],
114708
+ name: secretName,
114707
114709
  value,
114708
114710
  encrypted,
114709
114711
  kid
@@ -114717,11 +114719,16 @@ function updateSecretLineValue(content, lineNumber, newValue) {
114717
114719
  throw new Error(`Line ${lineNumber + 1} is out of range.`);
114718
114720
  }
114719
114721
  const line2 = lines[lineNumber];
114722
+ const secretConnectionStringMatch = line2.match(secretConnectionStringRegex2);
114720
114723
  const secretMatch = line2.match(secretRegex2);
114721
- if (!secretMatch) {
114724
+ if (!secretConnectionStringMatch && !secretMatch) {
114722
114725
  throw new Error(`Line ${lineNumber + 1} is not a secret declaration.`);
114723
114726
  }
114724
- lines[lineNumber] = `${secretMatch[1]}${secretMatch[2]}${secretMatch[3]}${newValue}`;
114727
+ if (secretConnectionStringMatch) {
114728
+ lines[lineNumber] = `${secretConnectionStringMatch[1]}${secretConnectionStringMatch[2]}${secretConnectionStringMatch[3]}${newValue}`;
114729
+ } else {
114730
+ lines[lineNumber] = `${secretMatch[1]}${secretMatch[2]}${secretMatch[3]}${newValue}`;
114731
+ }
114725
114732
  return lines.join(detectEol(content));
114726
114733
  }
114727
114734
  function findSecretLine(content, variableName, envName) {
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.8.0",
5
+ "version": "1.9.0",
6
6
  "publisher": "Norn-PeterKrustanov",
7
7
  "author": {
8
8
  "name": "Peter Krastanov"
@@ -362,6 +362,12 @@
362
362
  "settings": {
363
363
  "foreground": "#85EA2C"
364
364
  }
365
+ },
366
+ {
367
+ "scope": "support.type.connection.nornenv",
368
+ "settings": {
369
+ "foreground": "#d7ba7d"
370
+ }
365
371
  }
366
372
  ]
367
373
  }