@usecontextlayer/ctxb 0.4.12 → 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 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]="ef079c22-d6b0-5302-9831-a7cf8d1b8bd9")}catch(e){}}();
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.12";
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 = /* @__PURE__ */ __toESM(require_dist(), 1);
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
- const queryOptionsSchema = strictObject({
33701
- format: _enum([
33702
- "json",
33703
- "md",
33704
- "ndjson"
33705
- ]).default("ndjson"),
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 toMarkdownOutputOptions(options) {
33768
- if (options.mdOutputMode === "stdout") return {
33769
- bodyColumn: options.mdBodyColumn,
33770
- output: "stdout"
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, optionsInput, resolvePaths) {
33780
- const options = parseQueryOptions(optionsInput);
33781
- if (!options) return;
33512
+ async function runQueryCommand(sql, resolvePaths) {
33782
33513
  const queryResult = await executeQuery(sql, resolvePaths);
33783
- if (options.format === "json") {
33784
- process.stdout.write(`${formatJson(queryResult)}\n`);
33785
- return;
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 writeResult = await writeMarkdownDirectory(markdownOutputPlan);
33809
- process.stdout.write(`${writeResult.fileCount} files written to ${writeResult.outputDir}\n`);
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 stream results to stdout as NDJSON (default; requires unique column names), JSON, or markdown (stdout or per-row files).").option("--format <format>", "Output format: ndjson, json, or md (default: ndjson)").option("--md-body-column <column>", "Column to use as markdown body").option("--md-output-mode <mode>", "Markdown output mode: stdout or dir (default: stdout)").option("--md-filename-columns <columns...>", "Column(s) for markdown filenames").option("--md-output-dir <path>", "Directory for markdown file output").action(async function(sql, options) {
34048
- await runQueryCommand(sql, options, () => resolveRuntimePaths(this));
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=ef079c22-d6b0-5302-9831-a7cf8d1b8bd9
33815
+ //# debugId=6401b755-8e7e-5377-bff5-d539662b326a