@usecontextlayer/ctxb 0.4.11 → 0.4.13
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.mjs +24 -312
- package/dist/cli.mjs.map +1 -1
- package/package.json +4 -4
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6401b755-8e7e-5377-bff5-d539662b326a")}catch(e){}}();
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import * as Sentry from "@sentry/node";
|
|
6
6
|
import path, { posix, sep, win32 } from "node:path";
|
|
@@ -63,7 +63,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
63
63
|
|
|
64
64
|
//#endregion
|
|
65
65
|
//#region package.json
|
|
66
|
-
var version$2 = "0.4.
|
|
66
|
+
var version$2 = "0.4.13";
|
|
67
67
|
|
|
68
68
|
//#endregion
|
|
69
69
|
//#region sentry.ts
|
|
@@ -33249,7 +33249,7 @@ var require_dist = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
33249
33249
|
|
|
33250
33250
|
//#endregion
|
|
33251
33251
|
//#region gen/dagster.ts
|
|
33252
|
-
var import_dist =
|
|
33252
|
+
var import_dist = require_dist();
|
|
33253
33253
|
const DAGSTER_PARTITION_TAG = "dagster/partition";
|
|
33254
33254
|
const DAGSTER_MAX_CONCURRENT_RUNS = 10;
|
|
33255
33255
|
function pluginIdToPythonPackage(pluginId) {
|
|
@@ -33475,201 +33475,6 @@ async function runPsqlCommand(passthroughArgsInput, paths) {
|
|
|
33475
33475
|
if (psqlInvocationResult.exitCode !== 0) process.exitCode = psqlInvocationResult.exitCode;
|
|
33476
33476
|
}
|
|
33477
33477
|
|
|
33478
|
-
//#endregion
|
|
33479
|
-
//#region query/formatters.ts
|
|
33480
|
-
function formatJson(queryResult) {
|
|
33481
|
-
return JSON.stringify(queryResult);
|
|
33482
|
-
}
|
|
33483
|
-
function formatNdjson(queryResult) {
|
|
33484
|
-
const columnNames = queryResult.columns.map((column) => column.name);
|
|
33485
|
-
return queryResult.rows.map((row) => {
|
|
33486
|
-
const obj = Object.create(null);
|
|
33487
|
-
for (const [index, name] of columnNames.entries()) obj[name] = row[index];
|
|
33488
|
-
return JSON.stringify(obj);
|
|
33489
|
-
}).join("\n");
|
|
33490
|
-
}
|
|
33491
|
-
function formatBodyValue(value) {
|
|
33492
|
-
if (value === null || value === void 0) return "";
|
|
33493
|
-
if (typeof value === "string") return value;
|
|
33494
|
-
return JSON.stringify(value, null, 2);
|
|
33495
|
-
}
|
|
33496
|
-
function findDuplicateColumnNames(columns) {
|
|
33497
|
-
const counts = /* @__PURE__ */ new Map();
|
|
33498
|
-
for (const column of columns) counts.set(column.name, (counts.get(column.name) ?? 0) + 1);
|
|
33499
|
-
return Array.from(counts.entries(), ([name, count]) => ({
|
|
33500
|
-
count,
|
|
33501
|
-
name
|
|
33502
|
-
})).filter((entry) => entry.count > 1).map((entry) => entry.name);
|
|
33503
|
-
}
|
|
33504
|
-
function buildColumnNameIndex$1(columns) {
|
|
33505
|
-
return new Map(columns.map((column, index) => [column.name, index]));
|
|
33506
|
-
}
|
|
33507
|
-
function formatMarkdownRow(row, columns, bodyColumn) {
|
|
33508
|
-
const frontmatter = {};
|
|
33509
|
-
const columnNameIndex = buildColumnNameIndex$1(columns);
|
|
33510
|
-
for (const [index, column] of columns.entries()) {
|
|
33511
|
-
if (column.name === bodyColumn) continue;
|
|
33512
|
-
frontmatter[column.name] = row[index];
|
|
33513
|
-
}
|
|
33514
|
-
const yamlContent = import_dist.stringify(frontmatter).trimEnd();
|
|
33515
|
-
const bodyIndex = columnNameIndex.get(bodyColumn);
|
|
33516
|
-
if (bodyIndex === void 0) throw new Error(`body column '${bodyColumn}' not found`);
|
|
33517
|
-
return `---\n${yamlContent}\n---\n\n${formatBodyValue(row[bodyIndex])}\n`;
|
|
33518
|
-
}
|
|
33519
|
-
|
|
33520
|
-
//#endregion
|
|
33521
|
-
//#region query/markdown.ts
|
|
33522
|
-
const EDGE_PUNCTUATION_PATTERN = /^[-.]+|[-.]+$/g;
|
|
33523
|
-
const MAX_BASENAME_LENGTH = 120;
|
|
33524
|
-
const REPEATED_DASH_PATTERN = /-+/g;
|
|
33525
|
-
const UNSAFE_FILENAME_PATTERN = /[^A-Za-z0-9._-]+/g;
|
|
33526
|
-
const WHITESPACE_PATTERN = /\s+/g;
|
|
33527
|
-
function buildColumnNameIndex(columns) {
|
|
33528
|
-
return new Map(columns.map((column, index) => [column.name, index]));
|
|
33529
|
-
}
|
|
33530
|
-
function validateColumnsExist(columnNames, availableColumns) {
|
|
33531
|
-
const availableColumnNames = availableColumns.map((column) => column.name);
|
|
33532
|
-
const availableColumnsLabel = availableColumnNames.length > 0 ? availableColumnNames.join(", ") : "(none)";
|
|
33533
|
-
for (const columnName of columnNames) if (!availableColumnNames.includes(columnName)) throw new Error(`column '${columnName}' not found in query results. Available columns: ${availableColumnsLabel}`);
|
|
33534
|
-
}
|
|
33535
|
-
function describeFilenameValue(value) {
|
|
33536
|
-
if (value === null) return "null";
|
|
33537
|
-
if (value === void 0) return "undefined";
|
|
33538
|
-
if (Array.isArray(value)) return "array";
|
|
33539
|
-
if (value instanceof Date) return "date";
|
|
33540
|
-
return typeof value;
|
|
33541
|
-
}
|
|
33542
|
-
function coerceFilenameValue(columnName, rowIndex, value) {
|
|
33543
|
-
if (value instanceof Date) return value.toISOString();
|
|
33544
|
-
switch (typeof value) {
|
|
33545
|
-
case "bigint":
|
|
33546
|
-
case "boolean":
|
|
33547
|
-
case "number":
|
|
33548
|
-
case "string": return String(value);
|
|
33549
|
-
default: throw new Error(`filename column '${columnName}' in row ${rowIndex + 1} must be a non-null scalar value; got ${describeFilenameValue(value)}`);
|
|
33550
|
-
}
|
|
33551
|
-
}
|
|
33552
|
-
function replaceControlOrSeparatorRuns(value) {
|
|
33553
|
-
let normalizedValue = "";
|
|
33554
|
-
let previousWasReplacement = false;
|
|
33555
|
-
for (const character of value) {
|
|
33556
|
-
const charCode = character.charCodeAt(0);
|
|
33557
|
-
if (charCode <= 31 || charCode === 127 || character === "/" || character === "\\") {
|
|
33558
|
-
if (!previousWasReplacement) {
|
|
33559
|
-
normalizedValue += "-";
|
|
33560
|
-
previousWasReplacement = true;
|
|
33561
|
-
}
|
|
33562
|
-
continue;
|
|
33563
|
-
}
|
|
33564
|
-
normalizedValue += character;
|
|
33565
|
-
previousWasReplacement = false;
|
|
33566
|
-
}
|
|
33567
|
-
return normalizedValue;
|
|
33568
|
-
}
|
|
33569
|
-
function sanitizeFilenameSegment(columnName, rowIndex, value) {
|
|
33570
|
-
const normalizedValue = replaceControlOrSeparatorRuns(coerceFilenameValue(columnName, rowIndex, value).trim()).replace(WHITESPACE_PATTERN, "-").replace(UNSAFE_FILENAME_PATTERN, "-").replace(REPEATED_DASH_PATTERN, "-").replace(EDGE_PUNCTUATION_PATTERN, "");
|
|
33571
|
-
if (!normalizedValue || normalizedValue === "." || normalizedValue === "..") throw new Error(`filename column '${columnName}' in row ${rowIndex + 1} produced an empty or unsafe filename segment`);
|
|
33572
|
-
return normalizedValue;
|
|
33573
|
-
}
|
|
33574
|
-
function trimBasenameLength(basename) {
|
|
33575
|
-
if (basename.length <= MAX_BASENAME_LENGTH) return basename;
|
|
33576
|
-
return basename.slice(0, MAX_BASENAME_LENGTH).replace(EDGE_PUNCTUATION_PATTERN, "");
|
|
33577
|
-
}
|
|
33578
|
-
function applyCollisionSuffix(basename, count) {
|
|
33579
|
-
const suffix = `__${String(count).padStart(3, "0")}`;
|
|
33580
|
-
const maxStemLength = MAX_BASENAME_LENGTH - suffix.length;
|
|
33581
|
-
const trimmedStem = basename.slice(0, maxStemLength).replace(EDGE_PUNCTUATION_PATTERN, "");
|
|
33582
|
-
return `${trimmedStem.length > 0 ? trimmedStem : "file"}${suffix}`;
|
|
33583
|
-
}
|
|
33584
|
-
function deduplicateBasenames(basenames) {
|
|
33585
|
-
const counts = /* @__PURE__ */ new Map();
|
|
33586
|
-
return basenames.map((basename) => {
|
|
33587
|
-
const count = counts.get(basename) ?? 0;
|
|
33588
|
-
counts.set(basename, count + 1);
|
|
33589
|
-
if (count === 0) return basename;
|
|
33590
|
-
return applyCollisionSuffix(basename, count);
|
|
33591
|
-
});
|
|
33592
|
-
}
|
|
33593
|
-
function buildSafeBasename(row, rowIndex, columnNameIndex, filenameColumns) {
|
|
33594
|
-
const rawFilenameValues = filenameColumns.map((columnName) => {
|
|
33595
|
-
const columnIndex = columnNameIndex.get(columnName);
|
|
33596
|
-
if (columnIndex === void 0) throw new Error(`filename column '${columnName}' not found`);
|
|
33597
|
-
return row[columnIndex];
|
|
33598
|
-
});
|
|
33599
|
-
const safeBasename = trimBasenameLength(filenameColumns.map((columnName) => {
|
|
33600
|
-
const columnIndex = columnNameIndex.get(columnName);
|
|
33601
|
-
if (columnIndex === void 0) throw new Error(`filename column '${columnName}' not found`);
|
|
33602
|
-
return sanitizeFilenameSegment(columnName, rowIndex, row[columnIndex]);
|
|
33603
|
-
}).join("__"));
|
|
33604
|
-
if (!safeBasename || safeBasename === "." || safeBasename === "..") throw new Error(`row ${rowIndex + 1} produced an empty or unsafe markdown basename`);
|
|
33605
|
-
return {
|
|
33606
|
-
rawFilenameValues,
|
|
33607
|
-
safeBasename
|
|
33608
|
-
};
|
|
33609
|
-
}
|
|
33610
|
-
function planMarkdownFiles(options) {
|
|
33611
|
-
const columnNameIndex = buildColumnNameIndex(options.columns);
|
|
33612
|
-
const plannedFiles = options.rows.map((row, rowIndex) => {
|
|
33613
|
-
const { rawFilenameValues, safeBasename } = buildSafeBasename(row, rowIndex, columnNameIndex, options.filenameColumns);
|
|
33614
|
-
return {
|
|
33615
|
-
content: formatMarkdownRow(row, options.columns, options.bodyColumn),
|
|
33616
|
-
rawFilenameValues,
|
|
33617
|
-
rowIndex,
|
|
33618
|
-
safeBasename
|
|
33619
|
-
};
|
|
33620
|
-
});
|
|
33621
|
-
const uniqueBasenames = deduplicateBasenames(plannedFiles.map((plannedFile) => plannedFile.safeBasename));
|
|
33622
|
-
return plannedFiles.map((plannedFile, index) => {
|
|
33623
|
-
const uniqueBasename = uniqueBasenames[index];
|
|
33624
|
-
if (uniqueBasename === void 0) throw new Error("markdown basename planning lost row alignment");
|
|
33625
|
-
return {
|
|
33626
|
-
...plannedFile,
|
|
33627
|
-
relativePath: `${uniqueBasename}.md`,
|
|
33628
|
-
safeBasename: uniqueBasename
|
|
33629
|
-
};
|
|
33630
|
-
});
|
|
33631
|
-
}
|
|
33632
|
-
function resolveMarkdownOutputPath(outputDir, relativePath) {
|
|
33633
|
-
const resolvedOutputPath = path.resolve(outputDir, relativePath);
|
|
33634
|
-
const relativeOutputPath = path.relative(outputDir, resolvedOutputPath);
|
|
33635
|
-
if (relativeOutputPath.startsWith("..") || path.isAbsolute(relativeOutputPath)) throw new Error(`planned markdown output path escapes output directory: ${relativePath}`);
|
|
33636
|
-
return resolvedOutputPath;
|
|
33637
|
-
}
|
|
33638
|
-
function planMarkdownOutput(queryResult, options) {
|
|
33639
|
-
const duplicateColumnNames = findDuplicateColumnNames(queryResult.columns);
|
|
33640
|
-
if (duplicateColumnNames.length > 0) throw new Error(`markdown output requires unique column names. Duplicate columns: ${duplicateColumnNames.join(", ")}`);
|
|
33641
|
-
const columnsToValidate = [options.bodyColumn];
|
|
33642
|
-
if (options.output === "dir") columnsToValidate.push(...options.filenameColumns);
|
|
33643
|
-
validateColumnsExist(columnsToValidate, queryResult.columns);
|
|
33644
|
-
if (options.output === "stdout") {
|
|
33645
|
-
if (queryResult.rows.length !== 1) throw new Error(`markdown stdout output requires exactly 1 row; got ${queryResult.rows.length}. Use --md-output-mode dir with --md-output-dir and --md-filename-columns for multi-row output.`);
|
|
33646
|
-
const [row] = queryResult.rows;
|
|
33647
|
-
if (row === void 0) throw new Error("expected a single row for markdown stdout output");
|
|
33648
|
-
return {
|
|
33649
|
-
document: formatMarkdownRow(row, queryResult.columns, options.bodyColumn),
|
|
33650
|
-
output: "stdout"
|
|
33651
|
-
};
|
|
33652
|
-
}
|
|
33653
|
-
return {
|
|
33654
|
-
files: planMarkdownFiles({
|
|
33655
|
-
bodyColumn: options.bodyColumn,
|
|
33656
|
-
columns: queryResult.columns,
|
|
33657
|
-
filenameColumns: options.filenameColumns,
|
|
33658
|
-
rows: queryResult.rows
|
|
33659
|
-
}),
|
|
33660
|
-
output: "dir",
|
|
33661
|
-
outputDir: path.resolve(options.outputDir)
|
|
33662
|
-
};
|
|
33663
|
-
}
|
|
33664
|
-
async function writeMarkdownDirectory(plan) {
|
|
33665
|
-
await mkdir(plan.outputDir, { recursive: true });
|
|
33666
|
-
for (const plannedFile of plan.files) await writeFile(resolveMarkdownOutputPath(plan.outputDir, plannedFile.relativePath), plannedFile.content, "utf8");
|
|
33667
|
-
return {
|
|
33668
|
-
fileCount: plan.files.length,
|
|
33669
|
-
outputDir: plan.outputDir
|
|
33670
|
-
};
|
|
33671
|
-
}
|
|
33672
|
-
|
|
33673
33478
|
//#endregion
|
|
33674
33479
|
//#region query/runtime.ts
|
|
33675
33480
|
async function executeQuery(queryText, resolvePaths) {
|
|
@@ -33681,12 +33486,7 @@ async function executeQuery(queryText, resolvePaths) {
|
|
|
33681
33486
|
return await sql.begin("read only", async (transactionSql) => {
|
|
33682
33487
|
const result = await transactionSql.unsafe(queryText).values();
|
|
33683
33488
|
return {
|
|
33684
|
-
columns: result.columns.map((column) =>
|
|
33685
|
-
name: column.name,
|
|
33686
|
-
typeOid: column.type
|
|
33687
|
-
})),
|
|
33688
|
-
command: result.command,
|
|
33689
|
-
count: result.count,
|
|
33489
|
+
columns: result.columns.map((column) => column.name),
|
|
33690
33490
|
rows: Array.from(result, (row) => Array.from(row))
|
|
33691
33491
|
};
|
|
33692
33492
|
});
|
|
@@ -33697,116 +33497,28 @@ async function executeQuery(queryText, resolvePaths) {
|
|
|
33697
33497
|
|
|
33698
33498
|
//#endregion
|
|
33699
33499
|
//#region query/command.ts
|
|
33700
|
-
|
|
33701
|
-
|
|
33702
|
-
|
|
33703
|
-
|
|
33704
|
-
|
|
33705
|
-
|
|
33706
|
-
mdBodyColumn: string().trim().min(1).optional(),
|
|
33707
|
-
mdFilenameColumns: array(string().trim().min(1)).optional(),
|
|
33708
|
-
mdOutputDir: string().trim().min(1).optional(),
|
|
33709
|
-
mdOutputMode: _enum(["stdout", "dir"]).optional()
|
|
33710
|
-
}).superRefine((input, ctx) => {
|
|
33711
|
-
if (input.format === "json" || input.format === "ndjson") {
|
|
33712
|
-
if (input.mdBodyColumn || input.mdFilenameColumns || input.mdOutputDir || input.mdOutputMode !== void 0) ctx.addIssue({
|
|
33713
|
-
code: "custom",
|
|
33714
|
-
message: "--md-body-column, --md-filename-columns, --md-output-mode, and --md-output-dir are only supported with --format md",
|
|
33715
|
-
path: ["format"]
|
|
33716
|
-
});
|
|
33717
|
-
return;
|
|
33718
|
-
}
|
|
33719
|
-
if (!input.mdBodyColumn) ctx.addIssue({
|
|
33720
|
-
code: "custom",
|
|
33721
|
-
message: "--md-body-column is required with --format md",
|
|
33722
|
-
path: ["mdBodyColumn"]
|
|
33723
|
-
});
|
|
33724
|
-
if ((input.mdOutputMode ?? "stdout") === "stdout") {
|
|
33725
|
-
if (input.mdFilenameColumns || input.mdOutputDir) ctx.addIssue({
|
|
33726
|
-
code: "custom",
|
|
33727
|
-
message: "markdown stdout output does not accept --md-filename-columns or --md-output-dir",
|
|
33728
|
-
path: ["mdOutputMode"]
|
|
33729
|
-
});
|
|
33730
|
-
return;
|
|
33731
|
-
}
|
|
33732
|
-
if (!input.mdFilenameColumns || !input.mdOutputDir) ctx.addIssue({
|
|
33733
|
-
code: "custom",
|
|
33734
|
-
message: "--md-output-mode dir requires both --md-filename-columns and --md-output-dir",
|
|
33735
|
-
path: [input.mdFilenameColumns ? "mdOutputDir" : "mdFilenameColumns"]
|
|
33736
|
-
});
|
|
33737
|
-
});
|
|
33738
|
-
function writeError(message) {
|
|
33739
|
-
process.stderr.write(`${message}\n`);
|
|
33740
|
-
process.exitCode = 1;
|
|
33741
|
-
}
|
|
33742
|
-
function parseQueryOptions(optionsInput) {
|
|
33743
|
-
const parseResult = queryOptionsSchema.safeParse(optionsInput);
|
|
33744
|
-
if (!parseResult.success) {
|
|
33745
|
-
const firstIssue = parseResult.error.issues[0];
|
|
33746
|
-
if (firstIssue) writeError(firstIssue.message);
|
|
33747
|
-
return null;
|
|
33748
|
-
}
|
|
33749
|
-
const options = parseResult.data;
|
|
33750
|
-
if (options.format === "json") return { format: "json" };
|
|
33751
|
-
if (options.format === "ndjson") return { format: "ndjson" };
|
|
33752
|
-
if (options.mdBodyColumn === void 0) throw new Error("markdown options missing mdBodyColumn after validation");
|
|
33753
|
-
if ((options.mdOutputMode ?? "stdout") === "stdout") return {
|
|
33754
|
-
format: "md",
|
|
33755
|
-
mdBodyColumn: options.mdBodyColumn,
|
|
33756
|
-
mdOutputMode: "stdout"
|
|
33757
|
-
};
|
|
33758
|
-
if (options.mdFilenameColumns === void 0 || options.mdOutputDir === void 0) throw new Error("markdown directory options missing after validation");
|
|
33759
|
-
return {
|
|
33760
|
-
format: "md",
|
|
33761
|
-
mdBodyColumn: options.mdBodyColumn,
|
|
33762
|
-
mdFilenameColumns: options.mdFilenameColumns,
|
|
33763
|
-
mdOutputDir: options.mdOutputDir,
|
|
33764
|
-
mdOutputMode: "dir"
|
|
33765
|
-
};
|
|
33500
|
+
function formatNdjson(queryResult) {
|
|
33501
|
+
return queryResult.rows.map((row) => {
|
|
33502
|
+
const obj = Object.create(null);
|
|
33503
|
+
for (const [index, name] of queryResult.columns.entries()) obj[name] = row[index];
|
|
33504
|
+
return JSON.stringify(obj);
|
|
33505
|
+
}).join("\n");
|
|
33766
33506
|
}
|
|
33767
|
-
function
|
|
33768
|
-
|
|
33769
|
-
|
|
33770
|
-
|
|
33771
|
-
};
|
|
33772
|
-
return {
|
|
33773
|
-
bodyColumn: options.mdBodyColumn,
|
|
33774
|
-
filenameColumns: options.mdFilenameColumns,
|
|
33775
|
-
output: "dir",
|
|
33776
|
-
outputDir: options.mdOutputDir
|
|
33777
|
-
};
|
|
33507
|
+
function findDuplicateColumnNames(columns) {
|
|
33508
|
+
const counts = /* @__PURE__ */ new Map();
|
|
33509
|
+
for (const name of columns) counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
33510
|
+
return Array.from(counts).filter(([, count]) => count > 1).map(([name]) => name);
|
|
33778
33511
|
}
|
|
33779
|
-
async function runQueryCommand(sql,
|
|
33780
|
-
const options = parseQueryOptions(optionsInput);
|
|
33781
|
-
if (!options) return;
|
|
33512
|
+
async function runQueryCommand(sql, resolvePaths) {
|
|
33782
33513
|
const queryResult = await executeQuery(sql, resolvePaths);
|
|
33783
|
-
|
|
33784
|
-
|
|
33785
|
-
|
|
33786
|
-
|
|
33787
|
-
if (options.format === "ndjson") {
|
|
33788
|
-
const duplicateColumnNames = findDuplicateColumnNames(queryResult.columns);
|
|
33789
|
-
if (duplicateColumnNames.length > 0) {
|
|
33790
|
-
writeError(`ndjson output requires unique column names. Duplicate columns: ${duplicateColumnNames.join(", ")}`);
|
|
33791
|
-
return;
|
|
33792
|
-
}
|
|
33793
|
-
const ndjsonOutput = formatNdjson(queryResult);
|
|
33794
|
-
if (ndjsonOutput.length > 0) process.stdout.write(`${ndjsonOutput}\n`);
|
|
33795
|
-
return;
|
|
33796
|
-
}
|
|
33797
|
-
let markdownOutputPlan;
|
|
33798
|
-
try {
|
|
33799
|
-
markdownOutputPlan = planMarkdownOutput(queryResult, toMarkdownOutputOptions(options));
|
|
33800
|
-
} catch (error) {
|
|
33801
|
-
writeError(error instanceof Error ? error.message : String(error));
|
|
33802
|
-
return;
|
|
33803
|
-
}
|
|
33804
|
-
if (markdownOutputPlan.output === "stdout") {
|
|
33805
|
-
process.stdout.write(markdownOutputPlan.document);
|
|
33514
|
+
const duplicateColumnNames = findDuplicateColumnNames(queryResult.columns);
|
|
33515
|
+
if (duplicateColumnNames.length > 0) {
|
|
33516
|
+
process.stderr.write(`ndjson output requires unique column names. Duplicate columns: ${duplicateColumnNames.join(", ")}\n`);
|
|
33517
|
+
process.exitCode = 1;
|
|
33806
33518
|
return;
|
|
33807
33519
|
}
|
|
33808
|
-
const
|
|
33809
|
-
process.stdout.write(`${
|
|
33520
|
+
const ndjsonOutput = formatNdjson(queryResult);
|
|
33521
|
+
if (ndjsonOutput.length > 0) process.stdout.write(`${ndjsonOutput}\n`);
|
|
33810
33522
|
}
|
|
33811
33523
|
|
|
33812
33524
|
//#endregion
|
|
@@ -34044,8 +33756,8 @@ function createProgram() {
|
|
|
34044
33756
|
program.command("encode-uri <value>").description("URL-encode a value with JavaScript encodeURIComponent").action(async function(value) {
|
|
34045
33757
|
await runEncodeUriCommand(value);
|
|
34046
33758
|
});
|
|
34047
|
-
program.command("query <sql>").description("Execute a SQL statement against the resolved project database and
|
|
34048
|
-
await runQueryCommand(sql,
|
|
33759
|
+
program.command("query <sql>").description("Execute a SQL statement against the resolved project database and write results to stdout as NDJSON (one row per line; requires unique column names).").action(async function(sql) {
|
|
33760
|
+
await runQueryCommand(sql, () => resolveRuntimePaths(this));
|
|
34049
33761
|
});
|
|
34050
33762
|
const pgxCommand = program.command("pgx").description("Passthrough to the managed pgx binary (project-local Postgres) with inherited stdio. Runs with PGX_DATA_DIR=<project-root>/.base/db; `pgx start --daemon` writes data.pgx-state.json and data.pgx-password sidecars under that dir which the CLI's database URL resolver reads (unless CTXB_DATABASE_URL is set). Use `--` before any flag ctxb itself defines (e.g. --help) to pass it through to pgx.");
|
|
34051
33763
|
pgxCommand.allowUnknownOption(true).allowExcessArguments(true);
|
|
@@ -34100,4 +33812,4 @@ runCli().catch((error) => {
|
|
|
34100
33812
|
//#endregion
|
|
34101
33813
|
export { createProgram, runCli };
|
|
34102
33814
|
//# sourceMappingURL=cli.mjs.map
|
|
34103
|
-
//# debugId=
|
|
33815
|
+
//# debugId=6401b755-8e7e-5377-bff5-d539662b326a
|