norn-cli 1.9.0 → 1.10.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.
- package/dist/cli.js +209 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -109375,6 +109375,9 @@ init_quotedString();
|
|
|
109375
109375
|
var fs8 = __toESM(require("fs"));
|
|
109376
109376
|
var path6 = __toESM(require("path"));
|
|
109377
109377
|
|
|
109378
|
+
// src/sqlBuiltInAdapters.ts
|
|
109379
|
+
var import_child_process2 = require("child_process");
|
|
109380
|
+
|
|
109378
109381
|
// node_modules/pg/esm/index.mjs
|
|
109379
109382
|
var import_lib = __toESM(require_lib2(), 1);
|
|
109380
109383
|
var Client = import_lib.default.Client;
|
|
@@ -109405,6 +109408,13 @@ var BUILT_IN_SQL_ADAPTERS = [
|
|
|
109405
109408
|
description: "Built-in SQL Server adapter using a connection string.",
|
|
109406
109409
|
connectionSetupSummary: "connectionString",
|
|
109407
109410
|
optionalConnectionKeys: []
|
|
109411
|
+
},
|
|
109412
|
+
{
|
|
109413
|
+
id: "sqlserver-integrated",
|
|
109414
|
+
label: "SQL Server (Integrated Auth)",
|
|
109415
|
+
description: "Built-in SQL Server adapter using PowerShell for Windows/Trusted authentication.",
|
|
109416
|
+
connectionSetupSummary: "connectionString",
|
|
109417
|
+
optionalConnectionKeys: []
|
|
109408
109418
|
}
|
|
109409
109419
|
];
|
|
109410
109420
|
var BUILT_IN_SQL_ADAPTER_MAP = new Map(
|
|
@@ -109429,6 +109439,180 @@ function getConnectionString(values) {
|
|
|
109429
109439
|
function buildMissingConnectionError(adapterLabel, profile) {
|
|
109430
109440
|
return `Missing required ${adapterLabel} connection string. Expected 'connectionString ${profile} = ...' in .nornenv.`;
|
|
109431
109441
|
}
|
|
109442
|
+
var pwshAvailable2 = null;
|
|
109443
|
+
function isPwshAvailable2() {
|
|
109444
|
+
if (pwshAvailable2 !== null) {
|
|
109445
|
+
return pwshAvailable2;
|
|
109446
|
+
}
|
|
109447
|
+
try {
|
|
109448
|
+
const result = (0, import_child_process2.spawnSync)("pwsh", ["--version"], {
|
|
109449
|
+
timeout: 5e3,
|
|
109450
|
+
stdio: "pipe"
|
|
109451
|
+
});
|
|
109452
|
+
pwshAvailable2 = result.status === 0;
|
|
109453
|
+
} catch (error) {
|
|
109454
|
+
pwshAvailable2 = false;
|
|
109455
|
+
}
|
|
109456
|
+
return pwshAvailable2;
|
|
109457
|
+
}
|
|
109458
|
+
function getPowerShellCommand() {
|
|
109459
|
+
return isPwshAvailable2() ? "pwsh" : "powershell";
|
|
109460
|
+
}
|
|
109461
|
+
function encodePowerShellCommand(script) {
|
|
109462
|
+
return Buffer.from(script, "utf16le").toString("base64");
|
|
109463
|
+
}
|
|
109464
|
+
async function runSqlServerIntegratedViaPowerShell(request) {
|
|
109465
|
+
const script = `
|
|
109466
|
+
$ErrorActionPreference = 'Stop'
|
|
109467
|
+
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
|
109468
|
+
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
109469
|
+
|
|
109470
|
+
$raw = [Console]::In.ReadToEnd()
|
|
109471
|
+
if ([string]::IsNullOrWhiteSpace($raw)) {
|
|
109472
|
+
throw 'Missing SQL adapter payload.'
|
|
109473
|
+
}
|
|
109474
|
+
|
|
109475
|
+
$payload = $raw | ConvertFrom-Json -Depth 100
|
|
109476
|
+
$connectionString = [string]$payload.connection.values.connectionString
|
|
109477
|
+
if ([string]::IsNullOrWhiteSpace($connectionString)) {
|
|
109478
|
+
throw 'Missing SQL Server Integrated Auth connection string.'
|
|
109479
|
+
}
|
|
109480
|
+
|
|
109481
|
+
$sqlText = [string]$payload.operation.sql
|
|
109482
|
+
$mode = [string]$payload.mode
|
|
109483
|
+
$paramsObject = $payload.params
|
|
109484
|
+
|
|
109485
|
+
$connection = $null
|
|
109486
|
+
try {
|
|
109487
|
+
$connection = New-Object System.Data.SqlClient.SqlConnection $connectionString
|
|
109488
|
+
$command = $connection.CreateCommand()
|
|
109489
|
+
$command.CommandText = $sqlText
|
|
109490
|
+
|
|
109491
|
+
if ($null -ne $paramsObject) {
|
|
109492
|
+
foreach ($property in $paramsObject.PSObject.Properties) {
|
|
109493
|
+
$value = $property.Value
|
|
109494
|
+
if ($null -eq $value) {
|
|
109495
|
+
$value = [DBNull]::Value
|
|
109496
|
+
} elseif ($value -is [datetime]) {
|
|
109497
|
+
$value = $value.ToUniversalTime()
|
|
109498
|
+
} elseif ($value -is [System.Collections.IEnumerable] -and -not ($value -is [string]) -and -not ($value -is [byte[]])) {
|
|
109499
|
+
$value = ($value | ConvertTo-Json -Depth 100 -Compress)
|
|
109500
|
+
} elseif ($value -is [pscustomobject]) {
|
|
109501
|
+
$value = ($value | ConvertTo-Json -Depth 100 -Compress)
|
|
109502
|
+
}
|
|
109503
|
+
[void]$command.Parameters.AddWithValue("@$($property.Name)", $value)
|
|
109504
|
+
}
|
|
109505
|
+
}
|
|
109506
|
+
|
|
109507
|
+
$connection.Open()
|
|
109508
|
+
|
|
109509
|
+
if ($mode -eq 'query') {
|
|
109510
|
+
$reader = $command.ExecuteReader()
|
|
109511
|
+
$rows = @()
|
|
109512
|
+
|
|
109513
|
+
try {
|
|
109514
|
+
while ($reader.Read()) {
|
|
109515
|
+
$row = [ordered]@{}
|
|
109516
|
+
for ($i = 0; $i -lt $reader.FieldCount; $i++) {
|
|
109517
|
+
$value = $reader.GetValue($i)
|
|
109518
|
+
if ($value -is [DBNull]) {
|
|
109519
|
+
$value = $null
|
|
109520
|
+
} elseif ($value -is [datetime]) {
|
|
109521
|
+
$value = $value.ToString('o')
|
|
109522
|
+
} elseif ($value -is [byte[]]) {
|
|
109523
|
+
$value = [Convert]::ToBase64String($value)
|
|
109524
|
+
}
|
|
109525
|
+
$row[$reader.GetName($i)] = $value
|
|
109526
|
+
}
|
|
109527
|
+
$rows += [pscustomobject]$row
|
|
109528
|
+
}
|
|
109529
|
+
} finally {
|
|
109530
|
+
$reader.Close()
|
|
109531
|
+
}
|
|
109532
|
+
|
|
109533
|
+
$response = [pscustomobject]@{
|
|
109534
|
+
success = $true
|
|
109535
|
+
result = [pscustomobject]@{
|
|
109536
|
+
kind = 'rows'
|
|
109537
|
+
rowCount = @($rows).Count
|
|
109538
|
+
rows = @($rows)
|
|
109539
|
+
}
|
|
109540
|
+
}
|
|
109541
|
+
} else {
|
|
109542
|
+
$affectedRows = $command.ExecuteNonQuery()
|
|
109543
|
+
if ($affectedRows -lt 0) {
|
|
109544
|
+
$affectedRows = 0
|
|
109545
|
+
}
|
|
109546
|
+
$response = [pscustomobject]@{
|
|
109547
|
+
success = $true
|
|
109548
|
+
result = [pscustomobject]@{
|
|
109549
|
+
kind = 'exec'
|
|
109550
|
+
affectedRows = $affectedRows
|
|
109551
|
+
}
|
|
109552
|
+
}
|
|
109553
|
+
}
|
|
109554
|
+
|
|
109555
|
+
$response | ConvertTo-Json -Depth 100 -Compress
|
|
109556
|
+
}
|
|
109557
|
+
catch {
|
|
109558
|
+
$details = @()
|
|
109559
|
+
if ($_.Exception -and $_.Exception.GetType()) {
|
|
109560
|
+
$details += "type: $($_.Exception.GetType().FullName)"
|
|
109561
|
+
}
|
|
109562
|
+
if ($_.InvocationInfo -and $_.InvocationInfo.ScriptLineNumber) {
|
|
109563
|
+
$details += "line: $($_.InvocationInfo.ScriptLineNumber)"
|
|
109564
|
+
}
|
|
109565
|
+
if ($_.FullyQualifiedErrorId) {
|
|
109566
|
+
$details += "id: $($_.FullyQualifiedErrorId)"
|
|
109567
|
+
}
|
|
109568
|
+
$suffix = if ($details.Count -gt 0) { " ($($details -join ', '))" } else { '' }
|
|
109569
|
+
[Console]::Error.WriteLine("$($_.Exception.Message)$suffix")
|
|
109570
|
+
exit 1
|
|
109571
|
+
}
|
|
109572
|
+
finally {
|
|
109573
|
+
if ($null -ne $connection) {
|
|
109574
|
+
$connection.Dispose()
|
|
109575
|
+
}
|
|
109576
|
+
}
|
|
109577
|
+
`.trim();
|
|
109578
|
+
const payload = JSON.stringify(request);
|
|
109579
|
+
const command = getPowerShellCommand();
|
|
109580
|
+
const commandArgs = ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-OutputFormat", "Text", "-EncodedCommand", encodePowerShellCommand(script)];
|
|
109581
|
+
return new Promise((resolve11, reject) => {
|
|
109582
|
+
const child = (0, import_child_process2.spawn)(command, commandArgs, {
|
|
109583
|
+
cwd: request.context?.workingDir || process.cwd(),
|
|
109584
|
+
shell: false,
|
|
109585
|
+
env: {
|
|
109586
|
+
...process.env
|
|
109587
|
+
}
|
|
109588
|
+
});
|
|
109589
|
+
let stdout = "";
|
|
109590
|
+
let stderr = "";
|
|
109591
|
+
child.stdout.on("data", (data) => {
|
|
109592
|
+
stdout += data.toString();
|
|
109593
|
+
});
|
|
109594
|
+
child.stderr.on("data", (data) => {
|
|
109595
|
+
stderr += data.toString();
|
|
109596
|
+
});
|
|
109597
|
+
child.on("error", (error) => {
|
|
109598
|
+
reject(new Error(`Failed to start PowerShell for SQL Server Integrated Auth: ${error.message}`));
|
|
109599
|
+
});
|
|
109600
|
+
child.on("close", (code) => {
|
|
109601
|
+
if (code !== 0) {
|
|
109602
|
+
reject(new Error((stderr || stdout || `PowerShell exited with code ${code}`).trim()));
|
|
109603
|
+
return;
|
|
109604
|
+
}
|
|
109605
|
+
try {
|
|
109606
|
+
const parsed = JSON.parse(stdout.trim());
|
|
109607
|
+
resolve11(parsed);
|
|
109608
|
+
} catch (error) {
|
|
109609
|
+
reject(new Error(`Invalid PowerShell SQL adapter response: ${error instanceof Error ? error.message : String(error)}`));
|
|
109610
|
+
}
|
|
109611
|
+
});
|
|
109612
|
+
child.stdin.write(payload);
|
|
109613
|
+
child.stdin.end();
|
|
109614
|
+
});
|
|
109615
|
+
}
|
|
109432
109616
|
function shouldPassThroughError(error) {
|
|
109433
109617
|
if (!(error instanceof Error)) {
|
|
109434
109618
|
return false;
|
|
@@ -109573,6 +109757,27 @@ async function runBuiltInSqlServerAdapter(request) {
|
|
|
109573
109757
|
await pool.close().catch(() => void 0);
|
|
109574
109758
|
}
|
|
109575
109759
|
}
|
|
109760
|
+
async function runBuiltInSqlServerIntegratedAdapter(request) {
|
|
109761
|
+
const values = request.connection.values;
|
|
109762
|
+
const connectionString = getConnectionString(values);
|
|
109763
|
+
if (!connectionString) {
|
|
109764
|
+
fail(buildMissingConnectionError("SQL Server Integrated Auth", request.connection.profile));
|
|
109765
|
+
}
|
|
109766
|
+
const compiled = compileSqlServerSql(request.operation.sql, request.params || {});
|
|
109767
|
+
const compiledRequest = {
|
|
109768
|
+
...request,
|
|
109769
|
+
operation: {
|
|
109770
|
+
...request.operation,
|
|
109771
|
+
sql: compiled.text
|
|
109772
|
+
},
|
|
109773
|
+
params: Object.fromEntries(compiled.names.map((name) => [name, request.params?.[name] ?? null]))
|
|
109774
|
+
};
|
|
109775
|
+
try {
|
|
109776
|
+
return await runSqlServerIntegratedViaPowerShell(compiledRequest);
|
|
109777
|
+
} catch (error) {
|
|
109778
|
+
throw formatBuiltInDriverError("SQL Server Integrated Auth", error);
|
|
109779
|
+
}
|
|
109780
|
+
}
|
|
109576
109781
|
function isBuiltInSqlAdapter(adapterId) {
|
|
109577
109782
|
return BUILT_IN_SQL_ADAPTER_MAP.has(adapterId.toLowerCase());
|
|
109578
109783
|
}
|
|
@@ -109582,6 +109787,8 @@ async function runBuiltInSqlAdapter(adapterId, request) {
|
|
|
109582
109787
|
return runBuiltInPostgresAdapter(request);
|
|
109583
109788
|
case "sqlserver":
|
|
109584
109789
|
return runBuiltInSqlServerAdapter(request);
|
|
109790
|
+
case "sqlserver-integrated":
|
|
109791
|
+
return runBuiltInSqlServerIntegratedAdapter(request);
|
|
109585
109792
|
default:
|
|
109586
109793
|
fail(`Built-in SQL adapter '${adapterId}' is not supported`);
|
|
109587
109794
|
}
|
|
@@ -109759,7 +109966,7 @@ function resolveSqlAdapterTarget(startPath, adapterId) {
|
|
|
109759
109966
|
}
|
|
109760
109967
|
|
|
109761
109968
|
// src/sqlAdapterRunner.ts
|
|
109762
|
-
var
|
|
109969
|
+
var import_child_process3 = require("child_process");
|
|
109763
109970
|
function isRowsResult(value) {
|
|
109764
109971
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
109765
109972
|
return false;
|
|
@@ -109799,7 +110006,7 @@ async function runExternalSqlAdapter(command, request, workingDir) {
|
|
|
109799
110006
|
throw new Error("SQL adapter command is empty");
|
|
109800
110007
|
}
|
|
109801
110008
|
return new Promise((resolve11, reject) => {
|
|
109802
|
-
const child = (0,
|
|
110009
|
+
const child = (0, import_child_process3.spawn)(command[0], command.slice(1), {
|
|
109803
110010
|
cwd: workingDir,
|
|
109804
110011
|
env: process.env,
|
|
109805
110012
|
shell: false
|
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.
|
|
5
|
+
"version": "1.10.0",
|
|
6
6
|
"publisher": "Norn-PeterKrustanov",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Peter Krastanov"
|