@noormdev/sdk 1.0.0-alpha.16 → 1.0.0-alpha.18

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.
@@ -100,8 +100,6 @@ async function loadSql(filepath) {
100
100
 
101
101
  // src/core/dt/constants.ts
102
102
  var FORMAT_VERSION = 1;
103
- var GZIP_THRESHOLD = 128;
104
- var GZIP_RATIO_THRESHOLD = 0.85;
105
103
  var ENCODED_TYPES = {
106
104
  json: true,
107
105
  binary: true,
@@ -414,7 +412,7 @@ function createIncludeHelper(templateDir, projectRoot, options) {
414
412
  throw new Error(`Include path escapes project root: ${includePath}`);
415
413
  }
416
414
  if (resolved.endsWith(".tmpl")) {
417
- const { processFile: processFile2 } = await import('./engine-5K7FA66A.js');
415
+ const { processFile: processFile2 } = await import('./engine-IFYFFWFR.js');
418
416
  const result = await processFile2(resolved, options);
419
417
  return result.sql;
420
418
  }
@@ -479,6 +477,6 @@ async function processFiles(filepaths, options = {}) {
479
477
  return results;
480
478
  }
481
479
 
482
- export { DT_EXTENSIONS, DtReader, ENCODED_TYPES, FORMAT_VERSION, GZIP_RATIO_THRESHOLD, GZIP_THRESHOLD, encryptWithPassphrase, eta, isTemplate, processFile, processFiles, renderTemplate };
483
- //# sourceMappingURL=chunk-BTXUEWYQ.js.map
484
- //# sourceMappingURL=chunk-BTXUEWYQ.js.map
480
+ export { DT_EXTENSIONS, DtReader, ENCODED_TYPES, FORMAT_VERSION, encryptWithPassphrase, eta, isTemplate, processFile, processFiles, renderTemplate };
481
+ //# sourceMappingURL=chunk-KF7GE2VM.js.map
482
+ //# sourceMappingURL=chunk-KF7GE2VM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/template/types.ts","../../../src/core/template/loaders/js.ts","../../../src/core/template/helpers.ts","../../../src/core/template/loaders/json5.ts","../../../src/core/template/loaders/yaml.ts","../../../src/core/template/loaders/csv.ts","../../../src/core/template/loaders/sql.ts","../../../src/core/dt/constants.ts","../../../src/core/dt/crypto.ts","../../../src/core/dt/reader.ts","../../../src/core/template/loaders/dt.ts","../../../src/core/template/loaders/index.ts","../../../src/core/template/utils.ts","../../../src/core/template/context.ts","../../../src/core/template/engine.ts"],"names":["exports","JSON5","readFile","parse","path","attempt","processFile"],"mappings":"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","file":"chunk-KF7GE2VM.js","sourcesContent":["/**\n * Template engine types.\n *\n * Defines the context object ($) available in templates, loader interfaces,\n * and configuration options for the template engine.\n */\n\n/**\n * Built-in helper functions available on the template context.\n */\nexport interface BuiltInHelpers {\n /**\n * Include another SQL file.\n * Path is resolved relative to the template's directory.\n *\n * @example\n * ```sql\n * {%~ await $.include('lib/uuid_function.sql') %}\n * ```\n */\n include: (path: string) => Promise<string>;\n\n /**\n * SQL-escape a string value.\n * Escapes single quotes by doubling them.\n *\n * @example\n * ```sql\n * WHERE name = '{%~ $.escape(userName) %}'\n * ```\n */\n escape: (value: string) => string;\n\n /**\n * SQL-escape and wrap in single quotes.\n *\n * @example\n * ```sql\n * INSERT INTO users (name) VALUES ({%~ $.quote(userName) %});\n * ```\n */\n quote: (value: string | number | boolean | null) => string;\n\n /**\n * JSON stringify a value.\n *\n * @example\n * ```sql\n * INSERT INTO config (data) VALUES ('{%~ $.json(configObject) %}');\n * ```\n */\n json: (value: unknown) => string;\n\n /**\n * Current ISO timestamp.\n *\n * @example\n * ```sql\n * INSERT INTO logs (created_at) VALUES ('{%~ $.now() %}');\n * ```\n */\n now: () => string;\n\n /**\n * Generate a UUID v4.\n *\n * @example\n * ```sql\n * INSERT INTO users (id) VALUES ('{%~ $.uuid() %}');\n * ```\n */\n uuid: () => string;\n}\n\n/**\n * Template context object ($) available in templates.\n *\n * Contains auto-loaded data, inherited helpers, secrets, and built-in functions.\n */\nexport interface TemplateContext extends BuiltInHelpers {\n /**\n * Active configuration object.\n * Only available if no `config.*` file exists in the template directory.\n */\n config?: Record<string, unknown>;\n\n /**\n * Decrypted secrets for the active config.\n */\n secrets: Record<string, string>;\n\n /**\n * Decrypted global secrets (shared across configs).\n */\n globalSecrets: Record<string, string>;\n\n /**\n * Environment variables.\n */\n env: Record<string, string | undefined>;\n\n /**\n * Auto-loaded data files and inherited helpers.\n * Keys are camelCased filenames (e.g., `$.users`, `$.seedData`).\n */\n [key: string]: unknown;\n}\n\n/**\n * Result from a data loader.\n */\nexport interface LoaderResult {\n /**\n * The parsed data.\n */\n data: unknown;\n\n /**\n * Original file path.\n */\n filepath: string;\n\n /**\n * File extension (e.g., '.json5', '.yml').\n */\n format: string;\n}\n\n/**\n * A data file loader function.\n */\nexport type Loader = (filepath: string) => Promise<unknown>;\n\n/**\n * Registry of loaders by file extension.\n */\nexport type LoaderRegistry = Record<string, Loader>;\n\n/**\n * Options for rendering a template.\n */\nexport interface RenderOptions {\n /**\n * Active configuration to include in context.\n */\n config?: Record<string, unknown>;\n\n /**\n * Secrets for the active config.\n */\n secrets?: Record<string, string>;\n\n /**\n * Global secrets shared across configs.\n */\n globalSecrets?: Record<string, string>;\n\n /**\n * Project root directory.\n * Used to determine where to stop walking up for helpers.\n * Defaults to process.cwd().\n */\n projectRoot?: string;\n}\n\n/**\n * Result of processing a SQL file.\n */\nexport interface ProcessResult {\n /**\n * The SQL content (rendered if template, raw if .sql).\n */\n sql: string;\n\n /**\n * Whether the file was a template.\n */\n isTemplate: boolean;\n\n /**\n * Render duration in milliseconds (only for templates).\n */\n durationMs?: number;\n}\n\n/**\n * Supported data file extensions.\n */\nexport const DATA_EXTENSIONS = [\n '.json',\n '.json5',\n '.yaml',\n '.yml',\n '.csv',\n '.js',\n '.mjs',\n '.ts',\n '.sql',\n] as const;\n\n/**\n * Template file extension.\n */\nexport const TEMPLATE_EXTENSION = '.tmpl';\n\n/**\n * Helper file name pattern.\n */\nexport const HELPER_FILENAME = '$helpers';\n\n/**\n * Supported helper file extensions.\n */\nexport const HELPER_EXTENSIONS = ['.ts', '.js', '.mjs'] as const;\n","/**\n * JavaScript/TypeScript module loader.\n *\n * Loads .js, .mjs, and .ts files via dynamic import.\n * Returns module.default if available, otherwise the entire module.\n *\n * @example\n * ```typescript\n * const data = await loadJs('/path/to/helpers.ts')\n * ```\n */\nimport { pathToFileURL } from 'node:url';\n\n/**\n * Load a JavaScript or TypeScript module.\n *\n * Uses dynamic import to load the module. If the module has a default\n * export, returns that. Otherwise returns the entire module object.\n *\n * @param filepath - Absolute path to the JS/TS file\n * @returns The module's default export or the entire module\n * @throws If file cannot be imported\n */\nexport async function loadJs(filepath: string): Promise<unknown> {\n\n // Convert to file URL for cross-platform compatibility\n const url = pathToFileURL(filepath).href;\n\n // Add cache-busting query param to avoid stale imports\n const urlWithCacheBust = `${url}?t=${Date.now()}`;\n\n const mod = await import(urlWithCacheBust);\n\n // Return default export if available, otherwise the whole module\n return mod.default !== undefined ? mod.default : mod;\n\n}\n","/**\n * Helper file tree walker.\n *\n * Walks up the directory tree from a template's location to the project root,\n * collecting and merging $helpers.ts files. Child helpers override parent helpers.\n *\n * @example\n * ```typescript\n * import { loadHelpers } from './helpers'\n *\n * // Given structure:\n * // sql/\n * // ├── $helpers.ts ← loaded first (base)\n * // └── users/\n * // ├── $helpers.ts ← loaded second (overrides)\n * // └── 001_create.sql.tmpl\n *\n * const helpers = await loadHelpers('/project/sql/users', '/project')\n * // helpers contains merged exports from both files\n * ```\n */\nimport path from 'node:path';\nimport { stat } from 'node:fs/promises';\n\nimport { attempt } from '@logosdx/utils';\n\nimport { observer } from '../observer.js';\nimport { HELPER_FILENAME, HELPER_EXTENSIONS } from './types.js';\nimport { loadJs } from './loaders/js.js';\n\n/**\n * Find all helper files from a directory up to the project root.\n *\n * Returns paths in order from root to leaf (so child can override parent).\n *\n * @param fromDir - Starting directory (template's directory)\n * @param projectRoot - Project root directory (stop walking here)\n * @returns Array of helper file paths, ordered root to leaf\n */\nexport async function findHelperFiles(fromDir: string, projectRoot: string): Promise<string[]> {\n\n const helperPaths: string[] = [];\n let currentDir = path.resolve(fromDir);\n const root = path.resolve(projectRoot);\n\n // Walk up until we reach or pass the project root\n while (currentDir.startsWith(root)) {\n\n const helperPath = await findHelperInDir(currentDir);\n\n if (helperPath) {\n\n // Prepend so we get root-to-leaf order\n helperPaths.unshift(helperPath);\n\n }\n\n // Move up one directory\n const parentDir = path.dirname(currentDir);\n\n // Stop if we've reached the root or can't go higher\n if (parentDir === currentDir) {\n\n break;\n\n }\n\n currentDir = parentDir;\n\n }\n\n return helperPaths;\n\n}\n\n/**\n * Find a helper file in a directory.\n *\n * Checks for $helpers.ts, $helpers.js, $helpers.mjs in order.\n *\n * @param dir - Directory to search\n * @returns Path to helper file if found, null otherwise\n */\nasync function findHelperInDir(dir: string): Promise<string | null> {\n\n for (const ext of HELPER_EXTENSIONS) {\n\n const filepath = path.join(dir, `${HELPER_FILENAME}${ext}`);\n const [stats] = await attempt(() => stat(filepath));\n\n if (stats?.isFile()) {\n\n return filepath;\n\n }\n\n }\n\n return null;\n\n}\n\n/**\n * Load and merge helper files from a directory tree.\n *\n * Walks up from the template directory to the project root, loading each\n * $helpers.ts file found. Later helpers (closer to template) override\n * earlier helpers (closer to root).\n *\n * @param fromDir - Template's directory\n * @param projectRoot - Project root directory\n * @returns Merged helper exports\n *\n * @example\n * ```typescript\n * const helpers = await loadHelpers('/project/sql/users', '/project')\n * // helpers.padId() from sql/users/$helpers.ts\n * // helpers.formatDate() from sql/$helpers.ts\n * ```\n */\nexport async function loadHelpers(\n fromDir: string,\n projectRoot: string,\n): Promise<Record<string, unknown>> {\n\n const helperPaths = await findHelperFiles(fromDir, projectRoot);\n const merged: Record<string, unknown> = {};\n\n for (const filepath of helperPaths) {\n\n const [mod, err] = await attempt(() => loadJs(filepath));\n\n if (err) {\n\n observer.emit('error', {\n source: 'template',\n error: err,\n context: { filepath, operation: 'load-helpers' },\n });\n continue;\n\n }\n\n // Merge exports (later files override earlier)\n if (mod && typeof mod === 'object') {\n\n const exports = mod as Record<string, unknown>;\n const exportCount = Object.keys(exports).length;\n\n Object.assign(merged, exports);\n\n observer.emit('template:helpers', {\n filepath,\n count: exportCount,\n });\n\n }\n\n }\n\n return merged;\n\n}\n","/**\n * JSON5 data loader.\n *\n * Loads .json and .json5 files using the JSON5 parser, which supports:\n * - Comments (single-line and block)\n * - Trailing commas\n * - Unquoted keys\n * - Single-quoted strings\n * - Multi-line strings\n *\n * @example\n * ```typescript\n * const data = await loadJson5('/path/to/config.json5')\n * ```\n */\nimport { readFile } from 'node:fs/promises';\n\nimport JSON5 from 'json5';\n\n/**\n * Load and parse a JSON5 file.\n *\n * @param filepath - Absolute path to the JSON5 file\n * @returns Parsed JSON5 data\n * @throws If file cannot be read or parsed\n */\nexport async function loadJson5(filepath: string): Promise<unknown> {\n\n const content = await readFile(filepath, 'utf-8');\n\n return JSON5.parse(content);\n\n}\n","/**\n * YAML data loader.\n *\n * Loads .yaml and .yml files using the yaml parser.\n *\n * @example\n * ```typescript\n * const data = await loadYaml('/path/to/config.yml')\n * ```\n */\nimport { readFile } from 'node:fs/promises';\n\nimport { parse } from 'yaml';\n\n/**\n * Load and parse a YAML file.\n *\n * @param filepath - Absolute path to the YAML file\n * @returns Parsed YAML data\n * @throws If file cannot be read or parsed\n */\nexport async function loadYaml(filepath: string): Promise<unknown> {\n\n const content = await readFile(filepath, 'utf-8');\n\n return parse(content);\n\n}\n","/**\n * CSV data loader.\n *\n * Loads .csv files using csv-parse with headers.\n * Returns an array of objects where keys are column headers.\n *\n * @example\n * ```typescript\n * const data = await loadCsv('/path/to/users.csv')\n * // → [{ name: 'Alice', email: 'alice@example.com' }, ...]\n * ```\n */\nimport { readFile } from 'node:fs/promises';\n\nimport { parse } from 'csv-parse/sync';\n\n/**\n * Load and parse a CSV file.\n *\n * @param filepath - Absolute path to the CSV file\n * @returns Array of row objects with header keys\n * @throws If file cannot be read or parsed\n */\nexport async function loadCsv(filepath: string): Promise<Record<string, string>[]> {\n\n const content = await readFile(filepath, 'utf-8');\n\n return parse(content, {\n columns: true,\n skip_empty_lines: true,\n trim: true,\n });\n\n}\n","/**\n * SQL file loader.\n *\n * Loads .sql files as raw text strings.\n * Used for including SQL fragments in templates.\n *\n * @example\n * ```typescript\n * const sql = await loadSql('/path/to/fragment.sql')\n * ```\n */\nimport { readFile } from 'node:fs/promises';\n\n/**\n * Load a SQL file as text.\n *\n * @param filepath - Absolute path to the SQL file\n * @returns The SQL file content as a string\n * @throws If file cannot be read\n */\nexport async function loadSql(filepath: string): Promise<string> {\n\n return readFile(filepath, 'utf-8');\n\n}\n","/**\n * Constants for the .dt format.\n *\n * Defines thresholds for smart compression decisions and type classification sets.\n */\nimport type { EncodedType, SimpleType } from './types.js';\n\n/**\n * Current .dt format version.\n */\nexport const FORMAT_VERSION = 1;\n\n/**\n * Minimum byte size before considering gzip compression.\n *\n * Values smaller than this threshold remain uncompressed for readability.\n * 128 bytes is the sweet spot: below this, gzip overhead exceeds savings.\n */\nexport const GZIP_THRESHOLD = 128;\n\n/**\n * Maximum gzip-to-raw ratio to accept compression.\n *\n * Gzip must save at least 15% (ratio < 0.85) to be worth the overhead.\n * Incompressible data (random bytes, already-compressed content) stays raw.\n */\nexport const GZIP_RATIO_THRESHOLD = 0.85;\n\n/**\n * Simple types stored as native JSON values.\n *\n * Uses boolean hash for O(1) lookups.\n */\nexport const SIMPLE_TYPES: { [key in SimpleType]: true } = {\n string: true,\n int: true,\n bigint: true,\n float: true,\n decimal: true,\n bool: true,\n timestamp: true,\n date: true,\n uuid: true,\n};\n\n/**\n * Encoded types that use `[value, encoding]` tuples.\n *\n * Uses boolean hash for O(1) lookups.\n */\nexport const ENCODED_TYPES: { [key in EncodedType]: true } = {\n json: true,\n binary: true,\n vector: true,\n array: true,\n text: true,\n custom: true,\n};\n\n/**\n * Valid .dt file extensions.\n */\nexport const DT_EXTENSIONS = {\n /** Raw .dt file (uncompressed JSON5 lines). */\n RAW: '.dt',\n /** Gzip-compressed .dt file. */\n COMPRESSED: '.dtz',\n /** Gzip-compressed and AES-256-GCM encrypted .dt file. */\n ENCRYPTED: '.dtzx',\n} as const;\n\n/**\n * Supported database dialects for .dt operations.\n */\nexport const DT_SUPPORTED_DIALECTS = ['postgres', 'mysql', 'mssql'] as const;\n","/**\n * Passphrase-based encryption for .dtzx files.\n *\n * Self-contained AES-256-GCM encryption using PBKDF2 key derivation.\n * Independent of the identity system — uses a user-provided passphrase.\n *\n * @example\n * ```typescript\n * import { encryptWithPassphrase, decryptWithPassphrase } from './crypto.js';\n *\n * const payload = encryptWithPassphrase(data, 'my-secret');\n * const decrypted = decryptWithPassphrase(payload, 'my-secret');\n * ```\n */\nimport {\n createCipheriv,\n createDecipheriv,\n randomBytes,\n pbkdf2Sync,\n} from 'node:crypto';\n\nimport type { DtEncryptedPayload } from './types.js';\n\nconst ALGORITHM = 'aes-256-gcm';\nconst IV_LENGTH = 16;\nconst SALT_LENGTH = 32;\nconst AUTH_TAG_LENGTH = 16;\nconst KEY_LENGTH = 32;\nconst PBKDF2_ITERATIONS = 100_000;\nconst PBKDF2_DIGEST = 'sha256';\n\n/**\n * Encrypt data with a passphrase using AES-256-GCM.\n *\n * Derives a key from the passphrase using PBKDF2 with a random salt.\n * Each call generates a new salt and IV for unique ciphertexts.\n *\n * @param data - Data to encrypt\n * @param passphrase - User-provided encryption passphrase\n * @returns Encrypted payload with salt, IV, authTag, and ciphertext\n *\n * @example\n * ```typescript\n * const compressed = gzipSync(fileContent);\n * const payload = encryptWithPassphrase(compressed, 'my-passphrase');\n * ```\n */\nexport function encryptWithPassphrase(data: Buffer, passphrase: string): DtEncryptedPayload {\n\n const salt = randomBytes(SALT_LENGTH);\n const iv = randomBytes(IV_LENGTH);\n\n const key = pbkdf2Sync(passphrase, salt, PBKDF2_ITERATIONS, KEY_LENGTH, PBKDF2_DIGEST);\n\n const cipher = createCipheriv(ALGORITHM, key, iv, {\n authTagLength: AUTH_TAG_LENGTH,\n });\n\n const ciphertext = Buffer.concat([cipher.update(data), cipher.final()]);\n const authTag = cipher.getAuthTag();\n\n return {\n salt: salt.toString('base64'),\n iv: iv.toString('base64'),\n authTag: authTag.toString('base64'),\n ciphertext: ciphertext.toString('base64'),\n };\n\n}\n\n/**\n * Decrypt a payload using a passphrase.\n *\n * Derives the same key using PBKDF2 with the stored salt,\n * then decrypts and verifies with AES-256-GCM.\n *\n * @param payload - Encrypted payload from encryptWithPassphrase\n * @param passphrase - Same passphrase used for encryption\n * @returns Decrypted data buffer\n * @throws If passphrase is wrong or data is tampered\n *\n * @example\n * ```typescript\n * const decrypted = decryptWithPassphrase(payload, 'my-passphrase');\n * const content = gunzipSync(decrypted);\n * ```\n */\nexport function decryptWithPassphrase(payload: DtEncryptedPayload, passphrase: string): Buffer {\n\n const salt = Buffer.from(payload.salt, 'base64');\n const iv = Buffer.from(payload.iv, 'base64');\n const authTag = Buffer.from(payload.authTag, 'base64');\n const ciphertext = Buffer.from(payload.ciphertext, 'base64');\n\n const key = pbkdf2Sync(passphrase, salt, PBKDF2_ITERATIONS, KEY_LENGTH, PBKDF2_DIGEST);\n\n const decipher = createDecipheriv(ALGORITHM, key, iv, {\n authTagLength: AUTH_TAG_LENGTH,\n });\n\n decipher.setAuthTag(authTag);\n\n const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n\n return decrypted;\n\n}\n","/**\n * Streaming .dt file reader.\n *\n * Reads .dt files with extension-based input handling:\n * - `.dt`: raw text readline\n * - `.dtz`: gunzip then readline\n * - `.dtzx`: decrypt then gunzip then readline\n *\n * @example\n * ```typescript\n * import { DtReader } from './reader.js';\n *\n * const reader = new DtReader({ filepath: './data/users.dtz' });\n * await reader.open();\n *\n * const schema = reader.schema;\n *\n * for await (const values of reader.rows()) {\n * // values is DtValue[]\n * }\n *\n * reader.close();\n * ```\n */\nimport { createReadStream, readFileSync } from 'node:fs';\nimport { createGunzip } from 'node:zlib';\nimport { gunzipSync } from 'node:zlib';\nimport { createInterface } from 'node:readline';\nimport { PassThrough } from 'node:stream';\nimport path from 'node:path';\nimport JSON5 from 'json5';\n\nimport type { Readable } from 'node:stream';\nimport type { DtSchema, DtValue, DtReaderOptions } from './types.js';\nimport { DT_EXTENSIONS } from './constants.js';\nimport { decryptWithPassphrase } from './crypto.js';\n\n/**\n * Streaming .dt file reader.\n *\n * Handles raw, compressed, and encrypted input based on file extension.\n * Provides schema access and async iteration over rows.\n */\nexport class DtReader {\n\n #filepath: string;\n #passphrase?: string;\n #extension: string;\n #schema: DtSchema | null = null;\n #lineReader: AsyncGenerator<DtValue[], void, undefined> | null = null;\n #inputStream: Readable | null = null;\n\n /**\n * Create a new DtReader.\n *\n * @param options - File path and optional passphrase for .dtzx\n */\n constructor(options: DtReaderOptions) {\n\n this.#filepath = options.filepath;\n this.#passphrase = options.passphrase;\n this.#extension = path.extname(options.filepath).toLowerCase();\n\n }\n\n /** The parsed schema from line 1. Available after open(). */\n get schema(): DtSchema | null {\n\n return this.#schema;\n\n }\n\n /**\n * Open the file and parse the schema header.\n *\n * Must be called before iterating rows.\n */\n async open(): Promise<void> {\n\n const readable = this.#createReadableStream();\n this.#inputStream = readable;\n\n // Read first line as schema\n const rl = createInterface({ input: readable, crlfDelay: Infinity });\n const lines = rl[Symbol.asyncIterator]();\n const firstLine = await lines.next();\n\n if (firstLine.done || !firstLine.value) {\n\n throw new Error('Empty .dt file — no schema line');\n\n }\n\n this.#schema = JSON5.parse(firstLine.value) as DtSchema;\n\n // Validate version\n if (this.#schema.v !== 1) {\n\n throw new Error(`Unsupported .dt format version: ${this.#schema.v}`);\n\n }\n\n // Store iterator for rows\n this.#lineReader = this.#createRowIterator(lines);\n\n }\n\n /**\n * Async generator yielding parsed row value arrays.\n *\n * Each yield is a `DtValue[]` in column order matching the schema.\n *\n * @example\n * ```typescript\n * for await (const values of reader.rows()) {\n * console.log(values); // [1, \"alice@example.com\", true, \"2024-01-15T10:30:00Z\"]\n * }\n * ```\n */\n async *rows(): AsyncGenerator<DtValue[], void, undefined> {\n\n if (!this.#lineReader) {\n\n throw new Error('Reader not opened — call open() first');\n\n }\n\n yield* this.#lineReader;\n\n }\n\n /**\n * Close the reader and release resources.\n */\n close(): void {\n\n if (this.#inputStream) {\n\n this.#inputStream.destroy();\n this.#inputStream = null;\n\n }\n\n }\n\n /**\n * Create the readable stream based on file extension.\n */\n #createReadableStream(): Readable {\n\n if (this.#extension === DT_EXTENSIONS.ENCRYPTED) {\n\n // .dtzx: read all, decrypt, gunzip, create readable from buffer\n if (!this.#passphrase) {\n\n throw new Error('Passphrase required for .dtzx files');\n\n }\n\n const encrypted = readFileSync(this.#filepath, 'utf8');\n const payload = JSON.parse(encrypted);\n const compressed = decryptWithPassphrase(payload, this.#passphrase);\n const raw = gunzipSync(compressed);\n\n const stream = new PassThrough();\n stream.end(raw);\n\n return stream;\n\n }\n\n if (this.#extension === DT_EXTENSIONS.COMPRESSED) {\n\n // .dtz: pipe through gunzip\n const fileStream = createReadStream(this.#filepath);\n const gunzip = createGunzip();\n\n fileStream.pipe(gunzip);\n\n return gunzip;\n\n }\n\n // .dt: raw file stream\n return createReadStream(this.#filepath, { encoding: 'utf8' });\n\n }\n\n /**\n * Create async generator from remaining readline lines.\n */\n async *#createRowIterator(\n lines: AsyncIterableIterator<string>,\n ): AsyncGenerator<DtValue[], void, undefined> {\n\n for await (const line of { [Symbol.asyncIterator]: () => lines }) {\n\n const trimmed = line.trim();\n\n if (trimmed.length === 0) continue;\n\n yield JSON5.parse(trimmed) as DtValue[];\n\n }\n\n }\n\n}\n","/**\n * .dt file loader for template seed data.\n *\n * Loads .dt and .dtz files as arrays of row objects.\n * Does NOT support .dtzx — no way to provide a decryption\n * key in the template context.\n *\n * @example\n * ```typescript\n * import { loadDt } from './dt.js';\n *\n * const rows = await loadDt('/path/to/seed.dt');\n * // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]\n * ```\n */\nimport { DtReader } from '../../dt/reader.js';\n\n/**\n * Load a .dt or .dtz file as an array of row objects.\n *\n * Reads the schema to get column names, then maps each row's\n * positional values to named fields.\n *\n * @param filepath - Path to .dt or .dtz file\n * @returns Array of row objects with column names as keys\n * @throws If the file cannot be read or parsed\n *\n * @example\n * ```typescript\n * // Given a .dt file with columns [id, name, active]:\n * const data = await loadDt('./seeds/users.dt');\n * // [{ id: 1, name: 'Alice', active: true }, ...]\n * ```\n */\nexport async function loadDt(filepath: string): Promise<Record<string, unknown>[]> {\n\n const reader = new DtReader({ filepath });\n\n await reader.open();\n\n const schema = reader.schema;\n\n if (!schema) {\n\n throw new Error(`Failed to read .dt schema from: ${filepath}`);\n\n }\n\n const columnNames = schema.columns.map((c) => c.name);\n const rows: Record<string, unknown>[] = [];\n\n for await (const values of reader.rows()) {\n\n const row: Record<string, unknown> = {};\n\n for (let i = 0; i < columnNames.length; i++) {\n\n row[columnNames[i]!] = values[i] ?? null;\n\n }\n\n rows.push(row);\n\n }\n\n reader.close();\n\n return rows;\n\n}\n","/**\n * Loader registry for data files.\n *\n * Maps file extensions to their respective loader functions.\n * Provides a unified interface for loading any supported data format.\n *\n * @example\n * ```typescript\n * import { loadDataFile, getLoader, hasLoader } from './loaders'\n *\n * if (hasLoader('.json5')) {\n * const data = await loadDataFile('/path/to/config.json5')\n * }\n * ```\n */\nimport path from 'node:path';\n\nimport type { Loader, LoaderRegistry } from '../types.js';\nimport { loadJson5 } from './json5.js';\nimport { loadYaml } from './yaml.js';\nimport { loadCsv } from './csv.js';\nimport { loadJs } from './js.js';\nimport { loadSql } from './sql.js';\nimport { loadDt } from './dt.js';\n\n/**\n * Registry of loaders by file extension.\n */\nconst loaders: LoaderRegistry = {\n '.json': loadJson5,\n '.json5': loadJson5,\n '.yaml': loadYaml,\n '.yml': loadYaml,\n '.csv': loadCsv,\n '.js': loadJs,\n '.mjs': loadJs,\n '.ts': loadJs,\n '.sql': loadSql,\n '.dt': loadDt,\n '.dtz': loadDt,\n // NO .dtzx — can't provide passphrase in template context\n};\n\n/**\n * Check if a loader exists for the given extension.\n *\n * @param ext - File extension (e.g., '.json5')\n * @returns True if a loader is registered for this extension\n */\nexport function hasLoader(ext: string): boolean {\n\n return ext in loaders;\n\n}\n\n/**\n * Get the loader function for a file extension.\n *\n * @param ext - File extension (e.g., '.json5')\n * @returns The loader function, or undefined if not found\n */\nexport function getLoader(ext: string): Loader | undefined {\n\n return loaders[ext];\n\n}\n\n/**\n * Load a data file using the appropriate loader.\n *\n * Determines the loader from the file extension and loads the file.\n *\n * @param filepath - Absolute path to the data file\n * @returns The loaded and parsed data\n * @throws If no loader exists for the file extension\n * @throws If the file cannot be loaded or parsed\n *\n * @example\n * ```typescript\n * const users = await loadDataFile('/path/to/users.json5')\n * const config = await loadDataFile('/path/to/config.yml')\n * ```\n */\nexport async function loadDataFile(filepath: string): Promise<unknown> {\n\n const ext = path.extname(filepath).toLowerCase();\n const loader = getLoader(ext);\n\n if (!loader) {\n\n throw new Error(`No loader registered for extension: ${ext}`);\n\n }\n\n return loader(filepath);\n\n}\n\n/**\n * Get all supported data file extensions.\n *\n * @returns Array of supported extensions (e.g., ['.json', '.json5', '.yml', ...])\n */\nexport function getSupportedExtensions(): string[] {\n\n return Object.keys(loaders);\n\n}\n\n// Re-export individual loaders for direct use\nexport { loadJson5 } from './json5.js';\nexport { loadYaml } from './yaml.js';\nexport { loadCsv } from './csv.js';\nexport { loadJs } from './js.js';\nexport { loadSql } from './sql.js';\nexport { loadDt } from './dt.js';\n","/**\n * String transformation utilities using Voca.\n *\n * Provides consistent string transformations for converting filenames\n * to context property names.\n *\n * @example\n * ```typescript\n * import { toContextKey } from './utils'\n *\n * toContextKey('my-config.json5') // → 'myConfig'\n * toContextKey('seed_data.yml') // → 'seedData'\n * toContextKey('API_KEYS.json') // → 'apiKeys'\n * ```\n */\nimport v from 'voca';\nimport path from 'node:path';\n\n/**\n * Convert a filename to a camelCase context key.\n *\n * Strips the file extension and converts the base name to camelCase.\n * Handles kebab-case, snake_case, and SCREAMING_CASE.\n *\n * @param filename - The filename to convert (e.g., 'my-config.json5')\n * @returns The camelCase key (e.g., 'myConfig')\n *\n * @example\n * ```typescript\n * toContextKey('my-config.json5') // → 'myConfig'\n * toContextKey('seed_data.yml') // → 'seedData'\n * toContextKey('API_KEYS.json') // → 'apiKeys'\n * toContextKey('users.csv') // → 'users'\n * ```\n */\nexport function toContextKey(filename: string): string {\n\n // Get basename without extension\n const ext = path.extname(filename);\n const base = path.basename(filename, ext);\n\n // Convert to camelCase\n return v.camelCase(base);\n\n}\n\n/**\n * SQL-escape a string value.\n *\n * Escapes single quotes by doubling them, which is the standard\n * SQL escape sequence for string literals.\n *\n * @param value - The string to escape\n * @returns The escaped string (without surrounding quotes)\n *\n * @example\n * ```typescript\n * sqlEscape(\"O'Brien\") // → \"O''Brien\"\n * sqlEscape(\"normal\") // → \"normal\"\n * ```\n */\nexport function sqlEscape(value: string): string {\n\n return value.replace(/'/g, \"''\");\n\n}\n\n/**\n * SQL-escape and wrap in single quotes.\n *\n * Handles null values and various types appropriately.\n *\n * @param value - The value to quote\n * @returns The quoted SQL literal\n *\n * @example\n * ```typescript\n * sqlQuote(\"O'Brien\") // → \"'O''Brien'\"\n * sqlQuote(42) // → \"'42'\"\n * sqlQuote(null) // → \"NULL\"\n * sqlQuote(true) // → \"'true'\"\n * ```\n */\nexport function sqlQuote(value: string | number | boolean | null): string {\n\n if (value === null) {\n\n return 'NULL';\n\n }\n\n return `'${sqlEscape(String(value))}'`;\n\n}\n\n/**\n * Generate a UUID v4.\n *\n * Uses crypto.randomUUID() for secure random generation.\n *\n * @returns A UUID v4 string\n *\n * @example\n * ```typescript\n * generateUuid() // → \"550e8400-e29b-41d4-a716-446655440000\"\n * ```\n */\nexport function generateUuid(): string {\n\n return crypto.randomUUID();\n\n}\n\n/**\n * Get current ISO timestamp.\n *\n * @returns ISO 8601 timestamp string\n *\n * @example\n * ```typescript\n * isoNow() // → \"2024-01-15T10:30:00.000Z\"\n * ```\n */\nexport function isoNow(): string {\n\n return new Date().toISOString();\n\n}\n","/**\n * Template context builder.\n *\n * Builds the $ context object available in templates by:\n * 1. Loading inherited helpers from $helpers.ts files\n * 2. Auto-loading data files from the template's directory\n * 3. Adding config, secrets, env, and built-in helpers\n *\n * @example\n * ```typescript\n * import { buildContext } from './context'\n *\n * const ctx = await buildContext('/project/sql/users/001_create.sql.tmpl', {\n * projectRoot: '/project',\n * config: activeConfig,\n * secrets: { API_KEY: '...' },\n * })\n *\n * // ctx now has: $.padId, $.users, $.config, $.secrets, $.quote, etc.\n * ```\n */\nimport path from 'node:path';\nimport { readdir } from 'node:fs/promises';\n\nimport { attempt } from '@logosdx/utils';\n\nimport { observer } from '../observer.js';\nimport type { TemplateContext, RenderOptions } from './types.js';\nimport { HELPER_FILENAME } from './types.js';\nimport { loadHelpers } from './helpers.js';\nimport { loadDataFile, hasLoader } from './loaders/index.js';\nimport { toContextKey, sqlEscape, sqlQuote, generateUuid, isoNow } from './utils.js';\n\n/**\n * Build the template context ($) for a template file.\n *\n * @param templatePath - Absolute path to the template file\n * @param options - Render options (config, secrets, projectRoot)\n * @returns The complete template context\n */\nexport async function buildContext(\n templatePath: string,\n options: RenderOptions = {},\n): Promise<TemplateContext> {\n\n const templateDir = path.dirname(templatePath);\n const projectRoot = options.projectRoot ?? process.cwd();\n\n // 1. Load inherited helpers\n const helpers = await loadHelpers(templateDir, projectRoot);\n\n // 2. Auto-load data files from template directory\n const dataFiles = await loadDataFilesInDir(templateDir);\n\n // 3. Check if data files include a config file\n const hasLocalConfig = 'config' in dataFiles;\n\n // 4. Build context with all components\n const ctx: TemplateContext = {\n // Inherited helpers (can be overridden by data files with same name)\n ...helpers,\n\n // Auto-loaded data files\n ...dataFiles,\n\n // Config (only if no local config.* file)\n ...(hasLocalConfig ? {} : { config: options.config }),\n\n // Secrets\n secrets: options.secrets ?? {},\n globalSecrets: options.globalSecrets ?? {},\n\n // Environment\n env: process.env as Record<string, string | undefined>,\n\n // Built-in helpers\n include: createIncludeHelper(templateDir, projectRoot, options),\n escape: sqlEscape,\n quote: sqlQuote,\n json: (value: unknown) => JSON.stringify(value),\n now: isoNow,\n uuid: generateUuid,\n };\n\n return ctx;\n\n}\n\n/**\n * Load all data files in a directory.\n *\n * Scans the directory for supported data file extensions and loads each one.\n * File names are converted to camelCase context keys.\n *\n * @param dir - Directory to scan\n * @returns Object with camelCased keys and loaded data\n */\nasync function loadDataFilesInDir(dir: string): Promise<Record<string, unknown>> {\n\n const data: Record<string, unknown> = {};\n\n const [entries, readErr] = await attempt(() => readdir(dir, { withFileTypes: true }));\n\n if (readErr || !entries) {\n\n observer.emit('error', {\n source: 'template',\n error: readErr ?? new Error('Failed to read directory'),\n context: { dir, operation: 'scan-data-files' },\n });\n\n return data;\n\n }\n\n for (const entry of entries) {\n\n // Skip directories\n if (!entry.isFile()) {\n\n continue;\n\n }\n\n // Skip helper files\n if (entry.name.startsWith(HELPER_FILENAME)) {\n\n continue;\n\n }\n\n // Skip template files\n if (entry.name.endsWith('.tmpl')) {\n\n continue;\n\n }\n\n const ext = path.extname(entry.name).toLowerCase();\n\n // Skip unsupported extensions\n if (!hasLoader(ext)) {\n\n continue;\n\n }\n\n // Skip .sql files in data loading (they're for include())\n if (ext === '.sql') {\n\n continue;\n\n }\n\n const filepath = path.join(dir, entry.name);\n const key = toContextKey(entry.name);\n\n const [loaded, loadErr] = await attempt(() => loadDataFile(filepath));\n\n if (loadErr) {\n\n observer.emit('error', {\n source: 'template',\n error: loadErr,\n context: { filepath, operation: 'load-data-file' },\n });\n continue;\n\n }\n\n data[key] = loaded;\n\n observer.emit('template:load', {\n filepath,\n format: ext,\n });\n\n }\n\n return data;\n\n}\n\n/**\n * Create the include() helper function.\n *\n * The include helper resolves paths relative to the template's directory\n * and cannot escape the project root. If the included file is a template\n * (.sql.tmpl), it will be rendered recursively with the same options.\n *\n * @param templateDir - Template's directory\n * @param projectRoot - Project root (cannot escape)\n * @param options - Render options for nested templates\n * @returns The include helper function\n */\nfunction createIncludeHelper(\n templateDir: string,\n projectRoot: string,\n options: RenderOptions,\n): (includePath: string) => Promise<string> {\n\n return async (includePath: string): Promise<string> => {\n\n // Resolve path relative to template directory\n const resolved = path.resolve(templateDir, includePath);\n\n // Security: ensure we don't escape project root\n if (!resolved.startsWith(projectRoot)) {\n\n throw new Error(`Include path escapes project root: ${includePath}`);\n\n }\n\n // If it's a template, render it recursively\n if (resolved.endsWith('.tmpl')) {\n\n // Dynamic import to avoid circular dependency\n const { processFile } = await import('./engine.js');\n const result = await processFile(resolved, options);\n\n return result.sql;\n\n }\n\n // Load raw file\n const [content, err] = await attempt(() => loadDataFile(resolved));\n\n if (err) {\n\n throw new Error(`Failed to include '${includePath}': ${err.message}`);\n\n }\n\n if (typeof content === 'string') {\n\n return content;\n\n }\n\n // Non-string content (shouldn't happen for .sql files)\n return JSON.stringify(content);\n\n };\n\n}\n","/**\n * Template engine using Eta.\n *\n * Wraps Eta with noorm's custom syntax and integrates with the context builder\n * for auto-loading data files and inherited helpers.\n *\n * @example\n * ```typescript\n * import { processFile, renderTemplate } from './engine'\n *\n * // Process any SQL file (template or raw)\n * const result = await processFile('/path/to/file.sql.tmpl', {\n * config: activeConfig,\n * secrets: { API_KEY: '...' },\n * })\n *\n * // Or render a template string directly\n * const sql = await renderTemplate(\n * '{% for (const r of $.roles) { %}...',\n * context,\n * )\n * ```\n */\nimport { readFile } from 'node:fs/promises';\n\nimport { Eta } from 'eta';\n\nimport { observer } from '../observer.js';\nimport type { TemplateContext, RenderOptions, ProcessResult } from './types.js';\nimport { TEMPLATE_EXTENSION } from './types.js';\nimport { buildContext } from './context.js';\n\n/**\n * Eta instance configured with noorm's custom syntax.\n *\n * Custom delimiters:\n * - `{% %}` for JavaScript code (instead of `<% %>`)\n * - `{%~ %}` for raw output (instead of `<%~ %>`)\n * - `$` as the context variable (instead of `it`)\n */\nconst eta = new Eta({\n // Custom tags for code blocks\n tags: ['{%', '%}'],\n\n // Variable name for context ($ instead of it)\n varName: '$',\n\n // Don't auto-escape (SQL doesn't need HTML escaping)\n autoEscape: false,\n\n // Allow async functions in templates\n useWith: false,\n\n // Don't cache templates (we handle caching at a higher level)\n cache: false,\n});\n\n/**\n * Check if a file path is a template.\n *\n * @param filepath - File path to check\n * @returns True if the file has the .tmpl extension\n */\nexport function isTemplate(filepath: string): boolean {\n\n return filepath.endsWith(TEMPLATE_EXTENSION);\n\n}\n\n/**\n * Render a template string with the given context.\n *\n * @param template - Template string with Eta syntax\n * @param context - The $ context object\n * @returns Rendered SQL string\n *\n * @example\n * ```typescript\n * const sql = await renderTemplate(\n * '{% for (const role of $.roles) { %}INSERT INTO roles (name) VALUES ({%~ $.quote(role) %});\\n{% } %}',\n * { roles: ['admin', 'user'], quote: sqlQuote }\n * )\n * ```\n */\nexport async function renderTemplate(template: string, context: TemplateContext): Promise<string> {\n\n return eta.renderStringAsync(template, context);\n\n}\n\n/**\n * Process a SQL file.\n *\n * If the file is a template (.sql.tmpl), renders it with the context.\n * If it's a raw SQL file (.sql), returns the content as-is.\n *\n * @param filepath - Absolute path to the SQL file\n * @param options - Render options (config, secrets, projectRoot)\n * @returns Process result with SQL content and metadata\n *\n * @example\n * ```typescript\n * const result = await processFile('/project/sql/users/001_create.sql.tmpl', {\n * projectRoot: '/project',\n * config: { name: 'dev', connection: { ... } },\n * secrets: { API_KEY: 'secret123' },\n * })\n *\n * console.log(result.sql) // Rendered SQL\n * console.log(result.isTemplate) // true\n * console.log(result.durationMs) // 12\n * ```\n */\nexport async function processFile(\n filepath: string,\n options: RenderOptions = {},\n): Promise<ProcessResult> {\n\n // Read file content\n const content = await readFile(filepath, 'utf-8');\n\n // If not a template, return raw content\n if (!isTemplate(filepath)) {\n\n return {\n sql: content,\n isTemplate: false,\n };\n\n }\n\n // It's a template - build context and render\n const start = performance.now();\n\n const context = await buildContext(filepath, options);\n const sql = await renderTemplate(content, context);\n\n const durationMs = performance.now() - start;\n\n observer.emit('template:render', {\n filepath,\n durationMs,\n });\n\n return {\n sql,\n isTemplate: true,\n durationMs,\n };\n\n}\n\n/**\n * Process multiple SQL files.\n *\n * @param filepaths - Array of file paths to process\n * @param options - Render options\n * @returns Array of process results\n */\nexport async function processFiles(\n filepaths: string[],\n options: RenderOptions = {},\n): Promise<ProcessResult[]> {\n\n const results: ProcessResult[] = [];\n\n for (const filepath of filepaths) {\n\n const result = await processFile(filepath, options);\n results.push(result);\n\n }\n\n return results;\n\n}\n\n// Export the Eta instance for advanced usage\nexport { eta };\n"]}
@@ -17,6 +17,26 @@ var NOORM_TABLES = Object.freeze({
17
17
  /** Vault secrets table */
18
18
  vault: "__noorm_vault__"
19
19
  });
20
+ var SCHEMA_TABLES = Object.freeze({
21
+ version: "version",
22
+ change: "change",
23
+ executions: "executions",
24
+ lock: "lock",
25
+ identities: "identities",
26
+ vault: "vault"
27
+ });
28
+ function getNoormTables(dialect) {
29
+ if (dialect === "postgres" || dialect === "mssql") {
30
+ return SCHEMA_TABLES;
31
+ }
32
+ return NOORM_TABLES;
33
+ }
34
+ function noormDb(db, dialect) {
35
+ if (dialect === "postgres" || dialect === "mssql") {
36
+ return db.withSchema("noorm");
37
+ }
38
+ return db;
39
+ }
20
40
  function generateVaultKey() {
21
41
  return randomBytes(32);
22
42
  }
@@ -116,9 +136,11 @@ function decryptSecret(encrypted, vaultKey) {
116
136
  }
117
137
 
118
138
  // src/core/vault/storage.ts
119
- async function initializeVault(db, identityHash, publicKey) {
139
+ async function initializeVault(db, identityHash, publicKey, dialect) {
140
+ const ndb = noormDb(db, dialect);
141
+ const tables = getNoormTables(dialect);
120
142
  const [existing, checkErr] = await attempt(async () => {
121
- return db.selectFrom(NOORM_TABLES.identities).select("encrypted_vault_key").where("encrypted_vault_key", "is not", null).limit(1).executeTakeFirst();
143
+ return ndb.selectFrom(tables.identities).select("encrypted_vault_key").where("encrypted_vault_key", "is not", null).limit(1).executeTakeFirst();
122
144
  });
123
145
  if (checkErr) return [null, checkErr];
124
146
  if (existing?.encrypted_vault_key) {
@@ -128,15 +150,17 @@ async function initializeVault(db, identityHash, publicKey) {
128
150
  const encrypted = encryptVaultKey(vaultKey, publicKey);
129
151
  const encryptedJson = JSON.stringify(encrypted);
130
152
  const [, updateErr] = await attempt(async () => {
131
- return db.updateTable(NOORM_TABLES.identities).set({ encrypted_vault_key: encryptedJson }).where("identity_hash", "=", identityHash).execute();
153
+ return ndb.updateTable(tables.identities).set({ encrypted_vault_key: encryptedJson }).where("identity_hash", "=", identityHash).execute();
132
154
  });
133
155
  if (updateErr) return [null, updateErr];
134
156
  observer.emit("vault:initialized", { identityHash });
135
157
  return [vaultKey, null];
136
158
  }
137
- async function getVaultKey(db, identityHash, privateKey) {
159
+ async function getVaultKey(db, identityHash, privateKey, dialect) {
160
+ const ndb = noormDb(db, dialect);
161
+ const tables = getNoormTables(dialect);
138
162
  const [row, err] = await attempt(async () => {
139
- return db.selectFrom(NOORM_TABLES.identities).select("encrypted_vault_key").where("identity_hash", "=", identityHash).executeTakeFirst();
163
+ return ndb.selectFrom(tables.identities).select("encrypted_vault_key").where("identity_hash", "=", identityHash).executeTakeFirst();
140
164
  });
141
165
  if (err || !row?.encrypted_vault_key) return null;
142
166
  const encryptedValue = row.encrypted_vault_key;
@@ -146,17 +170,19 @@ async function getVaultKey(db, identityHash, privateKey) {
146
170
  if (parseErr) return null;
147
171
  return decryptVaultKey(parsed, privateKey);
148
172
  }
149
- async function setVaultSecret(db, vaultKey, secretKey, value, setBy) {
173
+ async function setVaultSecret(db, vaultKey, secretKey, value, setBy, dialect) {
174
+ const ndb = noormDb(db, dialect);
175
+ const tables = getNoormTables(dialect);
150
176
  const encrypted = encryptSecret(value, vaultKey);
151
177
  const encryptedJson = JSON.stringify(encrypted);
152
178
  const now = (/* @__PURE__ */ new Date()).toISOString();
153
179
  const [existing, checkErr] = await attempt(async () => {
154
- return db.selectFrom(NOORM_TABLES.vault).select("id").where("secret_key", "=", secretKey).executeTakeFirst();
180
+ return ndb.selectFrom(tables.vault).select("id").where("secret_key", "=", secretKey).executeTakeFirst();
155
181
  });
156
182
  if (checkErr) return [void 0, checkErr];
157
183
  if (existing) {
158
184
  const [, updateErr] = await attempt(async () => {
159
- return db.updateTable(NOORM_TABLES.vault).set({
185
+ return ndb.updateTable(tables.vault).set({
160
186
  encrypted_value: encryptedJson,
161
187
  set_by: setBy,
162
188
  updated_at: now
@@ -166,7 +192,7 @@ async function setVaultSecret(db, vaultKey, secretKey, value, setBy) {
166
192
  observer.emit("vault:secret:updated", { key: secretKey, setBy });
167
193
  } else {
168
194
  const [, insertErr] = await attempt(async () => {
169
- return db.insertInto(NOORM_TABLES.vault).values({
195
+ return ndb.insertInto(tables.vault).values({
170
196
  secret_key: secretKey,
171
197
  encrypted_value: encryptedJson,
172
198
  set_by: setBy
@@ -177,9 +203,11 @@ async function setVaultSecret(db, vaultKey, secretKey, value, setBy) {
177
203
  }
178
204
  return [void 0, null];
179
205
  }
180
- async function getVaultSecret(db, vaultKey, secretKey) {
206
+ async function getVaultSecret(db, vaultKey, secretKey, dialect) {
207
+ const ndb = noormDb(db, dialect);
208
+ const tables = getNoormTables(dialect);
181
209
  const [row, err] = await attempt(async () => {
182
- return db.selectFrom(NOORM_TABLES.vault).select("encrypted_value").where("secret_key", "=", secretKey).executeTakeFirst();
210
+ return ndb.selectFrom(tables.vault).select("encrypted_value").where("secret_key", "=", secretKey).executeTakeFirst();
183
211
  });
184
212
  if (err || !row) return null;
185
213
  const [parsed, parseErr] = attemptSync(
@@ -188,9 +216,11 @@ async function getVaultSecret(db, vaultKey, secretKey) {
188
216
  if (parseErr) return null;
189
217
  return decryptSecret(parsed, vaultKey);
190
218
  }
191
- async function getAllVaultSecrets(db, vaultKey) {
219
+ async function getAllVaultSecrets(db, vaultKey, dialect) {
220
+ const ndb = noormDb(db, dialect);
221
+ const tables = getNoormTables(dialect);
192
222
  const [rows, err] = await attempt(async () => {
193
- return db.selectFrom(NOORM_TABLES.vault).selectAll().execute();
223
+ return ndb.selectFrom(tables.vault).selectAll().execute();
194
224
  });
195
225
  if (err || !rows) return {};
196
226
  const secrets = {};
@@ -211,16 +241,20 @@ async function getAllVaultSecrets(db, vaultKey) {
211
241
  }
212
242
  return secrets;
213
243
  }
214
- async function listVaultSecretKeys(db) {
244
+ async function listVaultSecretKeys(db, dialect) {
245
+ const ndb = noormDb(db, dialect);
246
+ const tables = getNoormTables(dialect);
215
247
  const [rows, err] = await attempt(async () => {
216
- return db.selectFrom(NOORM_TABLES.vault).select("secret_key").orderBy("secret_key", "asc").execute();
248
+ return ndb.selectFrom(tables.vault).select("secret_key").orderBy("secret_key", "asc").execute();
217
249
  });
218
250
  if (err || !rows) return [];
219
251
  return rows.map((r) => r.secret_key);
220
252
  }
221
- async function deleteVaultSecret(db, secretKey) {
253
+ async function deleteVaultSecret(db, secretKey, dialect) {
254
+ const ndb = noormDb(db, dialect);
255
+ const tables = getNoormTables(dialect);
222
256
  const [result, err] = await attempt(async () => {
223
- return db.deleteFrom(NOORM_TABLES.vault).where("secret_key", "=", secretKey).execute();
257
+ return ndb.deleteFrom(tables.vault).where("secret_key", "=", secretKey).execute();
224
258
  });
225
259
  if (err || !result) return [false, err ?? new Error("Delete failed")];
226
260
  const firstResult = result[0];
@@ -230,20 +264,24 @@ async function deleteVaultSecret(db, secretKey) {
230
264
  }
231
265
  return [deleted, null];
232
266
  }
233
- async function vaultSecretExists(db, secretKey) {
267
+ async function vaultSecretExists(db, secretKey, dialect) {
268
+ const ndb = noormDb(db, dialect);
269
+ const tables = getNoormTables(dialect);
234
270
  const [row, err] = await attempt(async () => {
235
- return db.selectFrom(NOORM_TABLES.vault).select("id").where("secret_key", "=", secretKey).executeTakeFirst();
271
+ return ndb.selectFrom(tables.vault).select("id").where("secret_key", "=", secretKey).executeTakeFirst();
236
272
  });
237
273
  if (err) return false;
238
274
  return !!row;
239
275
  }
240
- async function getVaultStatus(db, identityHash) {
276
+ async function getVaultStatus(db, identityHash, dialect) {
277
+ const ndb = noormDb(db, dialect);
278
+ const tables = getNoormTables(dialect);
241
279
  const [secretRows] = await attempt(async () => {
242
- return db.selectFrom(NOORM_TABLES.vault).select(db.fn.count("id").as("count")).executeTakeFirst();
280
+ return ndb.selectFrom(tables.vault).select(ndb.fn.count("id").as("count")).executeTakeFirst();
243
281
  });
244
282
  const secretCount = secretRows ? Number(secretRows.count) : 0;
245
283
  const [identityRows] = await attempt(async () => {
246
- return db.selectFrom(NOORM_TABLES.identities).select([
284
+ return ndb.selectFrom(tables.identities).select([
247
285
  "identity_hash",
248
286
  "encrypted_vault_key"
249
287
  ]).execute();
@@ -263,6 +301,6 @@ async function getVaultStatus(db, identityHash) {
263
301
  };
264
302
  }
265
303
 
266
- export { NOORM_TABLES, deleteVaultSecret, encryptVaultKey, getAllVaultSecrets, getVaultKey, getVaultSecret, getVaultStatus, initializeVault, listVaultSecretKeys, setVaultSecret, vaultSecretExists };
267
- //# sourceMappingURL=chunk-ZRZ7AECF.js.map
268
- //# sourceMappingURL=chunk-ZRZ7AECF.js.map
304
+ export { deleteVaultSecret, encryptVaultKey, getAllVaultSecrets, getNoormTables, getVaultKey, getVaultSecret, getVaultStatus, initializeVault, listVaultSecretKeys, noormDb, setVaultSecret, vaultSecretExists };
305
+ //# sourceMappingURL=chunk-LJDHQEWW.js.map
306
+ //# sourceMappingURL=chunk-LJDHQEWW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/shared/tables.ts","../../../src/core/vault/key.ts","../../../src/core/vault/storage.ts"],"names":["attemptSync"],"mappings":"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","file":"chunk-LJDHQEWW.js","sourcesContent":["/**\n * Kysely table types for noorm tracking tables.\n *\n * These types define the shape of the database tables used by noorm\n * to track changes, executions, locks, identities, and versions.\n *\n * For full schema documentation, see plan/datamodel.md\n *\n * WHY: Kysely uses these types to provide type-safe queries.\n * They match the database schema created by migrations.\n */\nimport type { Generated, Insertable, Kysely, Selectable, Updateable } from 'kysely';\n\nimport type { Dialect } from '../connection/types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Table Names\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Noorm tracking table names.\n *\n * Use these constants instead of hardcoding table names.\n *\n * @deprecated Use `getNoormTables(dialect)` instead. This constant maps to prefixed\n * names and will produce incorrect SQL when used with `noormDb()` on pg/mssql.\n *\n * @example\n * ```typescript\n * import { NOORM_TABLES } from './shared'\n *\n * await db.selectFrom(NOORM_TABLES.version).selectAll().execute()\n * ```\n */\nexport const NOORM_TABLES = Object.freeze({\n /** Version tracking table */\n version: '__noorm_version__' as const,\n\n /** Change/operation tracking table */\n change: '__noorm_change__' as const,\n\n /** File execution tracking table */\n executions: '__noorm_executions__' as const,\n\n /** Concurrent operation lock table */\n lock: '__noorm_lock__' as const,\n\n /** Team member identity table */\n identities: '__noorm_identities__' as const,\n\n /** Vault secrets table */\n vault: '__noorm_vault__' as const,\n});\n\n/**\n * Shape returned by getNoormTables().\n */\nexport type NoormTableNames = {\n\n version: string;\n change: string;\n executions: string;\n lock: string;\n identities: string;\n vault: string;\n\n};\n\n/**\n * Schema-qualified table names for pg/mssql.\n *\n * Used with withSchema('noorm') — table names have no prefix.\n */\nconst SCHEMA_TABLES = Object.freeze({\n version: 'version' as const,\n change: 'change' as const,\n executions: 'executions' as const,\n lock: 'lock' as const,\n identities: 'identities' as const,\n vault: 'vault' as const,\n});\n\n/**\n * Get dialect-appropriate noorm table names.\n *\n * pg/mssql: clean names used with withSchema('noorm').\n * sqlite/mysql: prefixed names used directly.\n *\n * Returns the concrete const type so Kysely can narrow table names\n * for type-safe selectFrom() calls.\n *\n * @example\n * ```typescript\n * const tables = getNoormTables('postgres');\n * const ndb = noormDb(db, 'postgres');\n * await ndb.selectFrom(tables.change).selectAll().execute();\n * ```\n */\nexport function getNoormTables(dialect: Dialect): typeof SCHEMA_TABLES | typeof NOORM_TABLES {\n\n if (dialect === 'postgres' || dialect === 'mssql') {\n\n return SCHEMA_TABLES;\n\n }\n\n return NOORM_TABLES;\n\n}\n\n/**\n * Get a Kysely instance scoped to the noorm schema.\n *\n * pg/mssql: wraps with withSchema('noorm') so all table references\n * are prefixed with the noorm schema.\n * sqlite/mysql: returns the db as-is.\n *\n * @example\n * ```typescript\n * const ndb = noormDb(db, 'postgres');\n * await ndb.selectFrom('change').selectAll().execute();\n * // SQL: SELECT * FROM \"noorm\".\"change\"\n * ```\n */\nexport function noormDb(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n): Kysely<NoormDatabase> {\n\n if (dialect === 'postgres' || dialect === 'mssql') {\n\n return db.withSchema('noorm') as Kysely<NoormDatabase>;\n\n }\n\n return db;\n\n}\n\n/**\n * Type for prefixed noorm table names (sqlite/mysql).\n *\n * Only includes the `__noorm_*__` prefixed names from NOORM_TABLES.\n * For pg/mssql schema-qualified names, use NoormSchemaTableName.\n */\nexport type NoormTableName = (typeof NOORM_TABLES)[keyof typeof NOORM_TABLES];\n\n/**\n * Type for schema-qualified noorm table names (pg/mssql).\n *\n * Clean names used with withSchema('noorm').\n */\nexport type NoormSchemaTableName = (typeof SCHEMA_TABLES)[keyof typeof SCHEMA_TABLES];\n\n// ─────────────────────────────────────────────────────────────\n// __noorm_version__\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Version tracking table.\n *\n * Tracks noorm CLI version and all internal schema versions for migrations.\n * See: plan/datamodel.md#__noorm_version__\n */\nexport interface NoormVersionTable {\n /** Primary key */\n id: Generated<number>;\n\n /** CLI semver (e.g., \"1.2.3\") */\n cli_version: string;\n\n /** Database tracking tables version */\n noorm_version: number;\n\n /** State file (state.enc) schema version */\n state_version: number;\n\n /** Settings file (settings.yml) schema version */\n settings_version: number;\n\n /** First installation timestamp */\n installed_at: Generated<Date>;\n\n /** Last upgrade timestamp */\n upgraded_at: Generated<Date>;\n}\n\nexport type NoormVersion = Selectable<NoormVersionTable>;\nexport type NewNoormVersion = Insertable<NoormVersionTable>;\nexport type NoormVersionUpdate = Updateable<NoormVersionTable>;\n\n// ─────────────────────────────────────────────────────────────\n// __noorm_change__\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Operation status values.\n *\n * - pending: Operation started but not finished\n * - success: Operation completed successfully\n * - failed: Operation failed with error\n * - reverted: Operation was reverted\n * - stale: Operation's schema objects were torn down (needs re-run)\n */\nexport type OperationStatus = 'pending' | 'success' | 'failed' | 'reverted' | 'stale';\n\n/**\n * Change type values.\n */\nexport type ChangeType = 'build' | 'run' | 'change';\n\n/**\n * Direction values.\n */\nexport type Direction = 'change' | 'revert';\n\n/**\n * Change tracking table.\n *\n * Tracks all operation batches—changes, builds, and ad-hoc runs.\n * See: plan/datamodel.md#__noorm_change__\n */\nexport interface NoormChangeTable {\n /** Primary key */\n id: Generated<number>;\n\n /** Operation identifier */\n name: string;\n\n /** 'build', 'run', or 'change' */\n change_type: ChangeType;\n\n /** 'change' or 'revert' */\n direction: Direction;\n\n /** SHA-256 of sorted file checksums */\n checksum: Generated<string>;\n\n /** When executed */\n executed_at: Generated<Date>;\n\n /** Identity string */\n executed_by: Generated<string>;\n\n /** Which config was used */\n config_name: Generated<string>;\n\n /** noorm version */\n cli_version: Generated<string>;\n\n /** 'pending', 'success', 'failed', 'reverted' */\n status: OperationStatus;\n\n /** Error details (empty = no error) */\n error_message: Generated<string>;\n\n /** Execution time (0 = never ran) */\n duration_ms: Generated<number>;\n}\n\nexport type NoormChange = Selectable<NoormChangeTable>;\nexport type NewNoormChange = Insertable<NoormChangeTable>;\nexport type NoormChangeUpdate = Updateable<NoormChangeTable>;\n\n// ─────────────────────────────────────────────────────────────\n// __noorm_executions__\n// ─────────────────────────────────────────────────────────────\n\n/**\n * File execution status values.\n */\nexport type ExecutionStatus = 'pending' | 'success' | 'failed' | 'skipped';\n\n/**\n * File type values.\n */\nexport type FileType = 'sql' | 'txt';\n\n/**\n * Executions tracking table.\n *\n * Tracks individual file executions within an operation.\n * See: plan/datamodel.md#__noorm_executions__\n */\nexport interface NoormExecutionsTable {\n /** Primary key */\n id: Generated<number>;\n\n /** Parent operation (FK to __noorm_change__) */\n change_id: number;\n\n /** File that was executed */\n filepath: string;\n\n /** 'sql' or 'txt' */\n file_type: FileType;\n\n /** SHA-256 of file contents */\n checksum: Generated<string>;\n\n /** noorm version */\n cli_version: Generated<string>;\n\n /** 'pending', 'success', 'failed', 'skipped' */\n status: ExecutionStatus;\n\n /** Error details (empty = no error) */\n error_message: Generated<string>;\n\n /** 'unchanged', 'already-run', 'change failed' */\n skip_reason: Generated<string>;\n\n /** Execution time (0 = never ran) */\n duration_ms: Generated<number>;\n}\n\nexport type NoormExecution = Selectable<NoormExecutionsTable>;\nexport type NewNoormExecution = Insertable<NoormExecutionsTable>;\nexport type NoormExecutionUpdate = Updateable<NoormExecutionsTable>;\n\n// ─────────────────────────────────────────────────────────────\n// __noorm_lock__\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Lock table.\n *\n * Prevents concurrent operations on the same database.\n * See: plan/datamodel.md#__noorm_lock__\n */\nexport interface NoormLockTable {\n /** Primary key */\n id: Generated<number>;\n\n /** Lock scope (config name) */\n config_name: string;\n\n /** Identity of holder */\n locked_by: string;\n\n /** When acquired */\n locked_at: Generated<Date>;\n\n /** Auto-expiry time */\n expires_at: Date;\n\n /** Lock reason (empty = none) */\n reason: Generated<string>;\n}\n\nexport type NoormLock = Selectable<NoormLockTable>;\nexport type NewNoormLock = Insertable<NoormLockTable>;\nexport type NoormLockUpdate = Updateable<NoormLockTable>;\n\n// ─────────────────────────────────────────────────────────────\n// __noorm_identities__\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Identities table.\n *\n * Stores user identities for team discovery.\n * Auto-populated on first connect when identity is set up.\n * See: plan/datamodel.md#__noorm_identities__\n */\nexport interface NoormIdentitiesTable {\n /** Primary key */\n id: Generated<number>;\n\n /** SHA-256(email + name + machine + os) */\n identity_hash: string;\n\n /** User email */\n email: string;\n\n /** Display name */\n name: string;\n\n /** Machine hostname */\n machine: string;\n\n /** OS platform and version */\n os: string;\n\n /** X25519 public key (hex) */\n public_key: string;\n\n /** First registration */\n registered_at: Generated<Date>;\n\n /** Last activity */\n last_seen_at: Generated<Date>;\n\n /** Vault key encrypted with user's public key (nullable for users without vault access) */\n encrypted_vault_key: string | null;\n}\n\nexport type NoormIdentity = Selectable<NoormIdentitiesTable>;\nexport type NewNoormIdentity = Insertable<NoormIdentitiesTable>;\nexport type NoormIdentityUpdate = Updateable<NoormIdentitiesTable>;\n\n// ─────────────────────────────────────────────────────────────\n// __noorm_vault__\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Vault secrets table.\n *\n * Stores encrypted secrets shared across the team.\n * Secrets are encrypted with a vault key that is distributed\n * to team members via their public keys.\n */\nexport interface NoormVaultTable {\n /** Primary key */\n id: Generated<number>;\n\n /** Secret key name (e.g., 'API_KEY', 'DB_PASSWORD') */\n secret_key: string;\n\n /** AES-256-GCM encrypted value (JSON: {iv, authTag, ciphertext}) */\n encrypted_value: string;\n\n /** Identity who set this secret */\n set_by: string;\n\n /** When created */\n created_at: Generated<Date>;\n\n /** When last updated */\n updated_at: Generated<Date>;\n}\n\nexport type NoormVault = Selectable<NoormVaultTable>;\nexport type NewNoormVault = Insertable<NoormVaultTable>;\nexport type NoormVaultUpdate = Updateable<NoormVaultTable>;\n\n// ─────────────────────────────────────────────────────────────\n// Combined Database Interface\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Schema-qualified database interface for pg/mssql.\n *\n * Used with db.withSchema('noorm') — table names have no prefix.\n */\nexport interface NoormSchemaDb {\n\n version: NoormVersionTable;\n change: NoormChangeTable;\n executions: NoormExecutionsTable;\n lock: NoormLockTable;\n identities: NoormIdentitiesTable;\n vault: NoormVaultTable;\n\n}\n\n/**\n * Prefixed database interface for sqlite/mysql.\n *\n * Used directly — table names have __noorm_ prefix.\n */\nexport interface NoormPrefixDb {\n\n __noorm_version__: NoormVersionTable;\n __noorm_change__: NoormChangeTable;\n __noorm_executions__: NoormExecutionsTable;\n __noorm_lock__: NoormLockTable;\n __noorm_identities__: NoormIdentitiesTable;\n __noorm_vault__: NoormVaultTable;\n\n}\n\n/**\n * Combined database interface for all noorm tracking tables.\n *\n * Intersection of schema-qualified (pg/mssql) and prefixed (sqlite/mysql)\n * interfaces. Both key sets are valid — use getNoormTables(dialect) to get\n * the correct keys for your dialect.\n *\n * @example\n * ```typescript\n * const tables = getNoormTables(dialect);\n * const ndb = noormDb(db, dialect);\n * await ndb.selectFrom(tables.change).selectAll().execute();\n * ```\n */\nexport type NoormDatabase = NoormSchemaDb & NoormPrefixDb;\n","/**\n * Vault key management.\n *\n * Generates, encrypts, and decrypts the vault key.\n * The vault key is a 256-bit symmetric key used to encrypt vault secrets.\n * Each user's copy is encrypted with their public key.\n */\nimport {\n randomBytes,\n createCipheriv,\n createDecipheriv,\n createPrivateKey,\n createPublicKey,\n diffieHellman,\n generateKeyPairSync,\n hkdfSync,\n} from 'crypto';\n\nimport { attemptSync } from '@logosdx/utils';\n\nimport type { EncryptedVaultKey } from './types.js';\n\n/**\n * Generate a new 256-bit vault key.\n *\n * Called once during vault initialization by the first user.\n *\n * @example\n * ```typescript\n * const vaultKey = generateVaultKey();\n * // vaultKey is 32 bytes of cryptographically secure random data\n * ```\n */\nexport function generateVaultKey(): Buffer {\n\n return randomBytes(32);\n\n}\n\n/**\n * Derive shared secret from private key and public key using X25519 ECDH.\n */\nfunction deriveSharedSecret(privateKeyHex: string, publicKeyHex: string): Buffer {\n\n const privateKey = createPrivateKey({\n key: Buffer.from(privateKeyHex, 'hex'),\n format: 'der',\n type: 'pkcs8',\n });\n\n const publicKey = createPublicKey({\n key: Buffer.from(publicKeyHex, 'hex'),\n format: 'der',\n type: 'spki',\n });\n\n return diffieHellman({\n privateKey,\n publicKey,\n });\n\n}\n\n/**\n * Derive encryption key from shared secret using HKDF.\n */\nfunction deriveEncryptionKey(sharedSecret: Buffer, info: string): Buffer {\n\n return Buffer.from(\n hkdfSync(\n 'sha256',\n sharedSecret,\n Buffer.alloc(0),\n info,\n 32,\n ),\n );\n\n}\n\n/**\n * Encrypt vault key for a recipient using their public key.\n *\n * Uses the ephemeral keypair pattern:\n * 1. Generate ephemeral X25519 keypair\n * 2. ECDH with recipient's public key\n * 3. HKDF to derive encryption key\n * 4. AES-256-GCM encryption\n *\n * @param vaultKey - The 32-byte vault key to encrypt\n * @param recipientPubKey - Recipient's X25519 public key (hex)\n *\n * @example\n * ```typescript\n * const encrypted = encryptVaultKey(vaultKey, userPublicKey);\n * // Store encrypted in user's encrypted_vault_key column\n * ```\n */\nexport function encryptVaultKey(vaultKey: Buffer, recipientPubKey: string): EncryptedVaultKey {\n\n // Generate ephemeral keypair for this encryption\n const { publicKey, privateKey } = generateKeyPairSync('x25519', {\n publicKeyEncoding: { type: 'spki', format: 'der' },\n privateKeyEncoding: { type: 'pkcs8', format: 'der' },\n });\n\n const ephemeralPrivateHex = privateKey.toString('hex');\n const ephemeralPublicHex = publicKey.toString('hex');\n\n // Derive shared secret via ECDH\n const sharedSecret = deriveSharedSecret(ephemeralPrivateHex, recipientPubKey);\n\n // Derive encryption key\n const encKey = deriveEncryptionKey(sharedSecret, 'noorm-vault-key');\n\n // Generate random IV\n const iv = randomBytes(16);\n\n // Encrypt with AES-256-GCM\n const cipher = createCipheriv('aes-256-gcm', encKey, iv);\n const ciphertext = Buffer.concat([cipher.update(vaultKey), cipher.final()]);\n const authTag = cipher.getAuthTag();\n\n return {\n ephemeralPubKey: ephemeralPublicHex,\n iv: iv.toString('hex'),\n authTag: authTag.toString('hex'),\n ciphertext: ciphertext.toString('hex'),\n };\n\n}\n\n/**\n * Decrypt vault key using the user's private key.\n *\n * Reverses the ephemeral keypair pattern:\n * 1. ECDH with ephemeral public key and user's private key\n * 2. HKDF to derive decryption key\n * 3. AES-256-GCM decryption\n *\n * @param encrypted - The encrypted vault key payload\n * @param privateKey - User's X25519 private key (hex)\n * @returns The decrypted vault key, or null if decryption fails\n *\n * @example\n * ```typescript\n * const vaultKey = decryptVaultKey(encrypted, userPrivateKey);\n * if (!vaultKey) {\n * console.error('Failed to decrypt vault key');\n * }\n * ```\n */\nexport function decryptVaultKey(\n encrypted: EncryptedVaultKey,\n privateKey: string,\n): Buffer | null {\n\n const [result, err] = attemptSync(() => {\n\n // Derive shared secret from ephemeral pub + user's private\n const sharedSecret = deriveSharedSecret(privateKey, encrypted.ephemeralPubKey);\n\n // Derive decryption key\n const decKey = deriveEncryptionKey(sharedSecret, 'noorm-vault-key');\n\n // Decrypt\n const decipher = createDecipheriv(\n 'aes-256-gcm',\n decKey,\n Buffer.from(encrypted.iv, 'hex'),\n );\n decipher.setAuthTag(Buffer.from(encrypted.authTag, 'hex'));\n\n const vaultKey = Buffer.concat([\n decipher.update(Buffer.from(encrypted.ciphertext, 'hex')),\n decipher.final(),\n ]);\n\n return vaultKey;\n\n });\n\n if (err) return null;\n\n return result;\n\n}\n\n/**\n * Encrypt a secret value with the vault key.\n *\n * Uses AES-256-GCM for authenticated encryption.\n *\n * @param value - The plaintext secret value\n * @param vaultKey - The 32-byte vault key\n *\n * @example\n * ```typescript\n * const encrypted = encryptSecret('my-api-key', vaultKey);\n * // Store JSON.stringify(encrypted) in encrypted_value column\n * ```\n */\nexport function encryptSecret(\n value: string,\n vaultKey: Buffer,\n): { iv: string; authTag: string; ciphertext: string } {\n\n const iv = randomBytes(16);\n const cipher = createCipheriv('aes-256-gcm', vaultKey, iv);\n const ciphertext = Buffer.concat([cipher.update(value, 'utf8'), cipher.final()]);\n const authTag = cipher.getAuthTag();\n\n return {\n iv: iv.toString('hex'),\n authTag: authTag.toString('hex'),\n ciphertext: ciphertext.toString('hex'),\n };\n\n}\n\n/**\n * Decrypt a secret value with the vault key.\n *\n * @param encrypted - The encrypted secret payload\n * @param vaultKey - The 32-byte vault key\n * @returns The decrypted value, or null if decryption fails\n *\n * @example\n * ```typescript\n * const value = decryptSecret(encrypted, vaultKey);\n * if (!value) {\n * console.error('Failed to decrypt secret');\n * }\n * ```\n */\nexport function decryptSecret(\n encrypted: { iv: string; authTag: string; ciphertext: string },\n vaultKey: Buffer,\n): string | null {\n\n const [result, err] = attemptSync(() => {\n\n const decipher = createDecipheriv(\n 'aes-256-gcm',\n vaultKey,\n Buffer.from(encrypted.iv, 'hex'),\n );\n decipher.setAuthTag(Buffer.from(encrypted.authTag, 'hex'));\n\n const plaintext = Buffer.concat([\n decipher.update(Buffer.from(encrypted.ciphertext, 'hex')),\n decipher.final(),\n ]);\n\n return plaintext.toString('utf8');\n\n });\n\n if (err) return null;\n\n return result;\n\n}\n","/**\n * Vault storage operations.\n *\n * Database CRUD operations for the vault table and vault key management.\n * All operations use Kysely for type-safe queries.\n */\nimport type { Kysely } from 'kysely';\n\nimport { attempt, attemptSync } from '@logosdx/utils';\n\nimport type { NoormDatabase } from '../shared/tables.js';\nimport { getNoormTables, noormDb } from '../shared/tables.js';\nimport type { Dialect } from '../connection/types.js';\nimport { observer } from '../observer.js';\n\nimport type { EncryptedVaultKey, VaultSecret, VaultStatus } from './types.js';\nimport {\n generateVaultKey,\n encryptVaultKey,\n decryptVaultKey,\n encryptSecret,\n decryptSecret,\n} from './key.js';\n\n/**\n * Initialize the vault for a database.\n *\n * Generates a new vault key and stores it encrypted for the current user.\n * Only the first user to initialize gets the vault key.\n * Uses dialect-aware table names to support both legacy prefixed and\n * schema-qualified table locations.\n *\n * @param db - Kysely database instance\n * @param identityHash - Current user's identity hash\n * @param publicKey - Current user's public key (hex)\n * @param dialect - Database dialect for table name resolution\n *\n * @example\n * ```typescript\n * const [, err] = await initializeVault(db, identity.identityHash, identity.publicKey, 'postgres');\n * if (err) console.error('Failed to initialize vault');\n * ```\n */\nexport async function initializeVault(\n db: Kysely<NoormDatabase>,\n identityHash: string,\n publicKey: string,\n dialect: Dialect,\n): Promise<[Buffer | null, Error | null]> {\n\n const ndb = noormDb(db, dialect);\n const tables = getNoormTables(dialect);\n\n // Check if vault is already initialized (any user has a vault key)\n const [existing, checkErr] = await attempt(async () => {\n\n return ndb\n .selectFrom(tables.identities as keyof NoormDatabase)\n .select('encrypted_vault_key')\n .where('encrypted_vault_key', 'is not', null)\n .limit(1)\n .executeTakeFirst();\n\n });\n\n if (checkErr) return [null, checkErr];\n\n if (existing?.encrypted_vault_key) {\n\n return [null, new Error('Vault already initialized')];\n\n }\n\n // Generate new vault key\n const vaultKey = generateVaultKey();\n\n // Encrypt for current user\n const encrypted = encryptVaultKey(vaultKey, publicKey);\n const encryptedJson = JSON.stringify(encrypted);\n\n // Update user's identity row\n const [, updateErr] = await attempt(async () => {\n\n return ndb\n .updateTable(tables.identities as keyof NoormDatabase)\n .set({ encrypted_vault_key: encryptedJson })\n .where('identity_hash', '=', identityHash)\n .execute();\n\n });\n\n if (updateErr) return [null, updateErr];\n\n observer.emit('vault:initialized', { identityHash });\n\n return [vaultKey, null];\n\n}\n\n/**\n * Get the vault key for the current user.\n *\n * Fetches and decrypts the vault key from the user's identity row.\n * Uses dialect-aware table names to support both legacy prefixed and\n * schema-qualified table locations.\n *\n * @param db - Kysely database instance\n * @param identityHash - Current user's identity hash\n * @param privateKey - Current user's private key (hex)\n * @param dialect - Database dialect for table name resolution\n * @returns The decrypted vault key, or null if not found/accessible\n *\n * @example\n * ```typescript\n * const vaultKey = await getVaultKey(db, identity.identityHash, privateKey, 'postgres');\n * if (!vaultKey) {\n * console.log('No vault access - vault not initialized or not propagated');\n * }\n * ```\n */\nexport async function getVaultKey(\n db: Kysely<NoormDatabase>,\n identityHash: string,\n privateKey: string,\n dialect: Dialect,\n): Promise<Buffer | null> {\n\n const ndb = noormDb(db, dialect);\n const tables = getNoormTables(dialect);\n\n const [row, err] = await attempt(async () => {\n\n return ndb\n .selectFrom(tables.identities as keyof NoormDatabase)\n .select('encrypted_vault_key')\n .where('identity_hash', '=', identityHash)\n .executeTakeFirst();\n\n });\n\n if (err || !row?.encrypted_vault_key) return null;\n\n const encryptedValue = row.encrypted_vault_key;\n\n const [parsed, parseErr] = attemptSync(() =>\n JSON.parse(encryptedValue) as EncryptedVaultKey,\n );\n\n if (parseErr) return null;\n\n return decryptVaultKey(parsed, privateKey);\n\n}\n\n/**\n * Set a vault secret.\n *\n * Encrypts and stores a secret in the vault table.\n * Upserts - creates if new, updates if exists.\n * Uses dialect-aware table names to support both legacy prefixed and\n * schema-qualified table locations.\n *\n * @param db - Kysely database instance\n * @param vaultKey - The decrypted vault key\n * @param secretKey - The secret's key name\n * @param value - The plaintext secret value\n * @param setBy - Identity string of who set this secret\n * @param dialect - Database dialect for table name resolution\n *\n * @example\n * ```typescript\n * await setVaultSecret(db, vaultKey, 'API_KEY', 'sk-live-...', 'alice@example.com', 'postgres');\n * ```\n */\nexport async function setVaultSecret(\n db: Kysely<NoormDatabase>,\n vaultKey: Buffer,\n secretKey: string,\n value: string,\n setBy: string,\n dialect: Dialect,\n): Promise<[void, Error | null]> {\n\n const ndb = noormDb(db, dialect);\n const tables = getNoormTables(dialect);\n\n // Encrypt the value\n const encrypted = encryptSecret(value, vaultKey);\n const encryptedJson = JSON.stringify(encrypted);\n const now = new Date().toISOString();\n\n // Check if exists\n const [existing, checkErr] = await attempt(async () => {\n\n return ndb\n .selectFrom(tables.vault as keyof NoormDatabase)\n .select('id')\n .where('secret_key', '=', secretKey)\n .executeTakeFirst();\n\n });\n\n if (checkErr) return [undefined, checkErr];\n\n if (existing) {\n\n // Update existing\n const [, updateErr] = await attempt(async () => {\n\n return ndb\n .updateTable(tables.vault as keyof NoormDatabase)\n .set({\n encrypted_value: encryptedJson,\n set_by: setBy,\n updated_at: now as unknown as Date,\n })\n .where('secret_key', '=', secretKey)\n .execute();\n\n });\n\n if (updateErr) return [undefined, updateErr];\n\n observer.emit('vault:secret:updated', { key: secretKey, setBy });\n\n }\n else {\n\n // Insert new\n const [, insertErr] = await attempt(async () => {\n\n return ndb\n .insertInto(tables.vault as keyof NoormDatabase)\n .values({\n secret_key: secretKey,\n encrypted_value: encryptedJson,\n set_by: setBy,\n } as never)\n .execute();\n\n });\n\n if (insertErr) return [undefined, insertErr];\n\n observer.emit('vault:secret:created', { key: secretKey, setBy });\n\n }\n\n return [undefined, null];\n\n}\n\n/**\n * Get a vault secret by key.\n *\n * Uses dialect-aware table names to support both legacy prefixed and\n * schema-qualified table locations.\n *\n * @param db - Kysely database instance\n * @param vaultKey - The decrypted vault key\n * @param secretKey - The secret's key name\n * @param dialect - Database dialect for table name resolution\n * @returns The decrypted secret value, or null if not found\n *\n * @example\n * ```typescript\n * const value = await getVaultSecret(db, vaultKey, 'API_KEY', 'postgres');\n * if (value) {\n * console.log('Secret found:', value);\n * }\n * ```\n */\nexport async function getVaultSecret(\n db: Kysely<NoormDatabase>,\n vaultKey: Buffer,\n secretKey: string,\n dialect: Dialect,\n): Promise<string | null> {\n\n const ndb = noormDb(db, dialect);\n const tables = getNoormTables(dialect);\n\n const [row, err] = await attempt(async () => {\n\n return ndb\n .selectFrom(tables.vault as keyof NoormDatabase)\n .select('encrypted_value')\n .where('secret_key', '=', secretKey)\n .executeTakeFirst();\n\n });\n\n if (err || !row) return null;\n\n const [parsed, parseErr] = attemptSync(() =>\n JSON.parse(row.encrypted_value) as { iv: string; authTag: string; ciphertext: string },\n );\n\n if (parseErr) return null;\n\n return decryptSecret(parsed, vaultKey);\n\n}\n\n/**\n * Get all vault secrets.\n *\n * Uses dialect-aware table names to support both legacy prefixed and\n * schema-qualified table locations.\n *\n * @param db - Kysely database instance\n * @param vaultKey - The decrypted vault key\n * @param dialect - Database dialect for table name resolution\n * @returns Map of secret key to VaultSecret\n *\n * @example\n * ```typescript\n * const secrets = await getAllVaultSecrets(db, vaultKey, 'postgres');\n * for (const [key, secret] of Object.entries(secrets)) {\n * console.log(key, secret.value);\n * }\n * ```\n */\nexport async function getAllVaultSecrets(\n db: Kysely<NoormDatabase>,\n vaultKey: Buffer,\n dialect: Dialect,\n): Promise<Record<string, VaultSecret>> {\n\n const ndb = noormDb(db, dialect);\n const tables = getNoormTables(dialect);\n\n const [rows, err] = await attempt(async () => {\n\n return ndb\n .selectFrom(tables.vault as keyof NoormDatabase)\n .selectAll()\n .execute();\n\n });\n\n if (err || !rows) return {};\n\n const secrets: Record<string, VaultSecret> = {};\n\n for (const row of rows) {\n\n const [parsed, parseErr] = attemptSync(() =>\n JSON.parse(row.encrypted_value) as { iv: string; authTag: string; ciphertext: string },\n );\n\n if (parseErr) continue;\n\n const value = decryptSecret(parsed, vaultKey);\n if (!value) continue;\n\n secrets[row.secret_key] = {\n key: row.secret_key,\n value,\n setBy: row.set_by,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n };\n\n }\n\n return secrets;\n\n}\n\n/**\n * List all vault secret keys (without decrypting values).\n *\n * Uses dialect-aware table names to support both legacy prefixed and\n * schema-qualified table locations.\n *\n * @param db - Kysely database instance\n * @param dialect - Database dialect for table name resolution\n * @returns Array of secret key names\n *\n * @example\n * ```typescript\n * const keys = await listVaultSecretKeys(db, 'postgres');\n * console.log('Vault contains:', keys);\n * ```\n */\nexport async function listVaultSecretKeys(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n): Promise<string[]> {\n\n const ndb = noormDb(db, dialect);\n const tables = getNoormTables(dialect);\n\n const [rows, err] = await attempt(async () => {\n\n return ndb\n .selectFrom(tables.vault as keyof NoormDatabase)\n .select('secret_key')\n .orderBy('secret_key', 'asc')\n .execute();\n\n });\n\n if (err || !rows) return [];\n\n return rows.map((r) => r.secret_key);\n\n}\n\n/**\n * Delete a vault secret.\n *\n * Uses dialect-aware table names to support both legacy prefixed and\n * schema-qualified table locations.\n *\n * @param db - Kysely database instance\n * @param secretKey - The secret's key name\n * @param dialect - Database dialect for table name resolution\n *\n * @example\n * ```typescript\n * await deleteVaultSecret(db, 'OLD_API_KEY', 'postgres');\n * ```\n */\nexport async function deleteVaultSecret(\n db: Kysely<NoormDatabase>,\n secretKey: string,\n dialect: Dialect,\n): Promise<[boolean, Error | null]> {\n\n const ndb = noormDb(db, dialect);\n const tables = getNoormTables(dialect);\n\n const [result, err] = await attempt(async () => {\n\n return ndb\n .deleteFrom(tables.vault as keyof NoormDatabase)\n .where('secret_key', '=', secretKey)\n .execute();\n\n });\n\n if (err || !result) return [false, err ?? new Error('Delete failed')];\n\n const firstResult = result[0];\n const deleted = !!firstResult && Number(firstResult.numDeletedRows) > 0;\n\n if (deleted) {\n\n observer.emit('vault:secret:deleted', { key: secretKey });\n\n }\n\n return [deleted, null];\n\n}\n\n/**\n * Check if a vault secret exists.\n *\n * Uses dialect-aware table names to support both legacy prefixed and\n * schema-qualified table locations.\n *\n * @param db - Kysely database instance\n * @param secretKey - The secret's key name\n * @param dialect - Database dialect for table name resolution\n * @returns True if the secret exists\n */\nexport async function vaultSecretExists(\n db: Kysely<NoormDatabase>,\n secretKey: string,\n dialect: Dialect,\n): Promise<boolean> {\n\n const ndb = noormDb(db, dialect);\n const tables = getNoormTables(dialect);\n\n const [row, err] = await attempt(async () => {\n\n return ndb\n .selectFrom(tables.vault as keyof NoormDatabase)\n .select('id')\n .where('secret_key', '=', secretKey)\n .executeTakeFirst();\n\n });\n\n if (err) return false;\n\n return !!row;\n\n}\n\n/**\n * Get vault status.\n *\n * Uses dialect-aware table names to support both legacy prefixed and\n * schema-qualified table locations.\n *\n * @param db - Kysely database instance\n * @param identityHash - Current user's identity hash\n * @param dialect - Database dialect for table name resolution\n *\n * @example\n * ```typescript\n * const status = await getVaultStatus(db, identity.identityHash, 'postgres');\n * console.log('Vault initialized:', status.isInitialized);\n * console.log('Has access:', status.hasAccess);\n * ```\n */\nexport async function getVaultStatus(\n db: Kysely<NoormDatabase>,\n identityHash: string,\n dialect: Dialect,\n): Promise<VaultStatus> {\n\n const ndb = noormDb(db, dialect);\n const tables = getNoormTables(dialect);\n\n // Count secrets\n const [secretRows] = await attempt(async () => {\n\n return ndb\n .selectFrom(tables.vault as keyof NoormDatabase)\n .select(ndb.fn.count('id').as('count'))\n .executeTakeFirst();\n\n });\n\n const secretCount = secretRows ? Number(secretRows.count) : 0;\n\n // Count users with/without access\n const [identityRows] = await attempt(async () => {\n\n return ndb\n .selectFrom(tables.identities as keyof NoormDatabase)\n .select([\n 'identity_hash',\n 'encrypted_vault_key',\n ])\n .execute();\n\n });\n\n const identities = identityRows ?? [];\n const usersWithAccess = identities.filter((i) => i.encrypted_vault_key !== null).length;\n const usersWithoutAccess = identities.filter((i) => i.encrypted_vault_key === null).length;\n const isInitialized = usersWithAccess > 0;\n\n // Check if current user has access\n const currentUser = identities.find((i) => i.identity_hash === identityHash);\n const hasAccess = currentUser?.encrypted_vault_key !== null;\n\n return {\n isInitialized,\n hasAccess,\n secretCount,\n usersWithAccess,\n usersWithoutAccess,\n };\n\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export { eta, isTemplate, processFile, processFiles, renderTemplate } from './chunk-KF7GE2VM.js';
2
+ import './chunk-4HW4CS2C.js';
3
+ //# sourceMappingURL=engine-IFYFFWFR.js.map
4
+ //# sourceMappingURL=engine-IFYFFWFR.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-5K7FA66A.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-IFYFFWFR.js"}