@noormdev/sdk 1.0.0-alpha.9 → 1.0.1
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/LICENSE +21 -0
- package/README.md +81 -0
- package/dist/chunk-2RW4SL2O.js +97664 -0
- package/dist/chunk-D2XW2UOP.js +42 -0
- package/dist/chunk-DSXHOXDE.js +2591 -0
- package/dist/chunk-QAECL4RN.js +3372 -0
- package/dist/chunk-SPU42W75.js +13779 -0
- package/dist/chunk-TBRUDUBQ.js +1099 -0
- package/dist/chunk-UOFJT5PY.js +1499 -0
- package/dist/chunk-YJBKNUTP.js +7233 -0
- package/dist/csv-T5P3IN4K.js +7 -0
- package/dist/engine-S4DX3V33.js +11 -0
- package/dist/index.d.ts +3904 -2392
- package/dist/index.js +12980 -8777
- package/dist/json5-LNT3RGJ7.js +7 -0
- package/dist/mssql-NL6OHOMO.js +161 -0
- package/dist/{mysql-C2DR4TF7.js → mysql-5P43DYBY.js} +7 -4
- package/dist/{postgres-SIDJBSIT.js → postgres-NIL5BE3O.js} +7 -4
- package/dist/{sqlite-5VZTBN5J.js → sqlite-F3ZSSDUM.js} +5 -3
- package/dist/sqlite-bun-LMHUMGQI.js +60 -0
- package/dist/storage-6QBJ55SB.js +8 -0
- package/dist/yaml-XI7RQ2D5.js +7 -0
- package/package.json +7 -6
- package/dist/chunk-BMB5MF2T.js +0 -489
- package/dist/chunk-BMB5MF2T.js.map +0 -1
- package/dist/engine-HESCBITZ.js +0 -3
- package/dist/engine-HESCBITZ.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mssql-T4M7OGEC.js +0 -46
- package/dist/mssql-T4M7OGEC.js.map +0 -1
- package/dist/mysql-C2DR4TF7.js.map +0 -1
- package/dist/postgres-SIDJBSIT.js.map +0 -1
- package/dist/sqlite-5VZTBN5J.js.map +0 -1
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/identity/storage.ts","../../../src/core/identity/crypto.ts","../../../src/core/state/encryption/crypto.ts","../../../src/core/state/types.ts","../../../src/core/state/migrations.ts","../../../src/core/state/version.ts","../../../src/core/state/manager.ts","../../../src/core/state/index.ts","../../../src/core/settings/schema.ts","../../../src/core/settings/defaults.ts","../../../src/core/settings/rules.ts","../../../src/core/settings/manager.ts","../../../src/core/identity/resolver.ts","../../../src/core/identity/factory.ts","../../../src/core/connection/manager.ts","../../../src/core/connection/factory.ts","../../../src/core/version/types.ts","../../../src/core/version/schema/migrations/v1.ts","../../../src/core/update/checker.ts","../../../src/core/version/schema/index.ts","../../../src/core/shared/tables.ts","../../../src/core/environment.ts","../../../src/core/theme.ts","../../../src/core/logger/color.ts","../../../src/core/logger/redact.ts","../../../src/core/identity/sync.ts","../../../src/core/identity/index.ts","../../../src/core/config/schema.ts","../../../src/core/config/index.ts","../../../src/core/config/resolver.ts","../../../src/sdk/sql.ts","../../../src/core/explore/dialects/postgres.ts","../../../src/core/explore/dialects/mysql.ts","../../../src/core/explore/dialects/mssql.ts","../../../src/core/explore/dialects/sqlite.ts","../../../src/core/explore/dialects/index.ts","../../../src/core/explore/operations.ts","../../../src/core/teardown/dialects/postgres.ts","../../../src/core/teardown/dialects/mysql.ts","../../../src/core/teardown/dialects/mssql.ts","../../../src/core/teardown/dialects/sqlite.ts","../../../src/core/teardown/dialects/index.ts","../../../src/core/change/types.ts","../../../src/core/change/parser.ts","../../../src/core/change/scaffold.ts","../../../src/core/change/history.ts","../../../src/core/runner/tracker.ts","../../../src/core/change/tracker.ts","../../../src/core/runner/checksum.ts","../../../src/core/lock/types.ts","../../../src/core/lock/errors.ts","../../../src/core/lock/manager.ts","../../../src/core/change/executor.ts","../../../src/core/change/manager.ts","../../../src/core/teardown/operations.ts","../../../src/core/runner/runner.ts","../../../src/core/db/dual.ts","../../../src/core/transfer/same-server.ts","../../../src/core/transfer/dialects/postgres.ts","../../../src/core/transfer/dialects/mysql.ts","../../../src/core/transfer/dialects/mssql.ts","../../../src/core/transfer/dialects/index.ts","../../../src/core/dt/dialects/postgres.ts","../../../src/core/dt/dialects/mysql.ts","../../../src/core/dt/dialects/mssql.ts","../../../src/core/dt/dialects/index.ts","../../../src/core/dt/type-map.ts","../../../src/core/dt/version.ts","../../../src/core/dt/schema.ts","../../../src/core/transfer/planner.ts","../../../src/core/dt/streamer.ts","../../../src/core/transfer/executor.ts","../../../src/core/transfer/index.ts","../../../src/core/dt/writer.ts","../../../src/core/dt/serialize.ts","../../../src/core/dt/deserialize.ts","../../../src/core/dt/index.ts","../../../src/sdk/guards.ts","../../../src/sdk/noorm-ops.ts","../../../src/sdk/context.ts","../../../src/sdk/index.ts"],"names":["randomBytes","createCipheriv","createDecipheriv","join","attempt","attemptSync","path","fileExists","readFile","parseYaml","mkdir","stringifyYaml","writeFile","instance","conn","err","sql","resolveIdentity","DialectSchema","z","PortSchema","envConfig","merge","EXCLUDED_SCHEMAS","quote","qualifiedName","stat","readdir","access","fsConstants","data","durationMs","updateErr","fsWriteFile","isNoormTable","SQL_EXTENSIONS","loadAndRenderFile","executeFiles","results","executeDryRun","result","writeDryRunOutput","getDryRunOutputPath","quoteIdent","dialectOperations","plan","DEFAULT_BATCH_SIZE","schemaLine","createWriteStream","gzipSync","writeFileSync"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Key file storage for cryptographic identity.\n *\n * Private key stored at ~/.noorm/identity.key\n * Public key stored at ~/.noorm/identity.pub\n *\n * Private key is outside encrypted state to avoid bootstrap problem\n * (we need the key to decrypt state, but state contains the key).\n *\n * @example\n * ```typescript\n * // First-time setup\n * const keypair = generateKeyPair()\n * await saveKeyPair(keypair)\n *\n * // Later sessions\n * const privateKey = await loadPrivateKey()\n * ```\n */\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { chmod, mkdir, readFile, stat, writeFile } from 'fs/promises';\nimport { attempt, attemptSync } from '@logosdx/utils';\n\nimport type { KeyPair, CryptoIdentity } from './types.js';\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/** Base directory for noorm global config */\nconst NOORM_HOME = join(homedir(), '.noorm');\n\n/** Private key file path */\nconst PRIVATE_KEY_PATH = join(NOORM_HOME, 'identity.key');\n\n/** Public key file path */\nconst PUBLIC_KEY_PATH = join(NOORM_HOME, 'identity.pub');\n\n/** File permissions: owner read/write only */\nconst PRIVATE_KEY_MODE = 0o600;\n\n/** File permissions: owner read/write, others read */\nconst PUBLIC_KEY_MODE = 0o644;\n\n/** Identity metadata file path */\nconst IDENTITY_METADATA_PATH = join(NOORM_HOME, 'identity.json');\n\n// =============================================================================\n// Directory Setup\n// =============================================================================\n\n/**\n * Ensure ~/.noorm directory exists.\n */\nasync function ensureNoormDir(): Promise<void> {\n\n const [, err] = await attempt(() => mkdir(NOORM_HOME, { recursive: true }));\n\n if (err) {\n\n throw new Error(`Failed to create ${NOORM_HOME}: ${err.message}`);\n\n }\n\n}\n\n// =============================================================================\n// Key Storage\n// =============================================================================\n\n/**\n * Save keypair to disk.\n *\n * Creates ~/.noorm directory if it doesn't exist.\n * Sets appropriate file permissions (600 for private, 644 for public).\n *\n * @param keypair - The keypair to save\n *\n * @example\n * ```typescript\n * const keypair = generateKeyPair()\n * await saveKeyPair(keypair)\n * ```\n */\nexport async function saveKeyPair(keypair: KeyPair): Promise<void> {\n\n await ensureNoormDir();\n\n // Write private key\n const [, privateErr] = await attempt(() =>\n writeFile(PRIVATE_KEY_PATH, keypair.privateKey, {\n encoding: 'utf8',\n mode: PRIVATE_KEY_MODE,\n }),\n );\n\n if (privateErr) {\n\n throw new Error(`Failed to write private key: ${privateErr.message}`);\n\n }\n\n // Ensure permissions are correct (writeFile mode may not work on all platforms)\n await attempt(() => chmod(PRIVATE_KEY_PATH, PRIVATE_KEY_MODE));\n\n // Write public key\n const [, publicErr] = await attempt(() =>\n writeFile(PUBLIC_KEY_PATH, keypair.publicKey, { encoding: 'utf8', mode: PUBLIC_KEY_MODE }),\n );\n\n if (publicErr) {\n\n throw new Error(`Failed to write public key: ${publicErr.message}`);\n\n }\n\n await attempt(() => chmod(PUBLIC_KEY_PATH, PUBLIC_KEY_MODE));\n\n}\n\n/**\n * Save identity metadata to disk.\n *\n * Stores name, email, machine, OS alongside key files so that\n * identity can be reconstructed for new projects.\n *\n * @param identity - The identity metadata to save\n *\n * @example\n * ```typescript\n * const { identity } = await createCryptoIdentity({ name, email })\n * await saveIdentityMetadata(identity)\n * ```\n */\nexport async function saveIdentityMetadata(identity: CryptoIdentity): Promise<void> {\n\n await ensureNoormDir();\n\n const metadata = {\n identityHash: identity.identityHash,\n name: identity.name,\n email: identity.email,\n publicKey: identity.publicKey,\n machine: identity.machine,\n os: identity.os,\n createdAt: identity.createdAt,\n };\n\n const [, err] = await attempt(() =>\n writeFile(IDENTITY_METADATA_PATH, JSON.stringify(metadata, null, 2), { encoding: 'utf8' }),\n );\n\n if (err) {\n\n throw new Error(`Failed to write identity metadata: ${err.message}`);\n\n }\n\n}\n\n/**\n * Load identity metadata from disk.\n *\n * @returns Identity metadata or null if not found\n *\n * @example\n * ```typescript\n * const identity = await loadIdentityMetadata()\n * if (identity) {\n * await state.setIdentity(identity)\n * }\n * ```\n */\nexport async function loadIdentityMetadata(): Promise<CryptoIdentity | null> {\n\n const [content, err] = await attempt(() =>\n readFile(IDENTITY_METADATA_PATH, { encoding: 'utf8' }),\n );\n\n if (err) {\n\n // File doesn't exist = no metadata yet\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n\n return null;\n\n }\n\n throw new Error(`Failed to read identity metadata: ${err.message}`);\n\n }\n\n const [parsed, parseErr] = attemptSync(() => JSON.parse(content!) as CryptoIdentity);\n\n if (parseErr) {\n\n return null;\n\n }\n\n return parsed;\n\n}\n\n/**\n * Load private key from disk.\n *\n * @returns Private key as hex string, or null if not found\n *\n * @example\n * ```typescript\n * const privateKey = await loadPrivateKey()\n * if (!privateKey) {\n * // First-time setup needed\n * }\n * ```\n */\nexport async function loadPrivateKey(): Promise<string | null> {\n\n const [content, err] = await attempt(() => readFile(PRIVATE_KEY_PATH, { encoding: 'utf8' }));\n\n if (err) {\n\n // File doesn't exist = no identity yet\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n\n return null;\n\n }\n\n throw new Error(`Failed to read private key: ${err.message}`);\n\n }\n\n return content.trim();\n\n}\n\n/**\n * Load public key from disk.\n *\n * @returns Public key as hex string, or null if not found\n *\n * @example\n * ```typescript\n * const publicKey = await loadPublicKey()\n * console.log(`Share this with others: ${publicKey}`)\n * ```\n */\nexport async function loadPublicKey(): Promise<string | null> {\n\n const [content, err] = await attempt(() => readFile(PUBLIC_KEY_PATH, { encoding: 'utf8' }));\n\n if (err) {\n\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n\n return null;\n\n }\n\n throw new Error(`Failed to read public key: ${err.message}`);\n\n }\n\n return content.trim();\n\n}\n\n/**\n * Load full keypair from disk.\n *\n * @returns Keypair or null if identity not set up\n *\n * @example\n * ```typescript\n * const keypair = await loadKeyPair()\n * if (!keypair) {\n * console.log('Run noorm identity init first')\n * }\n * ```\n */\nexport async function loadKeyPair(): Promise<KeyPair | null> {\n\n const privateKey = await loadPrivateKey();\n const publicKey = await loadPublicKey();\n\n if (!privateKey || !publicKey) {\n\n return null;\n\n }\n\n return { privateKey, publicKey };\n\n}\n\n/**\n * Check if identity key files exist.\n *\n * @returns True if both key files exist\n */\nexport async function hasKeyFiles(): Promise<boolean> {\n\n const [privateStat] = await attempt(() => stat(PRIVATE_KEY_PATH));\n const [publicStat] = await attempt(() => stat(PUBLIC_KEY_PATH));\n\n return !!privateStat && !!publicStat;\n\n}\n\n// =============================================================================\n// Validation\n// =============================================================================\n\n/**\n * Validate that private key file has correct permissions.\n *\n * @returns True if permissions are 600 (owner read/write only)\n */\nexport async function validateKeyPermissions(): Promise<boolean> {\n\n const [stats, err] = await attempt(() => stat(PRIVATE_KEY_PATH));\n\n if (err) {\n\n return false;\n\n }\n\n // Check mode (mask off file type bits)\n const mode = stats.mode & 0o777;\n\n return mode === PRIVATE_KEY_MODE;\n\n}\n\n/**\n * Validate that a hex string is a valid X25519 key.\n *\n * X25519 keys are 32 bytes = 64 hex characters for the raw key,\n * but in DER format they're longer due to ASN.1 encoding.\n *\n * @param hex - Hex-encoded key to validate\n * @returns True if the key appears valid\n */\nexport function isValidKeyHex(hex: string): boolean {\n\n // Check hex format\n if (!/^[0-9a-f]+$/i.test(hex)) {\n\n return false;\n\n }\n\n // DER-encoded X25519 keys have specific lengths\n // PKCS8 private key: 48 bytes = 96 hex chars\n // SPKI public key: 44 bytes = 88 hex chars\n const validLengths = [88, 96];\n\n return validLengths.includes(hex.length);\n\n}\n\n// =============================================================================\n// Path Accessors\n// =============================================================================\n\n/**\n * Get the path to the private key file.\n */\nexport function getPrivateKeyPath(): string {\n\n return PRIVATE_KEY_PATH;\n\n}\n\n/**\n * Get the path to the public key file.\n */\nexport function getPublicKeyPath(): string {\n\n return PUBLIC_KEY_PATH;\n\n}\n\n/**\n * Get the path to the noorm home directory.\n */\nexport function getNoormHomePath(): string {\n\n return NOORM_HOME;\n\n}\n","/**\n * Cryptographic operations for identity.\n *\n * Uses X25519 for key exchange and AES-256-GCM for encryption.\n * Implements the ephemeral keypair pattern for secure config sharing.\n *\n * @example\n * ```typescript\n * // Generate keypair on first run\n * const { publicKey, privateKey } = generateKeyPair()\n *\n * // Encrypt config for recipient\n * const payload = encryptForRecipient(config, recipientPubKey)\n *\n * // Decrypt received config\n * const config = decryptWithPrivateKey(payload, privateKey)\n * ```\n */\nimport {\n generateKeyPairSync,\n createCipheriv,\n createDecipheriv,\n createPrivateKey,\n createPublicKey,\n diffieHellman,\n hkdfSync,\n randomBytes,\n} from 'crypto';\n\nimport type { KeyPair, SharedConfigPayload } from './types.js';\n\n// =============================================================================\n// Key Generation\n// =============================================================================\n\n/**\n * Generate an X25519 keypair for identity.\n *\n * X25519 is the standard for Diffie-Hellman key exchange.\n * Keys are returned as hex-encoded strings for storage.\n *\n * @example\n * ```typescript\n * const { publicKey, privateKey } = generateKeyPair()\n * // Store privateKey in ~/.noorm/identity.key\n * // Store publicKey in state and share with others\n * ```\n */\nexport function generateKeyPair(): KeyPair {\n\n const { publicKey, privateKey } = generateKeyPairSync('x25519', {\n publicKeyEncoding: { type: 'spki', format: 'der' },\n privateKeyEncoding: { type: 'pkcs8', format: 'der' },\n });\n\n return {\n publicKey: publicKey.toString('hex'),\n privateKey: privateKey.toString('hex'),\n };\n\n}\n\n// =============================================================================\n// Key Derivation\n// =============================================================================\n\n/**\n * Derive a shared secret from private key and public key.\n *\n * Uses X25519 ECDH to derive a shared secret that both parties\n * can independently compute.\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 *\n * @param sharedSecret - Raw shared secret from ECDH\n * @param info - Context string for key derivation\n * @returns 32-byte key for AES-256\n */\nfunction deriveEncryptionKey(sharedSecret: Buffer, info: string): Buffer {\n\n return Buffer.from(\n hkdfSync(\n 'sha256',\n sharedSecret,\n Buffer.alloc(0), // No salt needed for ECDH-derived secrets\n info,\n 32,\n ),\n );\n\n}\n\n// =============================================================================\n// Encryption for Config Sharing\n// =============================================================================\n\n/**\n * Encrypt data for a recipient using their public key.\n *\n * Uses the ephemeral keypair pattern:\n * 1. Generate ephemeral X25519 keypair\n * 2. Derive shared secret via ECDH\n * 3. Derive encryption key from shared secret\n * 4. Encrypt with AES-256-GCM\n *\n * @param plaintext - Data to encrypt (will be JSON stringified if object)\n * @param recipientPubKey - Recipient's X25519 public key (hex)\n * @param sender - Sender's email for metadata\n * @param recipient - Recipient's email for metadata\n *\n * @example\n * ```typescript\n * const payload = encryptForRecipient(\n * JSON.stringify(config),\n * recipientPubKey,\n * 'alice@example.com',\n * 'bob@example.com'\n * )\n * ```\n */\nexport function encryptForRecipient(\n plaintext: string,\n recipientPubKey: string,\n sender: string,\n recipient: string,\n): SharedConfigPayload {\n\n // Generate ephemeral keypair for this message\n const ephemeral = generateKeyPair();\n\n // Derive shared secret via ECDH\n const sharedSecret = deriveSharedSecret(ephemeral.privateKey, recipientPubKey);\n\n // Derive encryption key from shared secret\n const key = deriveEncryptionKey(sharedSecret, 'noorm-config-share');\n\n // Generate random IV\n const iv = randomBytes(16);\n\n // Encrypt with AES-256-GCM\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const authTag = cipher.getAuthTag();\n\n return {\n version: 1,\n sender,\n recipient,\n ephemeralPubKey: ephemeral.publicKey,\n iv: iv.toString('hex'),\n authTag: authTag.toString('hex'),\n ciphertext: ciphertext.toString('hex'),\n };\n\n}\n\n/**\n * Decrypt data using private key.\n *\n * Reverses the ephemeral keypair pattern:\n * 1. Derive shared secret from ephemeral pub + our private\n * 2. Derive decryption key\n * 3. Decrypt with AES-256-GCM\n *\n * @param payload - Encrypted payload from encryptForRecipient\n * @param privateKey - Recipient's X25519 private key (hex)\n *\n * @throws Error if decryption fails (wrong key, tampered data)\n *\n * @example\n * ```typescript\n * const plaintext = decryptWithPrivateKey(payload, privateKey)\n * const config = JSON.parse(plaintext)\n * ```\n */\nexport function decryptWithPrivateKey(payload: SharedConfigPayload, privateKey: string): string {\n\n if (payload.version !== 1) {\n\n throw new Error(`Unsupported payload version: ${payload.version}`);\n\n }\n\n // Derive shared secret from ephemeral pub + our private\n const sharedSecret = deriveSharedSecret(privateKey, payload.ephemeralPubKey);\n\n // Derive decryption key\n const key = deriveEncryptionKey(sharedSecret, 'noorm-config-share');\n\n // Decrypt\n const decipher = createDecipheriv('aes-256-gcm', key, Buffer.from(payload.iv, 'hex'));\n decipher.setAuthTag(Buffer.from(payload.authTag, 'hex'));\n\n const plaintext = Buffer.concat([\n decipher.update(Buffer.from(payload.ciphertext, 'hex')),\n decipher.final(),\n ]);\n\n return plaintext.toString('utf8');\n\n}\n\n// =============================================================================\n// Key Derivation for State Encryption\n// =============================================================================\n\n/**\n * Derive encryption key from private key for state encryption.\n *\n * This is used to encrypt the local state file. The key is derived\n * directly from the identity's private key (no shared secret needed).\n *\n * @param privateKey - X25519 private key (hex)\n * @returns 32-byte key for AES-256\n *\n * @example\n * ```typescript\n * const stateKey = deriveStateKey(privateKey)\n * // Use stateKey with AES-256-GCM to encrypt/decrypt state\n * ```\n */\nexport function deriveStateKey(privateKey: string): Buffer {\n\n const privateKeyBuffer = Buffer.from(privateKey, 'hex');\n\n return Buffer.from(\n hkdfSync(\n 'sha256',\n privateKeyBuffer,\n Buffer.alloc(0), // No salt - private key is already high entropy\n 'noorm-state-encryption',\n 32,\n ),\n );\n\n}\n\n/**\n * Encrypt state data using identity's private key.\n *\n * @param plaintext - State JSON string\n * @param privateKey - X25519 private key (hex)\n * @returns Encrypted payload with IV and auth tag\n */\nexport function encryptState(\n plaintext: string,\n privateKey: string,\n): { iv: string; authTag: string; ciphertext: string } {\n\n const key = deriveStateKey(privateKey);\n const iv = randomBytes(16);\n\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n const ciphertext = Buffer.concat([cipher.update(plaintext, '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 state data using identity's private key.\n *\n * @param encrypted - Encrypted payload from encryptState\n * @param privateKey - X25519 private key (hex)\n * @returns Decrypted state JSON string\n *\n * @throws Error if decryption fails\n */\nexport function decryptState(\n encrypted: { iv: string; authTag: string; ciphertext: string },\n privateKey: string,\n): string {\n\n const key = deriveStateKey(privateKey);\n\n const decipher = createDecipheriv('aes-256-gcm', key, Buffer.from(encrypted.iv, 'hex'));\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 * AES-256-GCM encryption/decryption.\n *\n * Provides authenticated encryption - both confidentiality and integrity.\n * Any tampering with the ciphertext will be detected.\n *\n * Encryption key is derived from the user's private key using HKDF.\n */\nimport { createCipheriv, createDecipheriv, randomBytes } from 'crypto';\nimport type { EncryptedPayload } from '../types.js';\nimport { deriveStateKey } from '../../identity/crypto.js';\n\nconst ALGORITHM = 'aes-256-gcm';\nconst IV_LENGTH = 16;\nconst AUTH_TAG_LENGTH = 16;\n\n/**\n * Encrypt a string using the private key.\n *\n * Uses HKDF to derive an encryption key from the private key,\n * then encrypts with AES-256-GCM.\n *\n * @example\n * ```typescript\n * const payload = encrypt('{\"configs\": {}}', privateKey)\n * // {\n * // algorithm: 'aes-256-gcm',\n * // iv: 'base64...',\n * // authTag: 'base64...',\n * // ciphertext: 'base64...'\n * // }\n * ```\n */\nexport function encrypt(plaintext: string, privateKey: string): EncryptedPayload {\n\n const key = deriveStateKey(privateKey);\n const iv = randomBytes(IV_LENGTH);\n\n const cipher = createCipheriv(ALGORITHM, key, iv, {\n authTagLength: AUTH_TAG_LENGTH,\n });\n\n const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n\n const authTag = cipher.getAuthTag();\n\n return {\n algorithm: ALGORITHM,\n iv: iv.toString('base64'),\n authTag: authTag.toString('base64'),\n ciphertext: ciphertext.toString('base64'),\n };\n\n}\n\n/**\n * Decrypt an encrypted payload and return the plaintext.\n *\n * Throws if decryption fails (wrong key, tampered data, etc.)\n *\n * @example\n * ```typescript\n * const plaintext = decrypt(payload, privateKey)\n * ```\n */\nexport function decrypt(payload: EncryptedPayload, privateKey: string): string {\n\n if (payload.algorithm !== ALGORITHM) {\n\n throw new Error(`Unsupported algorithm: ${payload.algorithm}`);\n\n }\n\n const key = deriveStateKey(privateKey);\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 decipher = createDecipheriv(ALGORITHM, key, iv, {\n authTagLength: AUTH_TAG_LENGTH,\n });\n\n decipher.setAuthTag(authTag);\n\n const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n\n return plaintext.toString('utf8');\n\n}\n","/**\n * State types.\n *\n * The State object is the in-memory representation of noorm's persistent data.\n * It holds configs, secrets, and known users.\n *\n * Note: Identity is stored globally in ~/.noorm/, not in project state.\n */\nimport type { Config, ConfigSummary } from '../config/types.js';\nimport type { KnownUser } from '../identity/types.js';\n\n// Re-export ConfigSummary from config/types to avoid duplication\nexport type { ConfigSummary };\n\n/**\n * The root state object stored in .noorm/state/state.enc\n *\n * Version tracks the package version that last wrote the state.\n * This enables migrations when the state schema changes between versions.\n */\nexport interface State {\n /** Package version that last saved this state */\n version: string;\n\n /** Known users discovered from database syncs (identityHash -> KnownUser) */\n knownUsers: Record<string, KnownUser>;\n\n /** Currently selected config name */\n activeConfig: string | null;\n\n /** All database configs (name -> Config) */\n configs: Record<string, Config>;\n\n /** Config-scoped secrets (configName -> key -> value) */\n secrets: Record<string, Record<string, string>>;\n\n /** App-level secrets (key -> value) */\n globalSecrets: Record<string, string>;\n}\n\n/**\n * Encrypted payload structure stored on disk.\n *\n * Uses AES-256-GCM with key derived from the user's private key via HKDF.\n */\nexport interface EncryptedPayload {\n /** Encryption algorithm (expected: AES-256-GCM, validated at runtime) */\n algorithm: string;\n\n /** Initialization vector (base64) */\n iv: string;\n\n /** Authentication tag (base64) */\n authTag: string;\n\n /** Encrypted state (base64) */\n ciphertext: string;\n}\n\n/**\n * Create an empty state with the given version.\n *\n * @example\n * ```typescript\n * import { createEmptyState } from './types'\n * import { version } from '../../../package.json'\n *\n * const state = createEmptyState(version)\n * ```\n */\nexport function createEmptyState(version: string): State {\n\n return {\n version,\n knownUsers: {},\n activeConfig: null,\n configs: {},\n secrets: {},\n globalSecrets: {},\n };\n\n}\n","/**\n * State migration system.\n *\n * Handles upgrading state files when the schema changes between versions.\n * Each migration adds missing fields with sensible defaults.\n *\n * WHY: State schema evolves over time. This ensures users don't lose data\n * when upgrading noorm, and we can add new fields without breaking existing state.\n */\nimport type { State } from './types.js';\nimport type { KnownUser } from '../identity/types.js';\nimport { observer } from '../observer.js';\n\n/**\n * Migrate state to current version.\n *\n * Ensures all required fields exist with defaults. Updates version stamp.\n *\n * @example\n * ```typescript\n * const migrated = migrateState(loadedState, packageVersion)\n * if (migrated.version !== loadedState.version) {\n * await persist(migrated)\n * }\n * ```\n */\nexport function migrateState(state: unknown, currentVersion: string): State {\n\n if (typeof state !== 'object' || state === null) {\n\n throw new Error('Invalid state format: expected object');\n\n }\n\n const obj = state as Record<string, unknown>;\n const previousVersion = obj['version'] as string | undefined;\n\n // Build migrated state with defaults for missing fields\n // Note: identity is now stored globally in ~/.noorm/, not in project state\n const migrated: State = {\n version: currentVersion,\n knownUsers: (obj['knownUsers'] as Record<string, KnownUser>) ?? {},\n activeConfig: (obj['activeConfig'] as string | null) ?? null,\n configs: (obj['configs'] as Record<string, unknown> as State['configs']) ?? {},\n secrets: (obj['secrets'] as Record<string, Record<string, string>>) ?? {},\n globalSecrets: (obj['globalSecrets'] as Record<string, string>) ?? {},\n };\n\n if (previousVersion !== currentVersion) {\n\n observer.emit('state:migrated', {\n from: previousVersion ?? 'unknown',\n to: currentVersion,\n });\n\n }\n\n return migrated;\n\n}\n\n/**\n * Check if state needs migration.\n */\nexport function needsMigration(state: unknown, currentVersion: string): boolean {\n\n if (typeof state !== 'object' || state === null) return true;\n\n const obj = state as Record<string, unknown>;\n\n // Version mismatch\n if (obj['version'] !== currentVersion) return true;\n\n // Missing required fields (add new fields here as they're added)\n if (!('globalSecrets' in obj)) return true;\n if (!('identity' in obj)) return true;\n if (!('knownUsers' in obj)) return true;\n\n return false;\n\n}\n","/**\n * Package version accessor.\n *\n * Provides the current package version for state versioning.\n * Version is injected at build time via esbuild define.\n */\n\n// Declare the build-time injected constant\ndeclare const __CLI_VERSION__: string;\n\n// Fallback for development (when not bundled)\nconst VERSION = typeof __CLI_VERSION__ !== 'undefined'\n ? __CLI_VERSION__\n : '0.0.0-dev';\n\n/**\n * Get the current package version.\n *\n * WHY: State files are versioned by the package version that last wrote them.\n * This enables migrations when upgrading noorm across versions.\n */\nexport function getPackageVersion(): string {\n\n return VERSION;\n\n}\n","/**\n * StateManager - Core state persistence with encryption.\n *\n * Handles loading, saving, and managing encrypted state.\n * All config, secret, and identity operations go through this class.\n *\n * Encryption uses the user's private key from ~/.noorm/identity.key\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { attemptSync, attempt } from '@logosdx/utils';\nimport type { Config } from '../config/types.js';\nimport type { KnownUser } from '../identity/types.js';\nimport { loadPrivateKey } from '../identity/storage.js';\nimport { encrypt, decrypt } from './encryption/index.js';\nimport type { State, ConfigSummary, EncryptedPayload } from './types.js';\nimport { createEmptyState } from './types.js';\nimport { migrateState, needsMigration } from './migrations.js';\nimport { getPackageVersion } from './version.js';\nimport { observer } from '../observer.js';\n\nconst DEFAULT_STATE_DIR = '.noorm/state';\nconst DEFAULT_STATE_FILE = 'state.enc';\n\n/**\n * Options for StateManager constructor.\n */\nexport interface StateManagerOptions {\n /** Private key for encryption (loaded from ~/.noorm/identity.key if not provided) */\n privateKey?: string;\n\n /** State directory name (defaults to '.noorm') */\n stateDir?: string;\n\n /** State filename (defaults to 'state.enc') */\n stateFile?: string;\n}\n\n/**\n * Manages encrypted state persistence.\n *\n * @example\n * ```typescript\n * const state = new StateManager(process.cwd())\n * await state.load()\n *\n * await state.setConfig('dev', { ... })\n * await state.setActiveConfig('dev')\n *\n * const config = state.getActiveConfig()\n * ```\n *\n * @example\n * ```typescript\n * // For testing with custom paths\n * const state = new StateManager('/tmp/test', {\n * stateDir: '.test-noorm',\n * stateFile: 'test-state.enc',\n * privateKey: testPrivateKey,\n * })\n * ```\n */\nexport class StateManager {\n\n private state: State | null = null;\n private privateKey: string | undefined;\n private statePath: string;\n private loaded = false;\n\n constructor(\n private readonly projectRoot: string,\n options: StateManagerOptions = {},\n ) {\n\n this.privateKey = options.privateKey;\n const stateDir = options.stateDir ?? DEFAULT_STATE_DIR;\n const stateFile = options.stateFile ?? DEFAULT_STATE_FILE;\n this.statePath = join(projectRoot, stateDir, stateFile);\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Load state from disk. Creates empty state if file doesn't exist.\n * Applies migrations if state version differs from current package version.\n * Must be called before any other operations.\n *\n * Tries to load private key from ~/.noorm/identity.key if not provided.\n */\n async load(): Promise<void> {\n\n if (this.loaded) return;\n\n // Try to load private key if not provided\n if (!this.privateKey) {\n\n const [key] = await attempt(() => loadPrivateKey());\n if (key) {\n\n this.privateKey = key;\n\n }\n\n }\n\n const currentVersion = getPackageVersion();\n\n // New project - no state file yet\n if (!existsSync(this.statePath)) {\n\n this.state = createEmptyState(currentVersion);\n this.loaded = true;\n observer.emit('state:loaded', {\n configCount: 0,\n activeConfig: null,\n version: currentVersion,\n });\n\n return;\n\n }\n\n // Existing state file - require private key\n if (!this.privateKey) {\n\n throw new Error(\n 'Private key required to decrypt state. ' + 'Set up identity with: noorm init',\n );\n\n }\n\n const [raw, readErr] = attemptSync(() => readFileSync(this.statePath, 'utf8'));\n if (readErr) {\n\n observer.emit('error', { source: 'state', error: readErr });\n throw readErr;\n\n }\n\n const [payload, parseErr] = attemptSync(() => JSON.parse(raw!) as EncryptedPayload);\n if (parseErr) {\n\n observer.emit('error', { source: 'state', error: parseErr });\n throw new Error('Failed to parse state file. File may be corrupted.');\n\n }\n\n const [decrypted, decryptErr] = attemptSync(() => decrypt(payload!, this.privateKey!));\n if (decryptErr) {\n\n observer.emit('error', { source: 'state', error: decryptErr });\n throw new Error('Failed to decrypt state. Wrong key or corrupted file.');\n\n }\n\n const [parsedState, stateParseErr] = attemptSync(() => JSON.parse(decrypted!) as unknown);\n if (stateParseErr) {\n\n observer.emit('error', { source: 'state', error: stateParseErr });\n throw new Error('Failed to parse decrypted state.');\n\n }\n\n // Apply migrations if needed (migrateState emits state:migrated if version changed)\n const wasMigrated = needsMigration(parsedState, currentVersion);\n this.state = migrateState(parsedState, currentVersion);\n this.loaded = true;\n\n // Persist if migrations were applied\n if (wasMigrated) {\n\n this.persist();\n\n }\n\n observer.emit('state:loaded', {\n configCount: Object.keys(this.state.configs).length,\n activeConfig: this.state.activeConfig,\n version: this.state.version,\n });\n\n }\n\n /**\n * Reload private key from disk.\n *\n * Call this after identity is created to ensure the manager\n * can encrypt/decrypt state. Useful when the singleton was\n * created before the identity files existed.\n *\n * @returns true if key was loaded successfully\n */\n async reloadPrivateKey(): Promise<boolean> {\n\n const [key] = await attempt(() => loadPrivateKey());\n if (key) {\n\n this.privateKey = key;\n\n return true;\n\n }\n\n return false;\n\n }\n\n /**\n * Persist current state to disk (encrypted).\n *\n * Requires private key to be set.\n */\n private persist(): void {\n\n if (!this.privateKey) {\n\n throw new Error(\n 'Private key required to save state. ' + 'Set up identity with: noorm init',\n );\n\n }\n\n const state = this.getState();\n\n const dir = dirname(this.statePath);\n if (!existsSync(dir)) {\n\n mkdirSync(dir, { recursive: true });\n\n }\n\n const json = JSON.stringify(state);\n const payload = encrypt(json, this.privateKey);\n\n const [, writeErr] = attemptSync(() =>\n writeFileSync(this.statePath, JSON.stringify(payload, null, 2)),\n );\n\n if (writeErr) {\n\n observer.emit('error', { source: 'state', error: writeErr });\n throw writeErr;\n\n }\n\n observer.emit('state:persisted', {\n configCount: Object.keys(state.configs).length,\n });\n\n }\n\n /**\n * Get the loaded state, throwing if not loaded.\n */\n private getState(): State {\n\n if (!this.loaded || !this.state) {\n\n throw new Error('StateManager not loaded. Call load() first.');\n\n }\n\n return this.state;\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Config Operations\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get a config by name.\n */\n getConfig(name: string): Config | null {\n\n const state = this.getState();\n\n return state.configs[name] ?? null;\n\n }\n\n /**\n * Set (create or update) a config.\n */\n async setConfig(name: string, config: Config): Promise<void> {\n\n const state = this.getState();\n const isNew = !state.configs[name];\n state.configs[name] = config;\n this.persist();\n\n observer.emit(isNew ? 'config:created' : 'config:updated', {\n name,\n fields: Object.keys(config),\n });\n\n }\n\n /**\n * Delete a config and its secrets.\n */\n async deleteConfig(name: string): Promise<void> {\n\n const state = this.getState();\n delete state.configs[name];\n delete state.secrets[name];\n\n if (state.activeConfig === name) {\n\n state.activeConfig = null;\n\n }\n\n this.persist();\n observer.emit('config:deleted', { name });\n\n }\n\n /**\n * List all configs with summary info.\n */\n listConfigs(): ConfigSummary[] {\n\n const state = this.getState();\n\n return Object.entries(state.configs).map(([name, config]) => ({\n name,\n type: config.type,\n isTest: config.isTest,\n protected: config.protected,\n isActive: state.activeConfig === name,\n dialect: config.connection.dialect,\n database: config.connection.database,\n }));\n\n }\n\n /**\n * Get the active config.\n */\n getActiveConfig(): Config | null {\n\n const state = this.getState();\n if (!state.activeConfig) return null;\n\n return state.configs[state.activeConfig] ?? null;\n\n }\n\n /**\n * Get the active config name.\n */\n getActiveConfigName(): string | null {\n\n const state = this.getState();\n\n return state.activeConfig;\n\n }\n\n /**\n * Set the active config.\n */\n async setActiveConfig(name: string): Promise<void> {\n\n const state = this.getState();\n if (!state.configs[name]) {\n\n throw new Error(`Config \"${name}\" does not exist.`);\n\n }\n\n const previous = state.activeConfig;\n state.activeConfig = name;\n this.persist();\n\n observer.emit('config:activated', { name, previous });\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Secret Operations\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get a secret value.\n */\n getSecret(configName: string, key: string): string | null {\n\n const state = this.getState();\n\n return state.secrets[configName]?.[key] ?? null;\n\n }\n\n /**\n * Get all secrets for a config.\n */\n getAllSecrets(configName: string): Record<string, string> {\n\n const state = this.getState();\n\n return state.secrets[configName] ? { ...state.secrets[configName] } : {};\n\n }\n\n /**\n * Set a secret value.\n */\n async setSecret(configName: string, key: string, value: string): Promise<void> {\n\n const state = this.getState();\n\n if (!state.configs[configName]) {\n\n throw new Error(`Config \"${configName}\" does not exist.`);\n\n }\n\n if (!state.secrets[configName]) {\n\n state.secrets[configName] = {};\n\n }\n\n state.secrets[configName][key] = value;\n this.persist();\n\n observer.emit('secret:set', { configName, key });\n\n }\n\n /**\n * Delete a secret.\n */\n async deleteSecret(configName: string, key: string): Promise<void> {\n\n const state = this.getState();\n\n if (state.secrets[configName]) {\n\n delete state.secrets[configName][key];\n this.persist();\n\n observer.emit('secret:deleted', { configName, key });\n\n }\n\n }\n\n /**\n * List all secret keys for a config (not values).\n */\n listSecrets(configName: string): string[] {\n\n const state = this.getState();\n\n return Object.keys(state.secrets[configName] ?? {});\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Global Secret Operations\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get a global secret value (app-level, not config-specific).\n *\n * @example\n * ```typescript\n * const apiKey = state.getGlobalSecret('ANTHROPIC_API_KEY')\n * ```\n */\n getGlobalSecret(key: string): string | null {\n\n const state = this.getState();\n\n return state.globalSecrets[key] ?? null;\n\n }\n\n /**\n * Get all global secrets.\n */\n getAllGlobalSecrets(): Record<string, string> {\n\n const state = this.getState();\n\n return { ...state.globalSecrets };\n\n }\n\n /**\n * Set a global secret value.\n *\n * @example\n * ```typescript\n * await state.setGlobalSecret('ANTHROPIC_API_KEY', 'sk-ant-...')\n * ```\n */\n async setGlobalSecret(key: string, value: string): Promise<void> {\n\n const state = this.getState();\n state.globalSecrets[key] = value;\n this.persist();\n\n observer.emit('global-secret:set', { key });\n\n }\n\n /**\n * Delete a global secret.\n */\n async deleteGlobalSecret(key: string): Promise<void> {\n\n const state = this.getState();\n\n if (key in state.globalSecrets) {\n\n delete state.globalSecrets[key];\n this.persist();\n\n observer.emit('global-secret:deleted', { key });\n\n }\n\n }\n\n /**\n * List all global secret keys (not values).\n */\n listGlobalSecrets(): string[] {\n\n const state = this.getState();\n\n return Object.keys(state.globalSecrets);\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Known Users Operations\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get all known users (discovered from database syncs).\n */\n getKnownUsers(): Record<string, KnownUser> {\n\n const state = this.getState();\n\n return { ...state.knownUsers };\n\n }\n\n /**\n * Get a known user by identity hash.\n */\n getKnownUser(identityHash: string): KnownUser | null {\n\n const state = this.getState();\n\n return state.knownUsers[identityHash] ?? null;\n\n }\n\n /**\n * Find known users by email.\n *\n * Returns all users with the given email (may be multiple machines).\n */\n findKnownUsersByEmail(email: string): KnownUser[] {\n\n const state = this.getState();\n\n return Object.values(state.knownUsers).filter((u) => u.email === email);\n\n }\n\n /**\n * Add or update a known user.\n *\n * Called during database sync to cache discovered identities.\n */\n async addKnownUser(user: KnownUser): Promise<void> {\n\n const state = this.getState();\n state.knownUsers[user.identityHash] = user;\n this.persist();\n\n observer.emit('known-user:added', {\n email: user.email,\n source: user.source,\n });\n\n }\n\n /**\n * Add multiple known users (batch operation).\n */\n async addKnownUsers(users: KnownUser[]): Promise<void> {\n\n const state = this.getState();\n\n for (const user of users) {\n\n state.knownUsers[user.identityHash] = user;\n\n }\n\n this.persist();\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Utilities\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get the current state version (package version).\n */\n getVersion(): string {\n\n const state = this.getState();\n\n return state.version;\n\n }\n\n /**\n * Check if state file exists (before loading).\n */\n exists(): boolean {\n\n return existsSync(this.statePath);\n\n }\n\n /**\n * Get the path to the state file.\n */\n getStatePath(): string {\n\n return this.statePath;\n\n }\n\n /**\n * Export state for backup (still encrypted).\n */\n exportEncrypted(): string | null {\n\n if (!existsSync(this.statePath)) return null;\n\n return readFileSync(this.statePath, 'utf8');\n\n }\n\n /**\n * Import state from backup.\n */\n async importEncrypted(encrypted: string): Promise<void> {\n\n if (!this.privateKey) {\n\n throw new Error('Private key required to import state.');\n\n }\n\n // Validate it can be decrypted first\n const [payload, parseErr] = attemptSync(() => JSON.parse(encrypted) as EncryptedPayload);\n if (parseErr) throw parseErr;\n\n const [, decryptErr] = attemptSync(() => decrypt(payload!, this.privateKey!));\n if (decryptErr) throw decryptErr;\n\n const dir = dirname(this.statePath);\n if (!existsSync(dir)) {\n\n mkdirSync(dir, { recursive: true });\n\n }\n\n writeFileSync(this.statePath, encrypted);\n this.loaded = false;\n await this.load();\n\n }\n\n /**\n * Set the private key for encryption.\n *\n * Used after first-time identity setup.\n */\n setPrivateKey(privateKey: string): void {\n\n this.privateKey = privateKey;\n\n }\n\n /**\n * Check if private key is available.\n */\n hasPrivateKey(): boolean {\n\n return !!this.privateKey;\n\n }\n\n}\n","/**\n * State module exports.\n *\n * Provides StateManager class and singleton helpers.\n */\nimport { StateManager } from './manager.js';\n\nexport { StateManager };\nexport type { StateManagerOptions } from './manager.js';\nexport * from './types.js';\nexport { migrateState, needsMigration } from './migrations.js';\nexport { getPackageVersion } from './version.js';\n\nlet instance: StateManager | null = null;\n\n/**\n * Get or create the StateManager singleton.\n *\n * @example\n * ```typescript\n * const state = getStateManager()\n * // Must call load() if not already loaded\n * ```\n */\nexport function getStateManager(projectRoot?: string): StateManager {\n\n if (!instance) {\n\n const root = projectRoot ?? process.cwd();\n instance = new StateManager(root);\n\n }\n\n return instance;\n\n}\n\n/**\n * Initialize the StateManager. Must be called at app startup.\n *\n * @example\n * ```typescript\n * const state = await initState()\n * const config = state.getActiveConfig()\n * ```\n */\nexport async function initState(projectRoot?: string): Promise<StateManager> {\n\n const manager = getStateManager(projectRoot);\n await manager.load();\n\n return manager;\n\n}\n\n/**\n * Reset the singleton (for testing).\n *\n * @example\n * ```typescript\n * beforeEach(() => {\n * resetStateManager()\n * })\n * ```\n */\nexport function resetStateManager(): void {\n\n instance = null;\n\n}\n","/**\n * Settings Zod schemas and validation.\n *\n * Settings define project-wide build behavior and stage configuration.\n * Validated on load to prevent invalid configurations from being used.\n */\nimport { z } from 'zod';\n\n// ─────────────────────────────────────────────────────────────\n// Base Schemas\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Valid database dialects.\n */\nconst DialectSchema = z.enum(['postgres', 'mysql', 'sqlite', 'mssql']);\n\n/**\n * Secret type for CLI input handling.\n */\nconst SecretTypeSchema = z.enum(['string', 'password', 'api_key', 'connection_string']);\n\n/**\n * Connection type.\n */\nconst ConnectionTypeSchema = z.enum(['local', 'remote']);\n\n/**\n * Log level.\n */\nconst LogLevelSchema = z.enum(['silent', 'error', 'warn', 'info', 'verbose']);\n\n/**\n * Port number validation.\n */\nconst PortSchema = z\n .number()\n .int()\n .min(1, 'Port must be at least 1')\n .max(65535, 'Port must be at most 65535');\n\n/**\n * File size pattern (e.g., '10mb', '100kb').\n */\nconst FileSizeSchema = z\n .string()\n .regex(/^\\d+\\s*(b|kb|mb|gb)$/i, 'Invalid file size format (e.g., \"10mb\")');\n\n// ─────────────────────────────────────────────────────────────\n// Stage Schemas\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Required secret definition for a stage.\n */\nconst StageSecretSchema = z.object({\n key: z.string().min(1, 'Secret key is required'),\n type: SecretTypeSchema,\n description: z.string().optional(),\n required: z.boolean().default(true),\n});\n\n/**\n * Stage defaults - values applied when creating a config from this stage.\n */\nconst StageDefaultsSchema = z.object({\n dialect: DialectSchema.optional(),\n host: z.string().optional(),\n port: PortSchema.optional(),\n database: z.string().optional(),\n user: z.string().optional(),\n password: z.string().optional(),\n ssl: z.boolean().optional(),\n isTest: z.boolean().optional(),\n protected: z.boolean().optional(),\n});\n\n/**\n * Stage definition - a preconfigured config template.\n */\nconst StageSchema = z.object({\n description: z.string().optional(),\n locked: z.boolean().default(false),\n defaults: StageDefaultsSchema.optional(),\n secrets: z.array(StageSecretSchema).optional(),\n});\n\n// ─────────────────────────────────────────────────────────────\n// Rule Schemas\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Conditions for rule matching.\n * All conditions are AND'd together.\n */\nconst RuleMatchSchema = z\n .object({\n name: z.string().optional(),\n protected: z.boolean().optional(),\n isTest: z.boolean().optional(),\n type: ConnectionTypeSchema.optional(),\n })\n .refine((match) => Object.keys(match).length > 0, {\n message: 'Rule match must specify at least one condition',\n });\n\n/**\n * Stage-based rule for conditional include/exclude.\n */\nconst RuleSchema = z\n .object({\n match: RuleMatchSchema,\n include: z.array(z.string()).optional(),\n exclude: z.array(z.string()).optional(),\n })\n .refine((rule) => rule.include || rule.exclude, {\n message: 'Rule must specify at least one of include or exclude',\n });\n\n// ─────────────────────────────────────────────────────────────\n// Config Section Schemas\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Build configuration schema.\n */\nconst BuildConfigSchema = z.object({\n include: z.array(z.string()).optional(),\n exclude: z.array(z.string()).optional(),\n});\n\n/**\n * Path configuration schema.\n */\nconst PathConfigSchema = z.object({\n sql: z.string().optional(),\n changes: z.string().optional(),\n});\n\n/**\n * Strict mode configuration schema.\n */\nconst StrictConfigSchema = z.object({\n enabled: z.boolean().default(false),\n stages: z.array(z.string()).optional(),\n});\n\n/**\n * Logging configuration schema.\n */\nconst LoggingConfigSchema = z.object({\n enabled: z.boolean().default(true),\n level: LogLevelSchema.default('info'),\n file: z.string().default('.noorm/state/noorm.log'),\n maxSize: FileSizeSchema.default('10mb'),\n maxFiles: z.number().int().min(1).default(5),\n});\n\n// ─────────────────────────────────────────────────────────────\n// Main Settings Schema\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Complete settings schema.\n */\nexport const SettingsSchema = z.object({\n build: BuildConfigSchema.optional(),\n paths: PathConfigSchema.optional(),\n rules: z.array(RuleSchema).optional(),\n stages: z.record(z.string(), StageSchema).optional(),\n strict: StrictConfigSchema.optional(),\n logging: LoggingConfigSchema.optional(),\n secrets: z.array(StageSecretSchema).optional(),\n});\n\n// ─────────────────────────────────────────────────────────────\n// Type Exports\n// ─────────────────────────────────────────────────────────────\n\nexport type SettingsSchemaType = z.infer<typeof SettingsSchema>;\nexport type StageSchemaType = z.infer<typeof StageSchema>;\nexport type StageDefaultsSchemaType = z.infer<typeof StageDefaultsSchema>;\nexport type StageSecretSchemaType = z.infer<typeof StageSecretSchema>;\nexport type RuleSchemaType = z.infer<typeof RuleSchema>;\nexport type RuleMatchSchemaType = z.infer<typeof RuleMatchSchema>;\nexport type BuildConfigSchemaType = z.infer<typeof BuildConfigSchema>;\nexport type PathConfigSchemaType = z.infer<typeof PathConfigSchema>;\nexport type StrictConfigSchemaType = z.infer<typeof StrictConfigSchema>;\nexport type LoggingConfigSchemaType = z.infer<typeof LoggingConfigSchema>;\n\n// ─────────────────────────────────────────────────────────────\n// Validation Error\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Error thrown when settings validation fails.\n */\nexport class SettingsValidationError extends Error {\n\n constructor(\n message: string,\n public readonly field: string,\n public readonly issues: z.ZodIssue[],\n ) {\n\n super(message);\n this.name = 'SettingsValidationError';\n\n }\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Validation Functions\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Validate a settings object.\n *\n * @throws SettingsValidationError if validation fails\n *\n * @example\n * ```typescript\n * const [_, err] = attemptSync(() => validateSettings(settings))\n * if (err) {\n * console.error(`Invalid settings: ${err.message}`)\n * }\n * ```\n */\nexport function validateSettings(settings: unknown): asserts settings is SettingsSchemaType {\n\n const result = SettingsSchema.safeParse(settings);\n\n if (!result.success) {\n\n const firstIssue = result.error.issues[0];\n\n throw new SettingsValidationError(\n firstIssue?.message ?? 'Settings validation failed',\n firstIssue?.path.join('.') || 'unknown',\n result.error.issues,\n );\n\n }\n\n}\n\n/**\n * Parse and validate settings, returning defaults for missing fields.\n *\n * @example\n * ```typescript\n * const settings = parseSettings({\n * build: { include: ['schema'] }\n * })\n * // settings.logging.level === 'info' (default)\n * ```\n */\nexport function parseSettings(settings: unknown): SettingsSchemaType {\n\n const result = SettingsSchema.safeParse(settings);\n\n if (!result.success) {\n\n const firstIssue = result.error.issues[0];\n\n throw new SettingsValidationError(\n firstIssue?.message ?? 'Settings validation failed',\n firstIssue?.path.join('.') || 'unknown',\n result.error.issues,\n );\n\n }\n\n return result.data;\n\n}\n\n/**\n * Validate a single stage definition.\n *\n * @throws SettingsValidationError if validation fails\n */\nexport function validateStage(stage: unknown): asserts stage is StageSchemaType {\n\n const result = StageSchema.safeParse(stage);\n\n if (!result.success) {\n\n const firstIssue = result.error.issues[0];\n\n throw new SettingsValidationError(\n firstIssue?.message ?? 'Stage validation failed',\n firstIssue?.path.join('.') || 'unknown',\n result.error.issues,\n );\n\n }\n\n}\n\n/**\n * Validate a single rule definition.\n *\n * @throws SettingsValidationError if validation fails\n */\nexport function validateRule(rule: unknown): asserts rule is RuleSchemaType {\n\n const result = RuleSchema.safeParse(rule);\n\n if (!result.success) {\n\n const firstIssue = result.error.issues[0];\n\n throw new SettingsValidationError(\n firstIssue?.message ?? 'Rule validation failed',\n firstIssue?.path.join('.') || 'unknown',\n result.error.issues,\n );\n\n }\n\n}\n","/**\n * Default Settings\n *\n * Sensible defaults used when no settings.yml exists or when\n * optional fields are missing.\n */\nimport type { Settings, BuildConfig, PathConfig, StrictConfig, LoggingConfig } from './types.js';\n\n/**\n * Default build configuration.\n *\n * Empty include means all files in the SQL directory are included.\n * Users can restrict to specific subdirectories via settings.\n */\nexport const DEFAULT_BUILD_CONFIG: BuildConfig = {\n include: [],\n exclude: [],\n};\n\n/**\n * Default path configuration.\n *\n * Standard locations relative to project root.\n */\nexport const DEFAULT_PATH_CONFIG: PathConfig = {\n sql: './sql',\n changes: './changes',\n};\n\n/**\n * Default strict mode configuration.\n *\n * Disabled by default - no required stages.\n */\nexport const DEFAULT_STRICT_CONFIG: StrictConfig = {\n enabled: false,\n stages: [],\n};\n\n/**\n * Default logging configuration.\n */\nexport const DEFAULT_LOGGING_CONFIG: LoggingConfig = {\n enabled: true,\n level: 'info',\n file: '.noorm/state/noorm.log',\n maxSize: '10mb',\n maxFiles: 5,\n};\n\n/**\n * Complete default settings.\n *\n * Used when no settings.yml exists.\n *\n * @example\n * ```typescript\n * // If settings.yml doesn't exist, use defaults\n * const settings = await loadSettings() ?? DEFAULT_SETTINGS\n * ```\n */\nexport const DEFAULT_SETTINGS: Settings = {\n build: DEFAULT_BUILD_CONFIG,\n paths: DEFAULT_PATH_CONFIG,\n rules: [],\n stages: {},\n strict: DEFAULT_STRICT_CONFIG,\n logging: DEFAULT_LOGGING_CONFIG,\n};\n\n/**\n * Create a fresh copy of default settings.\n *\n * IMPORTANT: Use this instead of spreading DEFAULT_SETTINGS\n * to avoid shared references to mutable nested objects.\n *\n * @example\n * ```typescript\n * // Good - creates fresh copy\n * this.#settings = createDefaultSettings()\n *\n * // Bad - shares references to rules[], stages{}, etc.\n * this.#settings = { ...DEFAULT_SETTINGS }\n * ```\n */\nexport function createDefaultSettings(): Settings {\n\n return {\n build: {\n include: [...(DEFAULT_BUILD_CONFIG.include ?? [])],\n exclude: [...(DEFAULT_BUILD_CONFIG.exclude ?? [])],\n },\n paths: { ...DEFAULT_PATH_CONFIG },\n rules: [],\n stages: {},\n strict: { ...DEFAULT_STRICT_CONFIG, stages: [...(DEFAULT_STRICT_CONFIG.stages ?? [])] },\n logging: { ...DEFAULT_LOGGING_CONFIG },\n };\n\n}\n\n/**\n * Settings file location relative to project root.\n */\nexport const SETTINGS_FILE_PATH = '.noorm/settings.yml';\n\n/**\n * Settings directory relative to project root.\n */\nexport const SETTINGS_DIR_PATH = '.noorm';\n\n/**\n * State directory relative to project root.\n *\n * Contains gitignored artifacts: logs, sql history, etc.\n */\nexport const STATE_DIR_PATH = '.noorm/state';\n","/**\n * Rule Evaluation\n *\n * Evaluates stage-based rules against a config to determine\n * which folders should be included or excluded from builds.\n *\n * Rules use AND matching - all conditions in a rule must match.\n * Multiple rules are evaluated in order; later rules can override earlier ones.\n */\nimport type {\n Rule,\n RuleMatch,\n RuleEvaluationResult,\n RulesEvaluationResult,\n ConfigForRuleMatch,\n} from './types.js';\n\n/**\n * Check if a single condition matches.\n *\n * @example\n * ```typescript\n * matchesCondition({ isTest: true }, 'isTest', true) // true\n * matchesCondition({ isTest: false }, 'isTest', true) // false\n * ```\n */\nfunction _matchesCondition<K extends keyof RuleMatch>(\n config: ConfigForRuleMatch,\n key: K,\n expected: RuleMatch[K],\n): boolean {\n\n if (expected === undefined) {\n\n return true;\n\n }\n\n return config[key as keyof ConfigForRuleMatch] === expected;\n\n}\n\n/**\n * Check if all conditions in a rule match the config.\n *\n * All specified conditions must be true (AND logic).\n *\n * @example\n * ```typescript\n * const rule = { match: { isTest: true, type: 'local' } }\n * const config = { name: 'dev', isTest: true, type: 'local', protected: false }\n *\n * ruleMatches(rule.match, config) // true\n * ```\n */\nexport function ruleMatches(match: RuleMatch, config: ConfigForRuleMatch): boolean {\n\n // Check each condition - all must match (AND logic)\n if (match.name !== undefined && config.name !== match.name) {\n\n return false;\n\n }\n\n if (match.protected !== undefined && config.protected !== match.protected) {\n\n return false;\n\n }\n\n if (match.isTest !== undefined && config.isTest !== match.isTest) {\n\n return false;\n\n }\n\n if (match.type !== undefined && config.type !== match.type) {\n\n return false;\n\n }\n\n return true;\n\n}\n\n/**\n * Evaluate a single rule against a config.\n *\n * Returns the matched status and any include/exclude paths from the rule.\n *\n * @example\n * ```typescript\n * const rule = {\n * match: { isTest: true },\n * include: ['sql/seeds'],\n * }\n *\n * const result = evaluateRule(rule, testConfig)\n * // { matched: true, include: ['sql/seeds'], exclude: [] }\n * ```\n */\nexport function evaluateRule(rule: Rule, config: ConfigForRuleMatch): RuleEvaluationResult {\n\n const matched = ruleMatches(rule.match, config);\n\n if (!matched) {\n\n return {\n matched: false,\n include: [],\n exclude: [],\n };\n\n }\n\n return {\n matched: true,\n include: rule.include ?? [],\n exclude: rule.exclude ?? [],\n };\n\n}\n\n/**\n * Evaluate all rules against a config.\n *\n * Rules are evaluated in order. Later rules can override earlier ones:\n * - If a folder is in both include and exclude, the later rule wins\n *\n * @example\n * ```typescript\n * const rules = [\n * { match: { isTest: true }, include: ['sql/seeds'] },\n * { match: { protected: true }, exclude: ['sql/dangerous'] },\n * ]\n *\n * const result = evaluateRules(rules, config)\n * // { matchedRules: [...], include: ['sql/seeds'], exclude: ['sql/dangerous'] }\n * ```\n */\nexport function evaluateRules(rules: Rule[], config: ConfigForRuleMatch): RulesEvaluationResult {\n\n const matchedRules: Rule[] = [];\n const includeSet = new Set<string>();\n const excludeSet = new Set<string>();\n\n for (const rule of rules) {\n\n const result = evaluateRule(rule, config);\n\n if (result.matched) {\n\n matchedRules.push(rule);\n\n // Add includes (remove from exclude if present)\n for (const path of result.include) {\n\n includeSet.add(path);\n excludeSet.delete(path);\n\n }\n\n // Add excludes (remove from include if present)\n for (const path of result.exclude) {\n\n excludeSet.add(path);\n includeSet.delete(path);\n\n }\n\n }\n\n }\n\n return {\n matchedRules,\n include: Array.from(includeSet),\n exclude: Array.from(excludeSet),\n };\n\n}\n\n/**\n * Merge build config includes/excludes with rule evaluation results.\n *\n * Build config provides the base include/exclude lists.\n * Rule results modify these lists based on the active config.\n *\n * @param buildInclude - Base include list from build config\n * @param buildExclude - Base exclude list from build config\n * @param ruleResult - Result from evaluateRules\n *\n * @example\n * ```typescript\n * const buildInclude = ['sql/tables', 'sql/views']\n * const buildExclude = ['sql/archive']\n * const ruleResult = evaluateRules(rules, config)\n *\n * const { include, exclude } = mergeWithBuildConfig(\n * buildInclude,\n * buildExclude,\n * ruleResult\n * )\n * ```\n */\nexport function mergeWithBuildConfig(\n buildInclude: string[],\n buildExclude: string[],\n ruleResult: RulesEvaluationResult,\n): { include: string[]; exclude: string[] } {\n\n // Start with build config\n const includeSet = new Set(buildInclude);\n const excludeSet = new Set(buildExclude);\n\n // Apply rule includes (add to include, remove from exclude)\n for (const path of ruleResult.include) {\n\n includeSet.add(path);\n excludeSet.delete(path);\n\n }\n\n // Apply rule excludes (add to exclude, remove from include)\n for (const path of ruleResult.exclude) {\n\n excludeSet.add(path);\n includeSet.delete(path);\n\n }\n\n return {\n include: Array.from(includeSet),\n exclude: Array.from(excludeSet),\n };\n\n}\n\n/**\n * Get effective build paths for a config.\n *\n * Combines build config with evaluated rules to determine\n * the final include/exclude lists for a build operation.\n *\n * @param buildInclude - Base include list from settings.build.include\n * @param buildExclude - Base exclude list from settings.build.exclude\n * @param rules - Rules from settings.rules\n * @param config - Config to evaluate rules against\n *\n * @example\n * ```typescript\n * const settings = await settingsManager.load()\n * const config = state.getActiveConfig()\n *\n * const { include, exclude } = getEffectiveBuildPaths(\n * settings.build?.include ?? [],\n * settings.build?.exclude ?? [],\n * settings.rules ?? [],\n * config\n * )\n *\n * // Use include/exclude for the build\n * ```\n */\nexport function getEffectiveBuildPaths(\n buildInclude: string[],\n buildExclude: string[],\n rules: Rule[],\n config: ConfigForRuleMatch,\n): { include: string[]; exclude: string[] } {\n\n const ruleResult = evaluateRules(rules, config);\n\n return mergeWithBuildConfig(buildInclude, buildExclude, ruleResult);\n\n}\n","/**\n * Settings Manager\n *\n * Loads, validates, and provides access to project settings from .noorm/settings.yml.\n * Settings are version controlled and shared across the team (unlike encrypted state).\n */\nimport { readFile, writeFile, mkdir, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport { attempt } from '@logosdx/utils';\n\nimport { observer } from '../observer.js';\nimport { parseSettings } from './schema.js';\nimport {\n DEFAULT_SETTINGS,\n SETTINGS_DIR_PATH,\n createDefaultSettings,\n} from './defaults.js';\nimport { evaluateRules, getEffectiveBuildPaths } from './rules.js';\n\nimport type {\n Settings,\n Stage,\n StageSecret,\n Rule,\n BuildConfig,\n PathConfig,\n StrictConfig,\n LoggingConfig,\n RulesEvaluationResult,\n ConfigForRuleMatch,\n} from './types.js';\n\n/**\n * Options for SettingsManager construction.\n */\nexport interface SettingsManagerOptions {\n /** Override settings directory (default: .noorm) */\n settingsDir?: string;\n\n /** Override settings file name (default: settings.yml) */\n settingsFile?: string;\n}\n\n/**\n * Manages project settings from .noorm/settings.yml.\n *\n * Settings are loaded once and cached. Changes are persisted immediately.\n *\n * @example\n * ```typescript\n * const manager = new SettingsManager(process.cwd())\n * await manager.load()\n *\n * const stage = manager.getStage('prod')\n * const paths = manager.getPaths()\n * ```\n */\nexport class SettingsManager {\n\n #projectRoot: string;\n #settingsDir: string;\n #settingsFile: string;\n #settings: Settings | null = null;\n #loaded = false;\n\n constructor(projectRoot: string, options: SettingsManagerOptions = {}) {\n\n this.#projectRoot = projectRoot;\n this.#settingsDir = options.settingsDir ?? SETTINGS_DIR_PATH;\n this.#settingsFile = options.settingsFile ?? 'settings.yml';\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Path Helpers\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get the full path to the settings directory.\n */\n get settingsDirPath(): string {\n\n return join(this.#projectRoot, this.#settingsDir);\n\n }\n\n /**\n * Get the full path to the settings file.\n */\n get settingsFilePath(): string {\n\n return join(this.settingsDirPath, this.#settingsFile);\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Loading / Saving\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Check if the settings file exists.\n */\n async exists(): Promise<boolean> {\n\n const [_, err] = await attempt(() => access(this.settingsFilePath));\n\n return !err;\n\n }\n\n /**\n * Load settings from disk.\n *\n * If the file doesn't exist, returns default settings without error.\n * Invalid YAML or schema violations throw errors.\n *\n * @throws SettingsValidationError if settings are invalid\n *\n * @example\n * ```typescript\n * const manager = new SettingsManager(process.cwd())\n * await manager.load()\n *\n * if (!manager.isLoaded) {\n * console.log('Using default settings')\n * }\n * ```\n */\n async load(): Promise<Settings> {\n\n const fileExists = await this.exists();\n\n if (!fileExists) {\n\n this.#settings = createDefaultSettings();\n this.#loaded = true;\n\n observer.emit('settings:loaded', {\n path: this.settingsFilePath,\n settings: this.#settings,\n fromFile: false,\n });\n\n return this.#settings;\n\n }\n\n // Read file\n const [content, readErr] = await attempt(() => readFile(this.settingsFilePath, 'utf-8'));\n\n if (readErr) {\n\n throw new Error(`Failed to read settings file: ${readErr.message}`);\n\n }\n\n // Parse YAML\n const [parsed, yamlErr] = await attempt(() => parseYaml(content));\n\n if (yamlErr) {\n\n throw new Error(`Invalid YAML in settings file: ${yamlErr.message}`);\n\n }\n\n // Handle empty file\n if (parsed === null || parsed === undefined) {\n\n this.#settings = createDefaultSettings();\n this.#loaded = true;\n\n observer.emit('settings:loaded', {\n path: this.settingsFilePath,\n settings: this.#settings,\n fromFile: true,\n });\n\n return this.#settings;\n\n }\n\n // Validate and parse with defaults\n this.#settings = parseSettings(parsed);\n this.#loaded = true;\n\n observer.emit('settings:loaded', {\n path: this.settingsFilePath,\n settings: this.#settings,\n fromFile: true,\n });\n\n return this.#settings;\n\n }\n\n /**\n * Save current settings to disk.\n *\n * Creates the settings directory if it doesn't exist.\n *\n * @example\n * ```typescript\n * await manager.load()\n * // ... modify settings ...\n * await manager.save()\n * ```\n */\n async save(): Promise<void> {\n\n this.#assertLoaded();\n\n // Ensure directory exists\n const [_, mkdirErr] = await attempt(() => mkdir(this.settingsDirPath, { recursive: true }));\n\n if (mkdirErr) {\n\n throw new Error(`Failed to create settings directory: ${mkdirErr.message}`);\n\n }\n\n // Stringify to YAML\n const yaml = stringifyYaml(this.#settings, {\n indent: 4,\n lineWidth: 120,\n });\n\n // Write file\n const [__, writeErr] = await attempt(() => writeFile(this.settingsFilePath, yaml, 'utf-8'));\n\n if (writeErr) {\n\n throw new Error(`Failed to write settings file: ${writeErr.message}`);\n\n }\n\n observer.emit('settings:saved', { path: this.settingsFilePath });\n\n }\n\n /**\n * Initialize a new settings file with defaults.\n *\n * @param force - Overwrite existing file if true\n * @throws Error if file exists and force is false\n */\n async init(force = false): Promise<void> {\n\n const fileExists = await this.exists();\n\n if (fileExists && !force) {\n\n throw new Error('Settings file already exists. Use force=true to overwrite.');\n\n }\n\n this.#settings = createDefaultSettings();\n this.#loaded = true;\n\n await this.save();\n\n observer.emit('settings:initialized', {\n path: this.settingsFilePath,\n force,\n });\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Accessors\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Whether settings have been loaded.\n */\n get isLoaded(): boolean {\n\n return this.#loaded;\n\n }\n\n /**\n * Get the raw settings object.\n *\n * @throws Error if not loaded\n */\n get settings(): Settings {\n\n this.#assertLoaded();\n\n return this.#settings!;\n\n }\n\n /**\n * Get build configuration.\n */\n getBuild(): BuildConfig {\n\n this.#assertLoaded();\n\n return this.#settings!.build ?? DEFAULT_SETTINGS.build!;\n\n }\n\n /**\n * Get path configuration.\n */\n getPaths(): PathConfig {\n\n this.#assertLoaded();\n\n return this.#settings!.paths ?? DEFAULT_SETTINGS.paths!;\n\n }\n\n /**\n * Get all rules.\n */\n getRules(): Rule[] {\n\n this.#assertLoaded();\n\n return this.#settings!.rules ?? [];\n\n }\n\n /**\n * Get all stages.\n */\n getStages(): Record<string, Stage> {\n\n this.#assertLoaded();\n\n return this.#settings!.stages ?? {};\n\n }\n\n /**\n * Get a specific stage by name.\n */\n getStage(name: string): Stage | undefined {\n\n return this.getStages()[name];\n\n }\n\n /**\n * Check if a stage exists.\n */\n hasStage(name: string): boolean {\n\n return name in this.getStages();\n\n }\n\n /**\n * Get strict mode configuration.\n */\n getStrict(): StrictConfig {\n\n this.#assertLoaded();\n\n return this.#settings!.strict ?? DEFAULT_SETTINGS.strict!;\n\n }\n\n /**\n * Get logging configuration.\n */\n getLogging(): LoggingConfig {\n\n this.#assertLoaded();\n\n return this.#settings!.logging ?? DEFAULT_SETTINGS.logging!;\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Rule Evaluation\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Evaluate rules against a config.\n *\n * @example\n * ```typescript\n * const result = manager.evaluateRules(activeConfig)\n * // { matchedRules: [...], include: [...], exclude: [...] }\n * ```\n */\n evaluateRules(config: ConfigForRuleMatch): RulesEvaluationResult {\n\n this.#assertLoaded();\n\n const rules = this.getRules();\n\n return evaluateRules(rules, config);\n\n }\n\n /**\n * Get effective build paths for a config.\n *\n * Combines build config with evaluated rules.\n *\n * @example\n * ```typescript\n * const { include, exclude } = manager.getEffectiveBuildPaths(config)\n *\n * // Build only these paths\n * for (const path of include) {\n * if (!exclude.includes(path)) {\n * await buildPath(path)\n * }\n * }\n * ```\n */\n getEffectiveBuildPaths(config: ConfigForRuleMatch): { include: string[]; exclude: string[] } {\n\n this.#assertLoaded();\n\n const build = this.getBuild();\n const rules = this.getRules();\n\n return getEffectiveBuildPaths(\n build.include ?? [],\n build.exclude ?? [],\n rules,\n config,\n );\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Stage Helpers\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Check if a stage is locked (configs cannot be deleted).\n */\n isStageLockedByName(stageName: string): boolean {\n\n const stage = this.getStage(stageName);\n\n return stage?.locked === true;\n\n }\n\n /**\n * Get required secrets for a stage.\n *\n * Merges universal secrets (from settings.secrets) with stage-specific secrets.\n * Stage-specific secrets override universal secrets with the same key.\n * Returns only secrets marked as required (default: true).\n */\n getRequiredSecrets(stageName: string): { key: string; type: string; description?: string }[] {\n\n this.#assertLoaded();\n\n // Get universal secrets\n const universalSecrets = this.#settings!.secrets ?? [];\n\n // Get stage-specific secrets\n const stage = this.getStage(stageName);\n const stageSecrets = stage?.secrets ?? [];\n\n // Merge with deduplication (stage-specific wins)\n const secretMap = new Map<string, StageSecret>();\n\n for (const secret of universalSecrets) {\n\n if (secret.required !== false) {\n\n secretMap.set(secret.key, secret);\n\n }\n\n }\n\n for (const secret of stageSecrets) {\n\n if (secret.required !== false) {\n\n secretMap.set(secret.key, secret);\n\n }\n\n }\n\n return Array.from(secretMap.values()).map((s) => ({\n key: s.key,\n type: s.type,\n description: s.description,\n }));\n\n }\n\n /**\n * Get stage defaults.\n *\n * Returns empty object if stage doesn't exist or has no defaults.\n */\n getStageDefaults(stageName: string): NonNullable<Stage['defaults']> {\n\n const stage = this.getStage(stageName);\n\n return stage?.defaults ?? {};\n\n }\n\n /**\n * Check if a stage enforces protected: true.\n *\n * When a stage has protected: true in defaults, configs\n * linked to that stage cannot override it to false.\n */\n stageEnforcesProtected(stageName: string): boolean {\n\n const defaults = this.getStageDefaults(stageName);\n\n return defaults.protected === true;\n\n }\n\n /**\n * Check if a stage enforces isTest: true.\n *\n * When a stage has isTest: true in defaults, configs\n * linked to that stage cannot override it to false.\n */\n stageEnforcesIsTest(stageName: string): boolean {\n\n const defaults = this.getStageDefaults(stageName);\n\n return defaults.isTest === true;\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Strict Mode\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Check if strict mode is enabled.\n */\n isStrictModeEnabled(): boolean {\n\n return this.getStrict().enabled === true;\n\n }\n\n /**\n * Get required stages for strict mode.\n */\n getRequiredStages(): string[] {\n\n const strict = this.getStrict();\n\n if (!strict.enabled) {\n\n return [];\n\n }\n\n return strict.stages ?? [];\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Mutations\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Set a stage definition.\n *\n * @example\n * ```typescript\n * await manager.setStage('prod', {\n * description: 'Production database',\n * locked: true,\n * defaults: { dialect: 'postgres', protected: true },\n * })\n * ```\n */\n async setStage(name: string, stage: Stage): Promise<void> {\n\n this.#assertLoaded();\n\n if (!this.#settings!.stages) {\n\n this.#settings!.stages = {};\n\n }\n\n this.#settings!.stages[name] = stage;\n\n await this.save();\n\n observer.emit('settings:stage-set', { name, stage });\n\n }\n\n /**\n * Remove a stage definition.\n */\n async removeStage(name: string): Promise<boolean> {\n\n this.#assertLoaded();\n\n if (!this.#settings!.stages || !(name in this.#settings!.stages)) {\n\n return false;\n\n }\n\n delete this.#settings!.stages[name];\n\n await this.save();\n\n observer.emit('settings:stage-removed', { name });\n\n return true;\n\n }\n\n /**\n * Add a rule.\n */\n async addRule(rule: Rule): Promise<void> {\n\n this.#assertLoaded();\n\n if (!this.#settings!.rules) {\n\n this.#settings!.rules = [];\n\n }\n\n this.#settings!.rules.push(rule);\n\n await this.save();\n\n observer.emit('settings:rule-added', { rule });\n\n }\n\n /**\n * Remove a rule by index.\n */\n async removeRule(index: number): Promise<boolean> {\n\n this.#assertLoaded();\n\n if (!this.#settings!.rules || index < 0 || index >= this.#settings!.rules.length) {\n\n return false;\n\n }\n\n const [removed] = this.#settings!.rules.splice(index, 1);\n\n await this.save();\n\n observer.emit('settings:rule-removed', { index, rule: removed! });\n\n return true;\n\n }\n\n /**\n * Update build configuration.\n */\n async setBuild(build: BuildConfig): Promise<void> {\n\n this.#assertLoaded();\n\n this.#settings!.build = build;\n\n await this.save();\n\n observer.emit('settings:build-updated', { build });\n\n }\n\n /**\n * Update path configuration.\n */\n async setPaths(paths: PathConfig): Promise<void> {\n\n this.#assertLoaded();\n\n this.#settings!.paths = paths;\n\n await this.save();\n\n observer.emit('settings:paths-updated', { paths });\n\n }\n\n /**\n * Update strict mode configuration.\n */\n async setStrict(strict: StrictConfig): Promise<void> {\n\n this.#assertLoaded();\n\n this.#settings!.strict = strict;\n\n await this.save();\n\n observer.emit('settings:strict-updated', { strict });\n\n }\n\n /**\n * Update logging configuration.\n */\n async setLogging(logging: LoggingConfig): Promise<void> {\n\n this.#assertLoaded();\n\n this.#settings!.logging = logging;\n\n await this.save();\n\n observer.emit('settings:logging-updated', { logging });\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Universal Secrets\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get universal secrets (apply to all stages).\n */\n getUniversalSecrets(): StageSecret[] {\n\n this.#assertLoaded();\n\n return this.#settings!.secrets ?? [];\n\n }\n\n /**\n * Add a universal secret definition.\n */\n async addUniversalSecret(secret: StageSecret): Promise<void> {\n\n this.#assertLoaded();\n\n if (!this.#settings!.secrets) {\n\n this.#settings!.secrets = [];\n\n }\n\n // Check for duplicate key\n const existing = this.#settings!.secrets.find((s) => s.key === secret.key);\n\n if (existing) {\n\n throw new Error(`Universal secret \"${secret.key}\" already exists`);\n\n }\n\n this.#settings!.secrets.push(secret);\n\n await this.save();\n\n observer.emit('settings:secret-added', { secret, scope: 'universal' });\n\n }\n\n /**\n * Update a universal secret definition.\n */\n async updateUniversalSecret(key: string, secret: StageSecret): Promise<void> {\n\n this.#assertLoaded();\n\n if (!this.#settings!.secrets) {\n\n throw new Error(`Universal secret \"${key}\" not found`);\n\n }\n\n const index = this.#settings!.secrets.findIndex((s) => s.key === key);\n\n if (index === -1) {\n\n throw new Error(`Universal secret \"${key}\" not found`);\n\n }\n\n this.#settings!.secrets[index] = secret;\n\n await this.save();\n\n observer.emit('settings:secret-updated', { key, secret, scope: 'universal' });\n\n }\n\n /**\n * Remove a universal secret definition.\n */\n async removeUniversalSecret(key: string): Promise<boolean> {\n\n this.#assertLoaded();\n\n if (!this.#settings!.secrets) {\n\n return false;\n\n }\n\n const index = this.#settings!.secrets.findIndex((s) => s.key === key);\n\n if (index === -1) {\n\n return false;\n\n }\n\n this.#settings!.secrets.splice(index, 1);\n\n await this.save();\n\n observer.emit('settings:secret-removed', { key, scope: 'universal' });\n\n return true;\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Stage Secrets\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Add a secret definition to a stage.\n */\n async addStageSecret(stageName: string, secret: StageSecret): Promise<void> {\n\n this.#assertLoaded();\n\n const stage = this.getStage(stageName);\n\n if (!stage) {\n\n throw new Error(`Stage \"${stageName}\" not found`);\n\n }\n\n if (!stage.secrets) {\n\n stage.secrets = [];\n\n }\n\n // Check for duplicate key\n const existing = stage.secrets.find((s) => s.key === secret.key);\n\n if (existing) {\n\n throw new Error(`Secret \"${secret.key}\" already exists in stage \"${stageName}\"`);\n\n }\n\n stage.secrets.push(secret);\n\n await this.setStage(stageName, stage);\n\n observer.emit('settings:secret-added', { secret, scope: 'stage', stageName });\n\n }\n\n /**\n * Update a secret definition in a stage.\n */\n async updateStageSecret(stageName: string, key: string, secret: StageSecret): Promise<void> {\n\n this.#assertLoaded();\n\n const stage = this.getStage(stageName);\n\n if (!stage) {\n\n throw new Error(`Stage \"${stageName}\" not found`);\n\n }\n\n if (!stage.secrets) {\n\n throw new Error(`Secret \"${key}\" not found in stage \"${stageName}\"`);\n\n }\n\n const index = stage.secrets.findIndex((s) => s.key === key);\n\n if (index === -1) {\n\n throw new Error(`Secret \"${key}\" not found in stage \"${stageName}\"`);\n\n }\n\n stage.secrets[index] = secret;\n\n await this.setStage(stageName, stage);\n\n observer.emit('settings:secret-updated', { key, secret, scope: 'stage', stageName });\n\n }\n\n /**\n * Remove a secret definition from a stage.\n */\n async removeStageSecret(stageName: string, key: string): Promise<boolean> {\n\n this.#assertLoaded();\n\n const stage = this.getStage(stageName);\n\n if (!stage || !stage.secrets) {\n\n return false;\n\n }\n\n const index = stage.secrets.findIndex((s) => s.key === key);\n\n if (index === -1) {\n\n return false;\n\n }\n\n stage.secrets.splice(index, 1);\n\n await this.setStage(stageName, stage);\n\n observer.emit('settings:secret-removed', { key, scope: 'stage', stageName });\n\n return true;\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Private Helpers\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Assert that settings have been loaded.\n */\n #assertLoaded(): void {\n\n if (!this.#loaded || !this.#settings) {\n\n throw new Error('SettingsManager not loaded. Call load() first.');\n\n }\n\n }\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Singleton / Reset Pattern\n// ─────────────────────────────────────────────────────────────\n\nlet settingsManagerInstance: SettingsManager | null = null;\n\n/**\n * Get or create a SettingsManager instance for a project.\n *\n * @example\n * ```typescript\n * const manager = getSettingsManager(process.cwd())\n * await manager.load()\n * ```\n */\nexport function getSettingsManager(\n projectRoot: string,\n options?: SettingsManagerOptions,\n): SettingsManager {\n\n if (!settingsManagerInstance) {\n\n settingsManagerInstance = new SettingsManager(projectRoot, options);\n\n }\n\n return settingsManagerInstance;\n\n}\n\n/**\n * Reset the singleton instance.\n *\n * Useful for testing to ensure clean state between tests.\n */\nexport function resetSettingsManager(): void {\n\n settingsManagerInstance = null;\n\n}\n","/**\n * Identity resolution logic.\n *\n * Resolves the current user's audit identity from multiple sources\n * with the following priority:\n * 1. Config override (for bots)\n * 2. Cryptographic identity from state\n * 3. NOORM_IDENTITY env var (for CI)\n * 4. Git user\n * 5. System user\n */\nimport { execSync } from 'child_process';\nimport { userInfo } from 'os';\nimport { attemptSync } from '@logosdx/utils';\nimport type { CryptoIdentity, Identity, IdentityOptions, IdentitySource } from './types.js';\nimport { observer } from '../observer.js';\n\n/**\n * Resolve the current user's audit identity.\n *\n * Priority chain:\n * 1. Config override (explicit bot/service identity)\n * 2. Cryptographic identity from state (normal user)\n * 3. NOORM_IDENTITY env var (CI pipelines)\n * 4. Git user (developer workstation)\n * 5. System user (fallback)\n *\n * @example\n * ```typescript\n * const identity = resolveIdentity()\n * console.log(`Executed by: ${identity.name}`)\n * ```\n *\n * @example\n * ```typescript\n * // With crypto identity from state\n * const identity = resolveIdentity({\n * cryptoIdentity: state.identity,\n * })\n * ```\n *\n * @example\n * ```typescript\n * // With config override (for bots)\n * const identity = resolveIdentity({\n * configIdentity: 'Deploy Bot <deploy@example.com>',\n * })\n * ```\n */\nexport function resolveIdentity(options: IdentityOptions = {}): Identity {\n\n let identity: Identity;\n\n // 1. Config override (explicit bot/service identity)\n if (options.configIdentity) {\n\n identity = parseIdentityString(options.configIdentity, 'config');\n\n }\n // 2. Cryptographic identity from state\n else if (options.cryptoIdentity) {\n\n identity = cryptoIdentityToAuditIdentity(options.cryptoIdentity);\n\n }\n // 3. Environment variable (CI)\n else if (process.env['NOORM_IDENTITY']) {\n\n identity = parseIdentityString(process.env['NOORM_IDENTITY'], 'env');\n\n }\n // 4. Git user\n else if (!options.skipGit) {\n\n const gitIdentity = getGitIdentity();\n identity = gitIdentity ?? getSystemIdentity();\n\n }\n // 5. System user\n else {\n\n identity = getSystemIdentity();\n\n }\n\n observer.emit('identity:resolved', {\n name: identity.name,\n email: identity.email,\n source: identity.source,\n });\n\n return identity;\n\n}\n\n/**\n * Convert cryptographic identity to audit identity.\n *\n * Extracts the name/email for tracking purposes.\n */\nfunction cryptoIdentityToAuditIdentity(crypto: CryptoIdentity): Identity {\n\n return {\n name: crypto.name,\n email: crypto.email,\n source: 'state',\n };\n\n}\n\n/**\n * Parse an identity string like \"Name <email>\" or just \"Name\".\n *\n * @example\n * ```typescript\n * parseIdentityString('John Doe <john@example.com>', 'config')\n * // { name: 'John Doe', email: 'john@example.com', source: 'config' }\n *\n * parseIdentityString('John Doe', 'env')\n * // { name: 'John Doe', source: 'env' }\n * ```\n */\nfunction parseIdentityString(input: string, source: IdentitySource): Identity {\n\n // Trim leading/trailing whitespace first\n const trimmed = input.trim();\n\n // Match \"Name <email>\" format\n const match = trimmed.match(/^(.+?)\\s*<([^>]+)>$/);\n\n if (match) {\n\n return {\n name: match[1]!.trim(),\n email: match[2]!.trim(),\n source,\n };\n\n }\n\n // Just a name\n return {\n name: trimmed,\n source,\n };\n\n}\n\n/**\n * Get identity from git config.\n *\n * Returns null if git is not available or user.name is not configured.\n */\nfunction getGitIdentity(): Identity | null {\n\n const [name, nameErr] = attemptSync(() =>\n execSync('git config user.name', {\n encoding: 'utf8',\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim(),\n );\n\n if (nameErr || !name) return null;\n\n const [email] = attemptSync(() =>\n execSync('git config user.email', {\n encoding: 'utf8',\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim(),\n );\n\n return {\n name,\n email: email || undefined,\n source: 'git',\n };\n\n}\n\n/**\n * Get identity from system user.\n */\nfunction getSystemIdentity(): Identity {\n\n const info = userInfo();\n\n return {\n name: info.username,\n source: 'system',\n };\n\n}\n\n/**\n * Format identity for display.\n *\n * @example\n * ```typescript\n * formatIdentity({ name: 'John', email: 'john@example.com', source: 'git' })\n * // 'John <john@example.com>'\n *\n * formatIdentity({ name: 'John', source: 'system' })\n * // 'John'\n * ```\n */\nexport function formatIdentity(identity: { name: string; email?: string }): string {\n\n if (identity.email) {\n\n return `${identity.name} <${identity.email}>`;\n\n }\n\n return identity.name;\n\n}\n\n/**\n * Format identity for database storage.\n *\n * Same as formatIdentity - returns \"Name <email>\" or just \"Name\".\n */\nexport function identityToString(identity: { name: string; email?: string }): string {\n\n return formatIdentity(identity);\n\n}\n","/**\n * Factory for creating cryptographic identities.\n *\n * Handles first-time identity setup including:\n * - Detecting defaults from system/git\n * - Generating keypairs\n * - Saving keys to disk\n * - Computing identity hash\n *\n * @example\n * ```typescript\n * // Detect defaults for form pre-fill\n * const defaults = await detectIdentityDefaults()\n *\n * // Create identity after user confirms/edits\n * const { identity, privateKey } = await createCryptoIdentity({\n * name: 'Alice Smith',\n * email: 'alice@example.com',\n * })\n * ```\n */\nimport { execSync } from 'child_process';\nimport { hostname, platform, release, userInfo } from 'os';\nimport { attemptSync } from '@logosdx/utils';\n\nimport type { CryptoIdentity, CryptoIdentityInput, KeyPair } from './types.js';\nimport { generateKeyPair } from './crypto.js';\nimport {\n saveKeyPair,\n saveIdentityMetadata,\n loadIdentityMetadata,\n loadPublicKey,\n} from './storage.js';\nimport { computeIdentityHash } from './hash.js';\nimport { observer } from '../observer.js';\n\n/**\n * Detected defaults for identity setup.\n */\nexport interface IdentityDefaults {\n /** Name from git or OS username */\n name: string;\n\n /** Email from git (empty if not found) */\n email: string;\n\n /** Machine hostname */\n machine: string;\n\n /** OS platform and version */\n os: string;\n}\n\n/**\n * Result of creating a crypto identity.\n */\nexport interface CreateIdentityResult {\n /** The created identity (store in state) */\n identity: CryptoIdentity;\n\n /** The keypair (privateKey should be stored securely) */\n keypair: KeyPair;\n}\n\n/**\n * Detect identity defaults from system and git.\n *\n * Used to pre-populate the identity setup form.\n * User can edit name, email, and machine; OS is auto-detected.\n *\n * @example\n * ```typescript\n * const defaults = await detectIdentityDefaults()\n * // defaults.name = 'Alice Smith' (from git)\n * // defaults.email = 'alice@example.com' (from git)\n * // defaults.machine = 'alice-macbook'\n * // defaults.os = 'darwin 24.5.0'\n * ```\n */\nexport function detectIdentityDefaults(): IdentityDefaults {\n\n // Try git config first (most reliable for name/email)\n const [gitName] = attemptSync(() =>\n execSync('git config user.name', {\n encoding: 'utf8',\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim(),\n );\n\n const [gitEmail] = attemptSync(() =>\n execSync('git config user.email', {\n encoding: 'utf8',\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim(),\n );\n\n return {\n name: gitName || userInfo().username,\n email: gitEmail || '',\n machine: hostname(),\n os: `${platform()} ${release()}`,\n };\n\n}\n\n/**\n * Create a new cryptographic identity.\n *\n * Generates keypair, computes identity hash, and saves keys to disk.\n * Returns the identity to be stored in state.\n *\n * @param input - User-provided identity details\n * @param saveKeys - Whether to save keys to ~/.noorm (default true)\n *\n * @example\n * ```typescript\n * const { identity, keypair } = await createCryptoIdentity({\n * name: 'Alice Smith',\n * email: 'alice@example.com',\n * })\n *\n * // Store identity in state\n * state.identity = identity\n * ```\n */\nexport async function createCryptoIdentity(\n input: CryptoIdentityInput,\n saveKeys: boolean = true,\n): Promise<CreateIdentityResult> {\n\n // Validate required fields\n if (!input.name?.trim()) {\n\n throw new Error('Name is required for identity');\n\n }\n\n if (!input.email?.trim()) {\n\n throw new Error('Email is required for identity');\n\n }\n\n // Get machine and OS info\n const machine = input.machine?.trim() || hostname();\n const osInfo = `${platform()} ${release()}`;\n\n // Generate keypair\n const keypair = generateKeyPair();\n\n // Compute identity hash\n const identityHash = computeIdentityHash({\n email: input.email.trim(),\n name: input.name.trim(),\n machine,\n os: osInfo,\n });\n\n // Build identity object\n const identity: CryptoIdentity = {\n identityHash,\n name: input.name.trim(),\n email: input.email.trim(),\n publicKey: keypair.publicKey,\n machine,\n os: osInfo,\n createdAt: new Date().toISOString(),\n };\n\n // Save to disk only if requested (tests pass false to avoid polluting ~/.noorm)\n if (saveKeys) {\n\n await saveKeyPair(keypair);\n await saveIdentityMetadata(identity);\n\n }\n\n // Emit event\n observer.emit('identity:created', {\n identityHash,\n name: identity.name,\n email: identity.email,\n machine: identity.machine,\n });\n\n return { identity, keypair };\n\n}\n\n/**\n * Regenerate keypair for existing identity.\n *\n * Use when private key is compromised. Updates publicKey and saves new keys.\n * Identity hash remains the same (based on user details, not keys).\n *\n * @param existingIdentity - Current identity to update\n * @param saveKeys - Whether to save keys to ~/.noorm (default true)\n *\n * @example\n * ```typescript\n * const { identity, keypair } = await regenerateKeyPair(state.identity)\n * state.identity = identity\n * ```\n */\nexport async function regenerateKeyPair(\n existingIdentity: CryptoIdentity,\n saveKeys: boolean = true,\n): Promise<CreateIdentityResult> {\n\n // Generate new keypair\n const keypair = generateKeyPair();\n\n // Update identity with new public key\n const identity: CryptoIdentity = {\n ...existingIdentity,\n publicKey: keypair.publicKey,\n };\n\n // Save keys to disk\n if (saveKeys) {\n\n await saveKeyPair(keypair);\n\n }\n\n return { identity, keypair };\n\n}\n\n/**\n * Create identity metadata for existing keys.\n *\n * Use when key files exist but metadata is missing.\n * Loads the existing public key and creates identity metadata.\n *\n * @param input - User-provided identity details\n *\n * @example\n * ```typescript\n * const identity = await createIdentityForExistingKeys({\n * name: 'Alice Smith',\n * email: 'alice@example.com',\n * })\n * if (identity) {\n * await state.setIdentity(identity)\n * }\n * ```\n */\nexport async function createIdentityForExistingKeys(\n input: CryptoIdentityInput,\n): Promise<CryptoIdentity | null> {\n\n // Validate required fields\n if (!input.name?.trim()) {\n\n throw new Error('Name is required for identity');\n\n }\n\n if (!input.email?.trim()) {\n\n throw new Error('Email is required for identity');\n\n }\n\n // Load existing public key\n const publicKey = await loadPublicKey();\n\n if (!publicKey) {\n\n return null;\n\n }\n\n // Get machine and OS info\n const machine = input.machine?.trim() || hostname();\n const osInfo = `${platform()} ${release()}`;\n\n // Compute identity hash\n const identityHash = computeIdentityHash({\n email: input.email.trim(),\n name: input.name.trim(),\n machine,\n os: osInfo,\n });\n\n // Build identity object\n const identity: CryptoIdentity = {\n identityHash,\n name: input.name.trim(),\n email: input.email.trim(),\n publicKey,\n machine,\n os: osInfo,\n createdAt: new Date().toISOString(),\n };\n\n // Save metadata\n await saveIdentityMetadata(identity);\n\n // Emit event\n observer.emit('identity:created', {\n identityHash,\n name: identity.name,\n email: identity.email,\n machine: identity.machine,\n });\n\n return identity;\n\n}\n\n/**\n * Load existing identity from disk.\n *\n * Loads both the identity metadata and public key from ~/.noorm/.\n * Used when initializing a new project with existing key files.\n *\n * @returns Identity or null if not found/incomplete\n *\n * @example\n * ```typescript\n * const identity = await loadExistingIdentity()\n * if (identity) {\n * await state.setIdentity(identity)\n * }\n * ```\n */\nexport async function loadExistingIdentity(): Promise<CryptoIdentity | null> {\n\n // Load metadata\n const metadata = await loadIdentityMetadata();\n\n if (!metadata) {\n\n return null;\n\n }\n\n // Verify public key matches (in case files got out of sync)\n const publicKey = await loadPublicKey();\n\n if (!publicKey) {\n\n return null;\n\n }\n\n // Return identity with current public key\n return {\n ...metadata,\n publicKey,\n };\n\n}\n","/**\n * Connection manager with tracking and auto-cleanup.\n *\n * Tracks ALL active database connections and ensures they're closed on shutdown.\n * Connections can be cached by config name for reuse, or tracked ephemerally.\n */\nimport { attempt } from '@logosdx/utils';\nimport type { Config } from '../config/types.js';\nimport type { ConnectionResult } from './types.js';\nimport { observer } from '../observer.js';\n\n/**\n * Internal connection entry with metadata.\n */\ninterface TrackedConnection {\n conn: ConnectionResult;\n configName: string;\n createdAt: Date;\n}\n\n/**\n * Manages all database connections.\n *\n * Two modes of operation:\n * 1. Cached: `getConnection(config)` - reuses existing connection for a config\n * 2. Tracked: `track(conn, name)` - tracks ephemeral connections for cleanup\n *\n * All tracked connections are automatically closed on `app:shutdown` event.\n *\n * @example\n * ```typescript\n * const manager = getConnectionManager()\n *\n * // Cached connection (reused)\n * const conn = await manager.getConnection(config)\n *\n * // Or track an ephemeral connection\n * const conn = await createConnection(config.connection, 'temp')\n * manager.track(conn, 'temp')\n *\n * // All connections closed on app:shutdown\n * ```\n */\nclass ConnectionManager {\n\n #cached = new Map<string, ConnectionResult>();\n #tracked = new Map<number, TrackedConnection>();\n #nextId = 1;\n #shuttingDown = false;\n #unsubscribe: (() => void) | null = null;\n\n constructor() {\n\n // Listen for shutdown event\n this.#unsubscribe = observer.on('app:shutdown', async () => {\n\n if (process.env['NOORM_DEBUG']) {\n\n console.error(\n `[ConnectionManager] app:shutdown received, closing ${this.size} connections`,\n );\n\n }\n\n this.#shuttingDown = true;\n await this.closeAll();\n\n if (process.env['NOORM_DEBUG']) {\n\n console.error('[ConnectionManager] all connections closed');\n\n }\n\n });\n\n }\n\n /**\n * Track a connection for cleanup on shutdown.\n *\n * Returns an ID that can be used to untrack the connection.\n */\n track(conn: ConnectionResult, configName: string): number {\n\n const id = this.#nextId++;\n this.#tracked.set(id, {\n conn,\n configName,\n createdAt: new Date(),\n });\n\n return id;\n\n }\n\n /**\n * Stop tracking a connection (call after manual destroy).\n */\n untrack(id: number): void {\n\n this.#tracked.delete(id);\n\n }\n\n /**\n * Get or create a cached connection for a config.\n *\n * If a connection already exists for this config name, returns it.\n * Otherwise creates a new connection and caches it.\n */\n async getConnection(\n config: Config,\n createFn: (config: Config) => Promise<ConnectionResult>,\n ): Promise<ConnectionResult> {\n\n const key = config.name;\n\n if (this.#cached.has(key)) {\n\n return this.#cached.get(key)!;\n\n }\n\n const conn = await createFn(config);\n this.#cached.set(key, conn);\n\n return conn;\n\n }\n\n /**\n * Close a specific cached connection by config name.\n */\n async closeCached(configName: string): Promise<void> {\n\n const conn = this.#cached.get(configName);\n if (conn) {\n\n const [, err] = await attempt(() => conn.destroy());\n this.#cached.delete(configName);\n\n if (err) {\n\n observer.emit('error', { source: 'connection', error: err });\n\n }\n else {\n\n observer.emit('connection:close', { configName });\n\n }\n\n }\n\n }\n\n /**\n * Close all connections (cached and tracked).\n *\n * Called automatically on app:shutdown event.\n * Uses a timeout to prevent hanging on stubborn connections.\n */\n async closeAll(): Promise<void> {\n\n const CLOSE_TIMEOUT = 5000; // 5 seconds per connection\n\n // Close all cached connections\n const cachedNames = Array.from(this.#cached.keys());\n for (const name of cachedNames) {\n\n await this.closeCached(name);\n\n }\n\n // Close all tracked connections with timeout\n const trackedEntries = Array.from(this.#tracked.entries());\n for (const [id, entry] of trackedEntries) {\n\n const destroyWithTimeout = Promise.race([\n entry.conn.destroy(),\n new Promise<void>((resolve) => setTimeout(resolve, CLOSE_TIMEOUT)),\n ]);\n\n const [, err] = await attempt(() => destroyWithTimeout);\n this.#tracked.delete(id);\n\n if (err) {\n\n observer.emit('error', { source: 'connection', error: err });\n\n }\n else {\n\n observer.emit('connection:close', { configName: entry.configName });\n\n }\n\n }\n\n }\n\n /**\n * Check if a cached connection exists for a config name.\n */\n hasCached(configName: string): boolean {\n\n return this.#cached.has(configName);\n\n }\n\n /**\n * Get total number of active connections.\n */\n get size(): number {\n\n return this.#cached.size + this.#tracked.size;\n\n }\n\n /**\n * Check if shutdown is in progress.\n */\n get isShuttingDown(): boolean {\n\n return this.#shuttingDown;\n\n }\n\n /**\n * Cleanup (for testing).\n */\n dispose(): void {\n\n if (this.#unsubscribe) {\n\n this.#unsubscribe();\n this.#unsubscribe = null;\n\n }\n\n }\n\n}\n\n// Singleton instance\nlet instance: ConnectionManager | null = null;\n\n/**\n * Get the global ConnectionManager instance.\n *\n * The manager automatically listens for app:shutdown and closes all connections.\n */\nexport function getConnectionManager(): ConnectionManager {\n\n if (!instance) {\n\n instance = new ConnectionManager();\n\n }\n\n return instance;\n\n}\n\n/**\n * Reset the global ConnectionManager (closes all connections).\n *\n * Primarily for testing.\n */\nexport async function resetConnectionManager(): Promise<void> {\n\n if (instance) {\n\n await instance.closeAll();\n instance.dispose();\n instance = null;\n\n }\n\n}\n","/**\n * Connection factory with retry logic.\n *\n * Creates database connections with automatic retry for transient failures.\n * Uses lazy imports to avoid requiring all database drivers.\n */\nimport { sql } from 'kysely';\nimport { retry, attempt } from '@logosdx/utils';\nimport type { ConnectionConfig, ConnectionResult, Dialect } from './types.js';\nimport { observer } from '../observer.js';\nimport { getConnectionManager } from './manager.js';\nimport { waitForIdentityToLoad } from '../identity/index.js';\n\ntype DialectFactory = (config: ConnectionConfig) => ConnectionResult | Promise<ConnectionResult>;\n\n/**\n * Get the dialect factory function.\n *\n * Uses dynamic import to lazy-load dialect modules.\n * This allows the connection module to be imported even when\n * specific database drivers aren't installed.\n */\nasync function getDialectFactory(dialect: Dialect): Promise<DialectFactory> {\n\n switch (dialect) {\n\n case 'sqlite':\n return (await import('./dialects/sqlite.js')).createSqliteConnection;\n\n case 'postgres':\n return (await import('./dialects/postgres.js')).createPostgresConnection;\n\n case 'mysql':\n return (await import('./dialects/mysql.js')).createMysqlConnection;\n\n case 'mssql':\n return (await import('./dialects/mssql.js')).createMssqlConnection;\n\n default:\n throw new Error(`Unsupported dialect: ${dialect}`);\n\n }\n\n}\n\n/**\n * Get the install command for a dialect's driver.\n */\nfunction getInstallCommand(dialect: Dialect): string {\n\n const commands: Record<Dialect, string> = {\n postgres: 'npm install pg',\n mysql: 'npm install mysql2',\n sqlite: 'npm install better-sqlite3',\n mssql: 'npm install tedious tarn',\n };\n\n return commands[dialect];\n\n}\n\n/**\n * Create a database connection with retry logic.\n *\n * Automatically retries on transient connection failures (ECONNREFUSED, ETIMEDOUT).\n * Does not retry authentication failures or missing drivers.\n *\n * @example\n * ```typescript\n * const conn = await createConnection({\n * dialect: 'postgres',\n * host: 'localhost',\n * database: 'myapp',\n * user: 'postgres',\n * password: 'secret',\n * })\n *\n * await sql`SELECT 1`.execute(conn.db)\n * await conn.destroy()\n * ```\n */\nexport async function createConnection(\n config: ConnectionConfig,\n configName: string = '__default__',\n): Promise<ConnectionResult> {\n\n const [conn, err] = await attempt(() =>\n retry(\n async () => {\n\n const [createFn, importErr] = await attempt(() =>\n getDialectFactory(config.dialect),\n );\n\n if (importErr) {\n\n const message = importErr.message;\n if (message.includes('Cannot find module')) {\n\n throw new Error(\n `Missing driver for ${config.dialect}. Install it with:\\n` +\n getInstallCommand(config.dialect),\n );\n\n }\n throw importErr;\n\n }\n\n const conn = await createFn!(config);\n\n // Test connection with simple query\n await sql`SELECT 1`.execute(conn.db);\n\n return conn;\n\n },\n {\n retries: 3,\n delay: 1000,\n backoff: 2, // 1s, 2s, 4s\n jitterFactor: 0.1,\n shouldRetry: (err) => {\n\n const msg = err.message.toLowerCase();\n\n // Don't retry auth failures\n if (msg.includes('authentication')) return false;\n if (msg.includes('password')) return false;\n if (msg.includes('missing driver')) return false;\n\n // Retry connection issues\n return (\n msg.includes('econnrefused') ||\n msg.includes('etimedout') ||\n msg.includes('too many connections') ||\n msg.includes('connection reset')\n );\n\n },\n },\n ),\n );\n\n if (err) {\n\n observer.emit('connection:error', { configName, error: err.message });\n throw err;\n\n }\n\n // Track connection with manager for auto-cleanup on shutdown\n const manager = getConnectionManager();\n const trackId = manager.track(conn!, configName);\n\n // Wrap destroy to also untrack from manager\n const originalDestroy = conn!.destroy;\n const wrappedDestroy = async (): Promise<void> => {\n\n manager.untrack(trackId);\n await originalDestroy();\n observer.emit('connection:close', { configName });\n\n };\n\n const trackedConn: ConnectionResult = {\n db: conn!.db,\n dialect: conn!.dialect,\n destroy: wrappedDestroy,\n };\n\n observer.emit('connection:open', { configName, dialect: config.dialect });\n\n await waitForIdentityToLoad(trackedConn.db as never);\n\n return trackedConn;\n\n}\n\n/**\n * Default system databases by dialect.\n * Used for testing server connectivity without requiring the target database to exist.\n */\nconst SYSTEM_DATABASES: Record<Dialect, string | undefined> = {\n postgres: 'postgres',\n mysql: undefined, // MySQL allows connecting without a database\n sqlite: undefined, // SQLite creates the file on connect\n mssql: 'master',\n};\n\n/**\n * Test a connection config without keeping the connection open.\n *\n * Useful for validating config before saving or for health checks.\n *\n * @param config - Connection configuration to test\n * @param options - Test options\n * @param options.testServerOnly - If true, connects to system database instead of target.\n * Useful when the target database doesn't exist yet.\n *\n * @example\n * ```typescript\n * // Test full connection (database must exist)\n * const result = await testConnection(config)\n *\n * // Test server only (database doesn't need to exist)\n * const result = await testConnection(config, { testServerOnly: true })\n *\n * if (!result.ok) {\n * console.error('Connection failed:', result.error)\n * }\n * ```\n */\nexport async function testConnection(\n config: ConnectionConfig,\n options: { testServerOnly?: boolean } = {},\n): Promise<{ ok: boolean; error?: string }> {\n\n let testConfig = config;\n\n // If testing server only, swap to system database\n if (options.testServerOnly && config.dialect !== 'sqlite') {\n\n const systemDb = SYSTEM_DATABASES[config.dialect];\n\n testConfig = {\n ...config,\n database: systemDb ?? config.database,\n };\n\n }\n\n const [conn, err] = await attempt(() => createConnection(testConfig, '__test__'));\n\n if (err) {\n\n return { ok: false, error: err.message };\n\n }\n\n await conn!.destroy();\n\n return { ok: true };\n\n}\n","/**\n * Version module types.\n *\n * Defines types for schema, state, and settings migrations.\n * Each layer has its own version number, independent of CLI package version.\n *\n * WHY: Decoupling version numbers allows us to:\n * - Keep state/settings stable while CLI evolves\n * - Only run migrations for what actually changed\n * - Gradually rollout changes across layers\n */\nimport type { Kysely } from 'kysely';\nimport type { Dialect } from '../connection/types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Version Numbers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Current version numbers for each layer.\n *\n * Increment these when adding new migrations.\n * These are independent of the package version.\n */\nexport const CURRENT_VERSIONS = Object.freeze({\n /** Database tracking tables schema version */\n schema: 1,\n\n /** State file (state.enc) schema version */\n state: 1,\n\n /** Settings file (settings.yml) schema version */\n settings: 1,\n});\n\n/**\n * Version layers tracked by the version module.\n */\nexport type VersionLayer = 'schema' | 'state' | 'settings';\n\n// ─────────────────────────────────────────────────────────────\n// Schema Migrations (Kysely)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Kysely migration for database schema changes.\n *\n * Uses Kysely's schema builder for dialect-agnostic DDL.\n * Do NOT write raw SQL - use db.schema methods.\n *\n * @example\n * ```typescript\n * export const v1: SchemaMigration = {\n * version: 1,\n * description: 'Create tracking tables',\n * async up(db, dialect) {\n * const idType = dialect === 'postgres' ? 'serial' : 'integer';\n * await db.schema\n * .createTable('__noorm_version__')\n * .addColumn('id', idType, col =>\n * dialect === 'postgres'\n * ? col.primaryKey()\n * : col.primaryKey().autoIncrement()\n * )\n * .execute()\n * },\n * async down(db, dialect) {\n * await db.schema.dropTable('__noorm_version__').execute()\n * }\n * }\n * ```\n */\nexport interface SchemaMigration {\n /** Migration version number (1, 2, 3, ...) */\n version: number;\n\n /** Human-readable description */\n description: string;\n\n /** Apply the migration */\n up(db: Kysely<unknown>, dialect: Dialect): Promise<void>;\n\n /** Rollback the migration */\n down(db: Kysely<unknown>, dialect: Dialect): Promise<void>;\n}\n\n// ─────────────────────────────────────────────────────────────\n// State Migrations (JSON)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * State migration for transforming decrypted JSON state.\n *\n * Migrations add/remove/rename fields in the state object.\n * They should be idempotent - running twice produces same result.\n *\n * @example\n * ```typescript\n * export const v2: StateMigration = {\n * version: 2,\n * description: 'Add globalSecrets field',\n * up(state) {\n * return {\n * ...state,\n * globalSecrets: state['globalSecrets'] ?? {},\n * }\n * },\n * down(state) {\n * const { globalSecrets, ...rest } = state\n * return rest\n * }\n * }\n * ```\n */\nexport interface StateMigration {\n /** Migration version number (1, 2, 3, ...) */\n version: number;\n\n /** Human-readable description */\n description: string;\n\n /** Apply the migration (transform state forward) */\n up(state: Record<string, unknown>): Record<string, unknown>;\n\n /** Rollback the migration (transform state backward) */\n down(state: Record<string, unknown>): Record<string, unknown>;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Settings Migrations (YAML)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Settings migration for transforming parsed YAML settings.\n *\n * Migrations add/remove/rename fields in the settings object.\n * They should be idempotent - running twice produces same result.\n *\n * @example\n * ```typescript\n * export const v2: SettingsMigration = {\n * version: 2,\n * description: 'Add strict mode defaults',\n * up(settings) {\n * return {\n * ...settings,\n * strict: settings['strict'] ?? {\n * enabled: false,\n * stages: [],\n * },\n * }\n * },\n * down(settings) {\n * const { strict, ...rest } = settings\n * return rest\n * }\n * }\n * ```\n */\nexport interface SettingsMigration {\n /** Migration version number (1, 2, 3, ...) */\n version: number;\n\n /** Human-readable description */\n description: string;\n\n /** Apply the migration (transform settings forward) */\n up(settings: Record<string, unknown>): Record<string, unknown>;\n\n /** Rollback the migration (transform settings backward) */\n down(settings: Record<string, unknown>): Record<string, unknown>;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Version Status\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Version status for a single layer.\n */\nexport interface LayerVersionStatus {\n /** Current version in storage */\n current: number;\n\n /** Expected version (what CLI needs) */\n expected: number;\n\n /** Whether migration is needed */\n needsMigration: boolean;\n\n /** Whether storage is newer than CLI (error case) */\n isNewer: boolean;\n}\n\n/**\n * Combined version status for all layers.\n */\nexport interface VersionStatus {\n /** Database schema version status */\n schema: LayerVersionStatus;\n\n /** State file version status */\n state: LayerVersionStatus;\n\n /** Settings file version status */\n settings: LayerVersionStatus;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Errors\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Error thrown when storage version is newer than CLI supports.\n *\n * This happens when running an older CLI against data created\n * by a newer version. Solution: upgrade the CLI.\n */\nexport class VersionMismatchError extends Error {\n\n constructor(\n public readonly layer: VersionLayer,\n public readonly current: number,\n public readonly expected: number,\n ) {\n\n super(\n `${layer} version ${current} is newer than CLI supports (${expected}). ` +\n 'Please upgrade noorm.',\n );\n this.name = 'VersionMismatchError';\n\n }\n\n}\n\n/**\n * Error thrown when a migration fails.\n */\nexport class MigrationError extends Error {\n\n constructor(\n public readonly layer: VersionLayer,\n public readonly version: number,\n public override readonly cause: Error,\n ) {\n\n super(`${layer} migration v${version} failed: ${cause.message}`);\n this.name = 'MigrationError';\n\n }\n\n}\n","/**\n * Schema Migration v1 - Initial tracking tables.\n *\n * Creates all noorm tracking tables using Kysely's schema builder.\n * Uses dialect-aware column types for auto-increment primary keys.\n *\n * For table schema documentation, see plan/datamodel.md\n */\nimport type { Kysely, CreateTableBuilder } from 'kysely';\nimport { sql } from 'kysely';\nimport type { SchemaMigration } from '../../types.js';\nimport type { Dialect } from '../../../connection/types.js';\n\n/**\n * Add an auto-incrementing ID column based on dialect.\n *\n * PostgreSQL uses 'serial' type, others use 'integer' with autoIncrement().\n */\nfunction addIdColumn<TB extends string, C extends string>(\n builder: CreateTableBuilder<TB, C>,\n dialect: Dialect,\n): CreateTableBuilder<TB, C | 'id'> {\n\n if (dialect === 'postgres') {\n\n return builder.addColumn('id', 'serial', (col) => col.primaryKey());\n\n }\n\n return builder.addColumn('id', 'integer', (col) => col.primaryKey().autoIncrement());\n\n}\n\n/**\n * Migration v1: Create initial tracking tables.\n *\n * Tables created:\n * - __noorm_version__ - Version tracking\n * - __noorm_change__ - Operation batches\n * - __noorm_executions__ - File executions\n * - __noorm_lock__ - Concurrent operation locks\n * - __noorm_identities__ - User identities for team discovery\n */\nexport const v1: SchemaMigration = {\n version: 1,\n description: 'Create initial tracking tables',\n\n async up(db: Kysely<unknown>, dialect: Dialect): Promise<void> {\n\n // __noorm_version__ - Version tracking\n await addIdColumn(db.schema.createTable('__noorm_version__'), dialect)\n .addColumn('cli_version', 'varchar(50)', (col) => col.notNull())\n .addColumn('noorm_version', 'integer', (col) => col.notNull())\n .addColumn('state_version', 'integer', (col) => col.notNull())\n .addColumn('settings_version', 'integer', (col) => col.notNull())\n .addColumn('installed_at', 'timestamp', (col) =>\n col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`),\n )\n .addColumn('upgraded_at', 'timestamp', (col) =>\n col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`),\n )\n .execute();\n\n // __noorm_change__ - Operation batches\n await addIdColumn(db.schema.createTable('__noorm_change__'), dialect)\n .addColumn('name', 'varchar(255)', (col) => col.notNull())\n .addColumn('change_type', 'varchar(50)', (col) => col.notNull())\n .addColumn('direction', 'varchar(50)', (col) => col.notNull())\n .addColumn('checksum', 'varchar(64)', (col) => col.notNull().defaultTo(''))\n .addColumn('executed_at', 'timestamp', (col) =>\n col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`),\n )\n .addColumn('executed_by', 'varchar(255)', (col) => col.notNull().defaultTo(''))\n .addColumn('config_name', 'varchar(255)', (col) => col.notNull().defaultTo(''))\n .addColumn('cli_version', 'varchar(50)', (col) => col.notNull().defaultTo(''))\n .addColumn('status', 'varchar(50)', (col) => col.notNull())\n .addColumn('error_message', 'text', (col) => col.notNull().defaultTo(''))\n .addColumn('duration_ms', 'integer', (col) => col.notNull().defaultTo(0))\n .execute();\n\n // __noorm_executions__ - File executions\n await addIdColumn(db.schema.createTable('__noorm_executions__'), dialect)\n .addColumn('change_id', 'integer', (col) =>\n col.notNull().references('__noorm_change__.id').onDelete('cascade'),\n )\n .addColumn('filepath', 'varchar(500)', (col) => col.notNull())\n .addColumn('file_type', 'varchar(10)', (col) => col.notNull())\n .addColumn('checksum', 'varchar(64)', (col) => col.notNull().defaultTo(''))\n .addColumn('cli_version', 'varchar(50)', (col) => col.notNull().defaultTo(''))\n .addColumn('status', 'varchar(50)', (col) => col.notNull())\n .addColumn('error_message', 'text', (col) => col.notNull().defaultTo(''))\n .addColumn('skip_reason', 'varchar(100)', (col) => col.notNull().defaultTo(''))\n .addColumn('duration_ms', 'integer', (col) => col.notNull().defaultTo(0))\n .execute();\n\n // __noorm_lock__ - Concurrent operation locks\n await addIdColumn(db.schema.createTable('__noorm_lock__'), dialect)\n .addColumn('config_name', 'varchar(255)', (col) => col.notNull().unique())\n .addColumn('locked_by', 'varchar(255)', (col) => col.notNull())\n .addColumn('locked_at', 'timestamp', (col) =>\n col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`),\n )\n .addColumn('expires_at', 'timestamp', (col) => col.notNull())\n .addColumn('reason', 'varchar(255)', (col) => col.notNull().defaultTo(''))\n .execute();\n\n // __noorm_identities__ - User identities for team discovery\n await addIdColumn(db.schema.createTable('__noorm_identities__'), dialect)\n .addColumn('identity_hash', 'varchar(64)', (col) => col.notNull().unique())\n .addColumn('email', 'varchar(255)', (col) => col.notNull())\n .addColumn('name', 'varchar(255)', (col) => col.notNull())\n .addColumn('machine', 'varchar(255)', (col) => col.notNull())\n .addColumn('os', 'varchar(255)', (col) => col.notNull())\n .addColumn('public_key', 'text', (col) => col.notNull())\n .addColumn('encrypted_vault_key', 'text')\n .addColumn('registered_at', 'timestamp', (col) =>\n col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`),\n )\n .addColumn('last_seen_at', 'timestamp', (col) =>\n col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`),\n )\n .execute();\n\n // Create __noorm_vault__ table for shared secrets\n await addIdColumn(db.schema.createTable('__noorm_vault__'), dialect)\n .addColumn('secret_key', 'varchar(255)', (col) => col.notNull().unique())\n .addColumn('encrypted_value', 'text', (col) => col.notNull())\n .addColumn('set_by', 'varchar(255)', (col) => col.notNull())\n .addColumn('created_at', 'timestamp', (col) =>\n col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`),\n )\n .addColumn('updated_at', 'timestamp', (col) =>\n col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`),\n )\n .execute();\n\n // Create index on executions for faster lookups by change\n await db.schema\n .createIndex('idx_executions_change_id')\n .on('__noorm_executions__')\n .column('change_id')\n .execute();\n\n // Create index on change for faster lookups by name and config\n await db.schema\n .createIndex('idx_change_name_config')\n .on('__noorm_change__')\n .columns(['name', 'config_name'])\n .execute();\n\n // Create index on secret_key for faster lookups\n await db.schema\n .createIndex('idx_vault_secret_key')\n .on('__noorm_vault__')\n .column('secret_key')\n .execute();\n\n },\n\n async down(db: Kysely<unknown>, _dialect: Dialect): Promise<void> {\n\n // Drop indexes first\n await db.schema.dropIndex('idx_change_name_config').execute();\n await db.schema.dropIndex('idx_executions_change_id').execute();\n await db.schema.dropIndex('idx_vault_secret_key').execute();\n\n // Drop tables in reverse order (child tables first due to FK constraints)\n await db.schema.dropTable('__noorm_vault__').execute();\n await db.schema.dropTable('__noorm_identities__').execute();\n await db.schema.dropTable('__noorm_lock__').execute();\n await db.schema.dropTable('__noorm_executions__').execute();\n await db.schema.dropTable('__noorm_change__').execute();\n await db.schema.dropTable('__noorm_version__').execute();\n\n },\n};\n","/**\n * Version comparison and update detection logic.\n *\n * Handles:\n * - Stable version updates (1.0.0 -> 1.1.0)\n * - Pre-release channel updates (1.0.0-alpha.1 -> 1.0.0-alpha.2)\n * - Cross-channel behavior (alpha stays on alpha until stable release)\n *\n * @example\n * ```typescript\n * const result = await checkForUpdate();\n * if (result?.updateAvailable) {\n * console.log(`Update available: ${result.latestVersion}`);\n * }\n * ```\n */\nimport { observer } from '../observer.js';\nimport { fetchPackageInfo, getLatestForChannel, getVersionsOnChannel } from './registry.js';\nimport type { UpdateCheckResult } from './types.js';\n\n// =============================================================================\n// Version Access\n// =============================================================================\n\n/**\n * Build-time injected CLI version.\n *\n * Defined in tsup.cli.config.ts via esbuild's define option.\n */\ndeclare const __CLI_VERSION__: string;\n\n/**\n * Get the current CLI version.\n *\n * Returns '0.0.0-dev' in development when __CLI_VERSION__ is not defined.\n */\nexport function getCurrentVersion(): string {\n\n return typeof __CLI_VERSION__ !== 'undefined'\n ? __CLI_VERSION__\n : '0.0.0-dev';\n\n}\n\n// =============================================================================\n// Version Parsing\n// =============================================================================\n\n/**\n * Pre-release version info.\n */\nexport interface PrereleaseInfo {\n /** Channel name (alpha, beta, rc) */\n channel: string;\n\n /** Pre-release number (e.g., 5 from alpha.5) */\n number: number;\n}\n\n/**\n * Parse pre-release info from version string.\n *\n * @param version - Semver version string\n * @returns Pre-release info or null if stable\n *\n * @example\n * ```typescript\n * parsePrerelease('1.0.0-alpha.5'); // { channel: 'alpha', number: 5 }\n * parsePrerelease('1.0.0'); // null\n * parsePrerelease('2.0.0-beta.1'); // { channel: 'beta', number: 1 }\n * ```\n */\nexport function parsePrerelease(version: string): PrereleaseInfo | null {\n\n const match = version.match(/-(\\w+)\\.?(\\d+)?$/);\n\n if (!match || !match[1]) {\n\n return null;\n\n }\n\n return {\n channel: match[1],\n number: match[2] ? parseInt(match[2], 10) : 0,\n };\n\n}\n\n// =============================================================================\n// Version Comparison\n// =============================================================================\n\n/**\n * Check if update is a major version bump.\n *\n * Major version changes may include breaking changes.\n *\n * @param current - Current version string\n * @param latest - Latest version string\n * @returns True if major version increased\n *\n * @example\n * ```typescript\n * isMajorVersionUpdate('1.5.2', '2.0.0'); // true\n * isMajorVersionUpdate('1.5.2', '1.6.0'); // false\n * isMajorVersionUpdate('1.5.2', '1.5.3'); // false\n * ```\n */\nexport function isMajorVersionUpdate(current: string, latest: string): boolean {\n\n const currentBase = current.split('-')[0] ?? '0.0.0';\n const latestBase = latest.split('-')[0] ?? '0.0.0';\n\n const currentMajor = parseInt(currentBase.split('.')[0] ?? '0', 10);\n const latestMajor = parseInt(latestBase.split('.')[0] ?? '0', 10);\n\n return latestMajor > currentMajor;\n\n}\n\n/**\n * Compare two semver versions.\n *\n * Handles pre-release versions according to semver spec:\n * - Stable is always greater than pre-release of same base\n * - Pre-releases compared by channel then number\n *\n * @param a - First version\n * @param b - Second version\n * @returns -1 if a < b, 0 if equal, 1 if a > b\n *\n * @example\n * ```typescript\n * compareVersions('1.0.0', '2.0.0'); // -1\n * compareVersions('1.0.0', '1.0.0'); // 0\n * compareVersions('2.0.0', '1.0.0'); // 1\n * compareVersions('1.0.0', '1.0.0-alpha.1'); // 1 (stable > prerelease)\n * ```\n */\nexport function compareVersions(a: string, b: string): number {\n\n // Strip prerelease suffix for base comparison\n const baseA = a.split('-')[0] ?? '0.0.0';\n const baseB = b.split('-')[0] ?? '0.0.0';\n\n const partsA = baseA.split('.').map(Number);\n const partsB = baseB.split('.').map(Number);\n\n // Compare major.minor.patch\n for (let i = 0; i < 3; i++) {\n\n const partA = partsA[i] ?? 0;\n const partB = partsB[i] ?? 0;\n\n if (partA > partB) {\n\n return 1;\n\n }\n\n if (partA < partB) {\n\n return -1;\n\n }\n\n }\n\n // Same base version, check prerelease\n const preA = parsePrerelease(a);\n const preB = parsePrerelease(b);\n\n // No prerelease = stable = higher than prerelease\n if (!preA && preB) {\n\n return 1;\n\n }\n\n if (preA && !preB) {\n\n return -1;\n\n }\n\n if (!preA && !preB) {\n\n return 0;\n\n }\n\n // Both prerelease - compare channel then number\n // Channel order: alpha < beta < rc\n const channelOrder: Record<string, number> = { alpha: 0, beta: 1, rc: 2 };\n const orderA = channelOrder[preA!.channel] ?? 99;\n const orderB = channelOrder[preB!.channel] ?? 99;\n\n if (orderA !== orderB) {\n\n return orderA > orderB ? 1 : -1;\n\n }\n\n // Same channel, compare number\n const numDiff = preA!.number - preB!.number;\n\n if (numDiff === 0) {\n\n return 0;\n\n }\n\n return numDiff > 0 ? 1 : -1;\n\n}\n\n// =============================================================================\n// Update Check\n// =============================================================================\n\n/**\n * Check for available updates.\n *\n * Logic:\n * - If current is stable, check against 'latest' tag\n * - If current is alpha/beta/rc, check against that channel's latest\n * - Pre-release can upgrade to stable if stable is newer\n * - Development version (0.0.0-dev) never triggers updates\n *\n * @returns Update check result or null if offline/error\n *\n * @example\n * ```typescript\n * const result = await checkForUpdate();\n * if (result?.updateAvailable) {\n * if (result.isMajorUpdate) {\n * // Show confirmation dialog\n * }\n * else {\n * // Auto-update if enabled\n * }\n * }\n * ```\n */\nexport async function checkForUpdate(): Promise<UpdateCheckResult | null> {\n\n const currentVersion = getCurrentVersion();\n\n // Dev version never triggers updates\n if (currentVersion === '0.0.0-dev') {\n\n return {\n currentVersion,\n latestVersion: currentVersion,\n updateAvailable: false,\n isMajorUpdate: false,\n isPrerelease: true,\n channel: 'dev',\n };\n\n }\n\n observer.emit('update:checking', {});\n\n const packageInfo = await fetchPackageInfo();\n\n if (!packageInfo) {\n\n // Offline or error - skip gracefully\n observer.emit('update:check-failed', { error: 'Network error or timeout' });\n\n return null;\n\n }\n\n const currentPrerelease = parsePrerelease(currentVersion);\n let latestVersion: string;\n\n if (currentPrerelease) {\n\n // Current is pre-release - check that channel\n const channelVersions = getVersionsOnChannel(packageInfo, currentPrerelease.channel);\n const latestOnChannel = channelVersions[channelVersions.length - 1];\n\n // Also check stable - if stable is newer than our base, use that\n const stableLatest = getLatestForChannel(packageInfo, 'latest');\n\n if (stableLatest && compareVersions(stableLatest, currentVersion) > 0) {\n\n latestVersion = stableLatest;\n\n }\n else {\n\n latestVersion = latestOnChannel ?? currentVersion;\n\n }\n\n }\n else {\n\n // Current is stable - check 'latest' tag\n latestVersion = getLatestForChannel(packageInfo, 'latest') ?? currentVersion;\n\n }\n\n const updateAvailable = compareVersions(latestVersion, currentVersion) > 0;\n const isMajorUpdate = updateAvailable && isMajorVersionUpdate(currentVersion, latestVersion);\n\n const result: UpdateCheckResult = {\n currentVersion,\n latestVersion,\n updateAvailable,\n isMajorUpdate,\n isPrerelease: !!currentPrerelease,\n channel: currentPrerelease?.channel,\n };\n\n if (updateAvailable) {\n\n if (isMajorUpdate) {\n\n observer.emit('update:major-available', {\n currentVersion,\n latestVersion,\n });\n\n }\n else {\n\n observer.emit('update:available', {\n currentVersion,\n latestVersion,\n });\n\n }\n\n }\n else {\n\n observer.emit('update:not-available', { currentVersion });\n\n }\n\n return result;\n\n}\n","/**\n * Schema Version Manager.\n *\n * Manages database tracking table versions using Kysely migrations.\n * The schema version is independent of the CLI package version.\n *\n * WHY: Using Kysely migrations instead of raw SQL means:\n * - Dialect-agnostic DDL (works with postgres, mysql, sqlite, mssql)\n * - Type-safe schema definitions\n * - No SQL injection risks\n */\nimport type { Kysely } from 'kysely';\nimport { sql } from 'kysely';\nimport { attempt } from '@logosdx/utils';\n\nimport { observer } from '../../observer.js';\nimport type { NoormDatabase } from '../../shared/tables.js';\nimport type { Dialect } from '../../connection/types.js';\n\nimport {\n CURRENT_VERSIONS,\n MigrationError,\n VersionMismatchError,\n type LayerVersionStatus,\n type SchemaMigration,\n} from '../types.js';\n\n// Import migrations\nimport { v1 } from './migrations/v1.js';\n\nimport { waitForIdentityToLoad } from '../../identity/index.js';\nimport { getCurrentVersion } from '../../update/checker.js';\n\n/**\n * All schema migrations in order.\n * Add new migrations here as they're created.\n */\nconst MIGRATIONS: SchemaMigration[] = [v1];\n\n/**\n * Check if tracking tables exist.\n *\n * @example\n * ```typescript\n * const exists = await tablesExist(db)\n * if (!exists) {\n * await bootstrap(db)\n * }\n * ```\n */\nexport async function tablesExist(db: Kysely<NoormDatabase>): Promise<boolean> {\n\n const [result, err] = await attempt(async () => {\n\n await sql`SELECT 1 FROM __noorm_version__ LIMIT 1`.execute(db);\n\n return true;\n\n });\n\n if (err) return false;\n\n return result;\n\n}\n\n/**\n * Get current schema version from database.\n * Returns 0 if tables don't exist.\n *\n * @example\n * ```typescript\n * const version = await getSchemaVersion(db)\n * // version = 3 (or 0 if not initialized)\n * ```\n */\nexport async function getSchemaVersion(db: Kysely<NoormDatabase>): Promise<number> {\n\n const exists = await tablesExist(db);\n if (!exists) return 0;\n\n const [result, err] = await attempt(async () => {\n\n return db\n .selectFrom('__noorm_version__')\n .select('noorm_version')\n .orderBy('id', 'desc')\n .limit(1)\n .executeTakeFirst();\n\n });\n\n if (err) return 0;\n\n return result?.noorm_version ?? 0;\n\n}\n\n/**\n * Check schema version status.\n *\n * @example\n * ```typescript\n * const status = await checkSchemaVersion(db)\n * if (status.needsMigration) {\n * await migrateSchema(db)\n * }\n * ```\n */\nexport async function checkSchemaVersion(db: Kysely<NoormDatabase>): Promise<LayerVersionStatus> {\n\n const current = await getSchemaVersion(db);\n const expected = CURRENT_VERSIONS.schema;\n\n observer.emit('version:schema:checking', { current });\n\n return {\n current,\n expected,\n needsMigration: current < expected,\n isNewer: current > expected,\n };\n\n}\n\n/**\n * Options for bootstrap and version record operations.\n */\nexport interface VersionRecordOptions {\n /** State schema version (defaults to CURRENT_VERSIONS.state) */\n stateVersion?: number;\n\n /** Settings schema version (defaults to CURRENT_VERSIONS.settings) */\n settingsVersion?: number;\n}\n\n/**\n * Bootstrap tracking tables from scratch.\n *\n * Runs all migrations and inserts initial version record.\n * Called when no tracking tables exist.\n */\nexport async function bootstrapSchema(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n options?: VersionRecordOptions,\n): Promise<void> {\n\n const start = performance.now();\n\n observer.emit('version:schema:migrating', {\n from: 0,\n to: CURRENT_VERSIONS.schema,\n });\n\n // Run all migrations in order\n for (const migration of MIGRATIONS) {\n\n const [, err] = await attempt(() => migration.up(db as Kysely<unknown>, dialect));\n\n if (err) {\n\n throw new MigrationError('schema', migration.version, err);\n\n }\n\n }\n\n // Insert initial version record with all versions\n await db\n .insertInto('__noorm_version__')\n .values({\n cli_version: getCurrentVersion(),\n noorm_version: CURRENT_VERSIONS.schema,\n state_version: options?.stateVersion ?? CURRENT_VERSIONS.state,\n settings_version: options?.settingsVersion ?? CURRENT_VERSIONS.settings,\n })\n .execute();\n\n const durationMs = performance.now() - start;\n\n observer.emit('version:schema:migrated', {\n from: 0,\n to: CURRENT_VERSIONS.schema,\n durationMs,\n });\n\n // Ensure identity is registered in the new schema\n await waitForIdentityToLoad(db);\n\n}\n\n/**\n * Update the version record with current versions.\n *\n * Call this after state or settings migrations to keep the database\n * record in sync with actual file versions.\n *\n * @example\n * ```typescript\n * // After migrating state and settings\n * await updateVersionRecord(db, {\n * stateVersion: CURRENT_VERSIONS.state,\n * settingsVersion: CURRENT_VERSIONS.settings,\n * })\n * ```\n */\nexport async function updateVersionRecord(\n db: Kysely<NoormDatabase>,\n options?: VersionRecordOptions,\n): Promise<void> {\n\n const now = new Date().toISOString();\n\n await db\n .insertInto('__noorm_version__')\n .values({\n cli_version: getCurrentVersion(),\n noorm_version: CURRENT_VERSIONS.schema,\n state_version: options?.stateVersion ?? CURRENT_VERSIONS.state,\n settings_version: options?.settingsVersion ?? CURRENT_VERSIONS.settings,\n upgraded_at: now as unknown as Date,\n })\n .execute();\n\n}\n\n/**\n * Get the latest version record.\n *\n * Returns the most recent version record, or null if no tables exist.\n */\nexport async function getLatestVersionRecord(\n db: Kysely<NoormDatabase>,\n): Promise<{ stateVersion: number; settingsVersion: number } | null> {\n\n const exists = await tablesExist(db);\n if (!exists) return null;\n\n const [result, err] = await attempt(async () => {\n\n return db\n .selectFrom('__noorm_version__')\n .select(['state_version', 'settings_version'])\n .orderBy('id', 'desc')\n .limit(1)\n .executeTakeFirst();\n\n });\n\n if (err || !result) return null;\n\n return {\n stateVersion: result.state_version,\n settingsVersion: result.settings_version,\n };\n\n}\n\n/**\n * Migrate schema from current version to latest.\n *\n * Only runs migrations that haven't been applied yet.\n * Carries forward existing state/settings versions.\n *\n * @throws VersionMismatchError if schema is newer than CLI supports\n * @throws MigrationError if a migration fails\n *\n * @example\n * ```typescript\n * await migrateSchema(db, 'postgres')\n * ```\n */\nexport async function migrateSchema(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n options?: VersionRecordOptions,\n): Promise<void> {\n\n const status = await checkSchemaVersion(db);\n\n // Schema is newer than CLI supports\n if (status.isNewer) {\n\n observer.emit('version:mismatch', {\n layer: 'schema',\n current: status.current,\n expected: status.expected,\n });\n\n throw new VersionMismatchError('schema', status.current, status.expected);\n\n }\n\n // No migration needed\n if (!status.needsMigration) return;\n\n // Bootstrap if no tables exist\n if (status.current === 0) {\n\n await bootstrapSchema(db, dialect, options);\n\n return;\n\n }\n\n const start = performance.now();\n\n observer.emit('version:schema:migrating', {\n from: status.current,\n to: CURRENT_VERSIONS.schema,\n });\n\n // Get existing versions to carry forward\n const existing = await getLatestVersionRecord(db);\n\n // Run pending migrations\n const pendingMigrations = MIGRATIONS.filter((m) => m.version > status.current);\n\n for (const migration of pendingMigrations) {\n\n const [, err] = await attempt(() => migration.up(db as Kysely<unknown>, dialect));\n\n if (err) {\n\n throw new MigrationError('schema', migration.version, err);\n\n }\n\n }\n\n // Update version record (carry forward existing versions or use provided)\n await db\n .insertInto('__noorm_version__')\n .values({\n cli_version: getCurrentVersion(),\n noorm_version: CURRENT_VERSIONS.schema,\n state_version:\n options?.stateVersion ?? existing?.stateVersion ?? CURRENT_VERSIONS.state,\n settings_version:\n options?.settingsVersion ?? existing?.settingsVersion ?? CURRENT_VERSIONS.settings,\n })\n .execute();\n\n const durationMs = performance.now() - start;\n\n observer.emit('version:schema:migrated', {\n from: status.current,\n to: CURRENT_VERSIONS.schema,\n durationMs,\n });\n\n await waitForIdentityToLoad(db);\n\n}\n\n/**\n * Ensure schema is at current version.\n *\n * Combines check and migrate into a single call.\n *\n * @throws VersionMismatchError if schema is newer than CLI supports\n * @throws MigrationError if a migration fails\n */\nexport async function ensureSchemaVersion(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n options?: VersionRecordOptions,\n): Promise<void> {\n\n await migrateSchema(db, dialect, options);\n\n}\n\n","/**\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, Selectable, Updateable } from 'kysely';\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 * @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 * Type for table names.\n */\nexport type NoormTableName = (typeof NOORM_TABLES)[keyof typeof NOORM_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 * Combined database interface for all noorm tracking tables.\n *\n * Use this with Kysely<NoormDatabase> for type-safe queries.\n *\n * @example\n * ```typescript\n * import { NoormDatabase, NOORM_TABLES } from './shared'\n *\n * const db = new Kysely<NoormDatabase>({ dialect })\n *\n * const version = await db\n * .selectFrom(NOORM_TABLES.version)\n * .selectAll()\n * .orderBy('id', 'desc')\n * .limit(1)\n * .executeTakeFirst()\n * ```\n */\nexport interface NoormDatabase {\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 * Environment Detection\n *\n * Utilities for detecting the runtime environment (CI, headless, etc.).\n * Used by logger and other modules that need to adapt behavior based on context.\n */\n\n/**\n * CI environment variable names to check.\n */\nconst CI_ENV_VARS = [\n 'CI',\n 'CONTINUOUS_INTEGRATION',\n 'GITHUB_ACTIONS',\n 'GITLAB_CI',\n 'CIRCLECI',\n 'TRAVIS',\n 'JENKINS_URL',\n 'BUILDKITE',\n 'TEAMCITY_VERSION',\n 'TF_BUILD',\n 'BITBUCKET_BUILD_NUMBER',\n];\n\n/**\n * Detect if running in a CI/headless environment.\n *\n * Checks for:\n * - NOORM_HEADLESS=true environment variable\n * - Common CI environment variables\n * - No TTY available\n *\n * @example\n * ```typescript\n * if (isCi()) {\n * // Log to stdout instead of file\n * console.log('Running in CI mode')\n * }\n * ```\n */\nexport function isCi(): boolean {\n\n // Explicit headless flag\n if (process.env['NOORM_HEADLESS'] === 'true') {\n\n return true;\n\n }\n\n // Check CI environment variables\n for (const envVar of CI_ENV_VARS) {\n\n if (process.env[envVar]) {\n\n return true;\n\n }\n\n }\n\n // No TTY available (piped output, non-interactive)\n if (!process.stdout.isTTY) {\n\n return true;\n\n }\n\n return false;\n\n}\n\n/**\n * Check if running in development mode.\n *\n * @returns true if NODE_ENV is 'development' or NOORM_DEV is set\n */\nexport function isDev(): boolean {\n\n return process.env['NODE_ENV'] === 'development' || process.env['NOORM_DEV'] === 'true';\n\n}\n\n/**\n * Check if debug logging is enabled.\n *\n * @returns true if NOORM_DEBUG is set\n */\nexport function isDebug(): boolean {\n\n return process.env['NOORM_DEBUG'] === 'true';\n\n}\n\n\n/**\n * Check if confirmations should be skipped.\n *\n * Returns true if NOORM_YES is set, enabling non-interactive mode.\n */\nexport function shouldSkipConfirmations(): boolean {\n\n const yes = process.env['NOORM_YES'];\n\n return yes === '1' || yes === 'true';\n\n}\n\n/**\n * Check if output should be JSON.\n *\n * Returns true if NOORM_JSON is set, enabling headless/parseable output.\n */\nexport function shouldOutputJson(): boolean {\n\n const json = process.env['NOORM_JSON'];\n\n return json === '1' || json === 'true';\n\n}\n\n/**\n * Get the active config name from environment.\n *\n * Returns the value of NOORM_CONFIG if set.\n */\nexport function getEnvConfigName(): string | undefined {\n\n return process.env['NOORM_CONFIG'];\n\n}\n","/**\n * Modern Slate Color Theme\n *\n * Centralized color scheme for terminal output, UI elements,\n * and status indicators. Uses ansis for truecolor (hex) support.\n *\n * @example\n * ```typescript\n * import { theme, status, ui } from '../core/theme.js'\n *\n * // Status messages\n * console.log(status.success('Operation complete'))\n * console.log(status.error('Connection failed'))\n *\n * // UI elements\n * console.log(ui.primary('Submit'))\n * console.log(ui.muted('(optional)'))\n * ```\n */\nimport ansis from 'ansis';\n\n// ─────────────────────────────────────────────────────────────\n// Color Palette\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Modern Slate color palette.\n * Hex values used directly with ansis truecolor support.\n */\nexport const palette = {\n\n // Brand\n primary: '#3B82F6', // Bright Blue\n\n // Status\n success: '#10B981', // Emerald Green\n warning: '#F59E0B', // Amber\n error: '#EF4444', // Red\n info: '#8B5CF6', // Purple\n debug: '#8B5CF6', // Purple (same as info)\n\n // UI Elements\n action: '#3B82F6', // Primary Action (same as primary)\n secondary: '#6B7280', // Gray-600\n muted: '#9CA3AF', // Gray-400\n destructive: '#EF4444', // Red (same as error)\n\n // Neutrals\n text: '#F3F4F6', // Gray-100 (light text on dark bg)\n textDim: '#D1D5DB', // Gray-300\n border: '#4B5563', // Gray-600\n borderLight: '#6B7280', // Gray-500\n background: '#1F2937', // Gray-800\n\n} as const;\n\n// ─────────────────────────────────────────────────────────────\n// Color Functions (Truecolor)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Theme color functions for direct use.\n * Uses ansis hex() for truecolor output.\n */\nexport const theme = {\n\n // Brand\n primary: (text: string) => ansis.hex(palette.primary)(text),\n\n // Status\n success: (text: string) => ansis.hex(palette.success)(text),\n warning: (text: string) => ansis.hex(palette.warning)(text),\n error: (text: string) => ansis.hex(palette.error)(text),\n info: (text: string) => ansis.hex(palette.info)(text),\n debug: (text: string) => ansis.hex(palette.debug)(text),\n\n // UI\n action: (text: string) => ansis.hex(palette.action)(text),\n secondary: (text: string) => ansis.hex(palette.secondary)(text),\n muted: (text: string) => ansis.hex(palette.muted)(text),\n destructive: (text: string) => ansis.hex(palette.destructive)(text),\n\n // Text\n text: (text: string) => ansis.hex(palette.text)(text),\n textDim: (text: string) => ansis.hex(palette.textDim)(text),\n\n // Borders\n border: (text: string) => ansis.hex(palette.border)(text),\n borderLight: (text: string) => ansis.hex(palette.borderLight)(text),\n\n // Utility\n bold: ansis.bold,\n dim: ansis.dim,\n italic: ansis.italic,\n underline: ansis.underline,\n inverse: ansis.inverse,\n reset: ansis.reset,\n\n} as const;\n\n// ─────────────────────────────────────────────────────────────\n// Status Message Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Icons for status messages.\n */\nexport const icons = {\n success: '✓',\n error: '✗',\n warning: '⚠',\n info: '•',\n debug: '○',\n pending: '◌',\n arrow: '→',\n bullet: '•',\n check: '✓',\n cross: '✗',\n star: '★',\n dot: '·',\n} as const;\n\n/**\n * Status message formatters with icons.\n */\nexport const status = {\n\n /**\n * Success message with checkmark.\n * @example status.success('Build complete')\n */\n success(message: string): string {\n\n return `${theme.success(icons.success)} ${theme.success(message)}`;\n\n },\n\n /**\n * Error message with X icon.\n * @example status.error('Connection failed')\n */\n error(message: string): string {\n\n return `${theme.error(icons.error)} ${theme.error(message)}`;\n\n },\n\n /**\n * Warning message with warning icon.\n * @example status.warning('Deprecated API')\n */\n warning(message: string): string {\n\n return `${theme.warning(icons.warning)} ${theme.warning(message)}`;\n\n },\n\n /**\n * Info message with bullet.\n * @example status.info('Processing 10 files')\n */\n info(message: string): string {\n\n return `${theme.info(icons.info)} ${theme.info(message)}`;\n\n },\n\n /**\n * Debug message with circle.\n * @example status.debug('Cache hit for key: user:123')\n */\n debug(message: string): string {\n\n return `${theme.debug(icons.debug)} ${theme.muted(message)}`;\n\n },\n\n /**\n * Pending/in-progress message.\n * @example status.pending('Connecting...')\n */\n pending(message: string): string {\n\n return `${theme.warning(icons.pending)} ${theme.textDim(message)}`;\n\n },\n\n} as const;\n\n// ─────────────────────────────────────────────────────────────\n// UI Element Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * UI element formatters for buttons, labels, and interactive elements.\n */\nexport const ui = {\n\n /**\n * Primary action (buttons, highlights).\n * @example ui.primary('Submit')\n */\n primary(text: string): string {\n\n return theme.primary(text);\n\n },\n\n /**\n * Secondary action.\n * @example ui.secondary('Cancel')\n */\n secondary(text: string): string {\n\n return theme.secondary(text);\n\n },\n\n /**\n * Muted/disabled text.\n * @example ui.muted('(optional)')\n */\n muted(text: string): string {\n\n return theme.muted(text);\n\n },\n\n /**\n * Destructive action (delete, danger).\n * @example ui.destructive('Delete')\n */\n destructive(text: string): string {\n\n return theme.destructive(text);\n\n },\n\n /**\n * Keyboard shortcut badge.\n * @example ui.key('Enter')\n */\n key(text: string): string {\n\n return `${theme.muted('[')}${theme.text(text)}${theme.muted(']')}`;\n\n },\n\n /**\n * Highlighted/selected item.\n * @example ui.highlight('> Selected item')\n */\n highlight(text: string): string {\n\n return theme.primary(ansis.bold(text));\n\n },\n\n /**\n * Label with value.\n * @example ui.label('Name', 'John')\n */\n label(name: string, value: string): string {\n\n return `${theme.muted(name)}: ${theme.text(value)}`;\n\n },\n\n /**\n * Header text (bold primary).\n * @example ui.header('Configuration')\n */\n header(text: string): string {\n\n return theme.primary(ansis.bold(text));\n\n },\n\n /**\n * Section divider line.\n * @example ui.divider(40)\n */\n divider(width: number = 40): string {\n\n return theme.border('─'.repeat(width));\n\n },\n\n} as const;\n\n// ─────────────────────────────────────────────────────────────\n// Modal/Box Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Box drawing characters for modals and frames.\n */\nexport const box = {\n\n // Single line\n topLeft: '┌',\n topRight: '┐',\n bottomLeft: '└',\n bottomRight: '┘',\n horizontal: '─',\n vertical: '│',\n\n // Double line\n dTopLeft: '╔',\n dTopRight: '╗',\n dBottomLeft: '╚',\n dBottomRight: '╝',\n dHorizontal: '═',\n dVertical: '║',\n\n // Rounded\n rTopLeft: '╭',\n rTopRight: '╮',\n rBottomLeft: '╰',\n rBottomRight: '╯',\n\n} as const;\n\n/**\n * Modal/frame border helpers.\n */\nexport const borders = {\n\n /**\n * Create a horizontal border line.\n * @example borders.horizontal(40)\n */\n horizontal(width: number, style: 'single' | 'double' | 'rounded' = 'single'): string {\n\n const char = style === 'double' ? box.dHorizontal : box.horizontal;\n\n return theme.border(char.repeat(width));\n\n },\n\n /**\n * Create a top border with corners.\n * @example borders.top(40, 'rounded')\n */\n top(width: number, style: 'single' | 'double' | 'rounded' = 'single'): string {\n\n const left = style === 'double' ? box.dTopLeft\n : style === 'rounded' ? box.rTopLeft\n : box.topLeft;\n const right = style === 'double' ? box.dTopRight\n : style === 'rounded' ? box.rTopRight\n : box.topRight;\n const char = style === 'double' ? box.dHorizontal : box.horizontal;\n\n return theme.border(`${left}${char.repeat(width - 2)}${right}`);\n\n },\n\n /**\n * Create a bottom border with corners.\n * @example borders.bottom(40, 'rounded')\n */\n bottom(width: number, style: 'single' | 'double' | 'rounded' = 'single'): string {\n\n const left = style === 'double' ? box.dBottomLeft\n : style === 'rounded' ? box.rBottomLeft\n : box.bottomLeft;\n const right = style === 'double' ? box.dBottomRight\n : style === 'rounded' ? box.rBottomRight\n : box.bottomRight;\n const char = style === 'double' ? box.dHorizontal : box.horizontal;\n\n return theme.border(`${left}${char.repeat(width - 2)}${right}`);\n\n },\n\n /**\n * Create a vertical border character.\n */\n vertical(style: 'single' | 'double' = 'single'): string {\n\n const char = style === 'double' ? box.dVertical : box.vertical;\n\n return theme.border(char);\n\n },\n\n /**\n * Frame content with borders (for modals).\n * @example borders.frame('Title', 40, 'rounded')\n */\n frame(title: string, width: number, style: 'single' | 'double' | 'rounded' = 'single'): {\n top: string;\n bottom: string;\n side: string;\n } {\n\n const titleLen = title.length;\n const padding = Math.max(0, width - titleLen - 4);\n const leftPad = Math.floor(padding / 2);\n const rightPad = padding - leftPad;\n\n const left = style === 'double' ? box.dTopLeft\n : style === 'rounded' ? box.rTopLeft\n : box.topLeft;\n const right = style === 'double' ? box.dTopRight\n : style === 'rounded' ? box.rTopRight\n : box.topRight;\n const char = style === 'double' ? box.dHorizontal : box.horizontal;\n\n const topLine = theme.border(left + char.repeat(leftPad + 1))\n + theme.primary(ansis.bold(title))\n + theme.border(char.repeat(rightPad + 1) + right);\n\n return {\n top: topLine,\n bottom: borders.bottom(width, style),\n side: borders.vertical(style === 'double' ? 'double' : 'single'),\n };\n\n },\n\n} as const;\n\n// ─────────────────────────────────────────────────────────────\n// Data Display Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Data value formatters for logs and displays.\n */\nexport const data = {\n\n /**\n * Format a string value.\n */\n string(value: string): string {\n\n return theme.text(value);\n\n },\n\n /**\n * Format a number value.\n */\n number(value: number): string {\n\n return theme.warning(String(value));\n\n },\n\n /**\n * Format a boolean value.\n */\n boolean(value: boolean): string {\n\n return value ? theme.success('true') : theme.error('false');\n\n },\n\n /**\n * Format null/undefined.\n */\n nil(): string {\n\n return theme.muted('null');\n\n },\n\n /**\n * Format a key-value pair.\n * @example data.pair('name', 'John')\n */\n pair(key: string, value: unknown): string {\n\n const formatted = typeof value === 'number' ? data.number(value)\n : typeof value === 'boolean' ? data.boolean(value)\n : value === null || value === undefined ? data.nil()\n : data.string(String(value));\n\n return `${theme.muted(key)}=${formatted}`;\n\n },\n\n /**\n * Format a file path.\n */\n path(filepath: string): string {\n\n return theme.info(filepath);\n\n },\n\n /**\n * Format a duration in milliseconds.\n */\n duration(ms: number): string {\n\n if (ms < 1000) {\n\n return theme.muted(`${ms}ms`);\n\n }\n\n return theme.muted(`${(ms / 1000).toFixed(2)}s`);\n\n },\n\n /**\n * Format a count/quantity.\n */\n count(n: number, singular: string, plural?: string): string {\n\n const word = n === 1 ? singular : (plural ?? `${singular}s`);\n\n return `${theme.warning(String(n))} ${theme.text(word)}`;\n\n },\n\n} as const;\n\n// ─────────────────────────────────────────────────────────────\n// Logger Integration\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Entry level colors for logger integration.\n * Maps log levels to theme colors.\n */\nexport const logLevelColors = {\n error: theme.error,\n warn: theme.warning,\n info: theme.info,\n debug: theme.debug,\n} as const;\n\n/**\n * Entry level icons for logger integration.\n */\nexport const logLevelIcons = {\n error: icons.error,\n warn: icons.warning,\n info: icons.info,\n debug: icons.debug,\n} as const;\n","/**\n * Color Formatter\n *\n * Formats log entries with ANSI colors for console output.\n * Uses the centralized theme for consistent styling with truecolor support.\n * Flattens data one level deep - nested objects are stringified.\n */\nimport ansis from 'ansis';\nimport { attemptSync } from '@logosdx/utils';\n\nimport type { EntryLevel } from './types.js';\nimport {\n theme,\n logLevelColors,\n logLevelIcons,\n data as dataFormatters,\n} from '../theme.js';\n\n/**\n * Level icons and colors from theme.\n */\nconst LEVEL_STYLE: Record<EntryLevel, { icon: string; color: (s: string) => string }> = {\n error: { icon: logLevelIcons.error, color: logLevelColors.error },\n warn: { icon: logLevelIcons.warn, color: logLevelColors.warn },\n info: { icon: logLevelIcons.info, color: logLevelColors.info },\n debug: { icon: logLevelIcons.debug, color: logLevelColors.debug },\n};\n\n/**\n * Format a value for single-line display.\n *\n * Primitives are displayed directly, objects are stringified.\n */\nfunction formatValue(value: unknown): string {\n\n if (value === null) {\n\n return dataFormatters.nil();\n\n }\n\n if (value === undefined) {\n\n return theme.muted('undefined');\n\n }\n\n if (typeof value === 'string') {\n\n return value.length > 50\n ? theme.text(`\"${value.slice(0, 47)}...\"`)\n : theme.text(value);\n\n }\n\n if (typeof value === 'number') {\n\n return dataFormatters.number(value);\n\n }\n\n if (typeof value === 'boolean') {\n\n return dataFormatters.boolean(value);\n\n }\n\n if (value instanceof Date) {\n\n return theme.muted(value.toISOString());\n\n }\n\n if (value instanceof Error) {\n\n return theme.error(value.message);\n\n }\n\n if (Array.isArray(value)) {\n\n if (value.length === 0) {\n\n return theme.muted('[]');\n\n }\n\n if (value.length <= 3 && value.every((v) => typeof v === 'string' || typeof v === 'number')) {\n\n return theme.text(`[${value.join(', ')}]`);\n\n }\n\n return theme.muted(`[${value.length} items]`);\n\n }\n\n if (typeof value === 'object') {\n\n const [str, error] = attemptSync(() => JSON.stringify(value));\n\n if (error) {\n\n return theme.muted('[object]');\n\n }\n\n return theme.text(str.length > 60 ? str.slice(0, 57) + '...' : str);\n\n }\n\n return theme.text(String(value));\n\n}\n\n/**\n * Flatten data to key=value pairs, one level deep.\n */\nfunction flattenData(data: Record<string, unknown>): string {\n\n const pairs: string[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n\n pairs.push(`${theme.muted(key)}=${formatValue(value)}`);\n\n }\n\n return pairs.join(' ');\n\n}\n\n/**\n * Format a log entry as a colored line.\n *\n * Format: `[icon] event message key=value key=value ...`\n *\n * @param level - Entry severity level\n * @param event - Observer event name\n * @param message - Human-readable message\n * @param data - Event payload (flattened one level deep)\n * @returns Colored line string (no newline)\n */\nexport function formatColorLine(\n level: EntryLevel,\n event: string,\n message: string,\n data?: Record<string, unknown>,\n): string {\n\n const style = LEVEL_STYLE[level];\n const icon = style.color(style.icon);\n const eventStr = style.color(event);\n\n let line = `${icon} ${eventStr} ${theme.text(message)}`;\n\n if (data && Object.keys(data).length > 0) {\n\n line += ` ${flattenData(data)}`;\n\n }\n\n return line;\n\n}\n\n/**\n * Status icons for common result types.\n * Uses theme colors for consistency.\n */\nexport const STATUS_ICONS = {\n success: theme.success('✓'),\n failed: theme.error('✗'),\n partial: theme.warning('⚠'),\n pending: theme.warning('○'),\n skipped: theme.muted('○'),\n reverted: theme.info('↩'),\n} as const;\n\n/**\n * Format duration for display.\n */\nexport function formatDuration(ms: number): string {\n\n return dataFormatters.duration(ms);\n\n}\n\n/**\n * Re-export ansis for direct use where needed.\n */\nexport { ansis };\n","/**\n * Smart Redaction\n *\n * Masks sensitive fields in log data with intelligent formatting.\n * Uses O(1) Set lookup with all case variations for fast matching.\n *\n * Features:\n * - Max 12 mask chars + \"...\" for overflow\n * - First 4 chars visible in verbose/debug mode\n * - All case variations (camelCase, snake_case, kebab-case, etc.)\n * - Dynamic secret registration via observer events\n *\n * @example\n * ```typescript\n * maskValue('mysecretpassword', 'Password', 'info')\n * // => '<Password ************... (16) />'\n *\n * maskValue('mysecretpassword', 'Password', 'verbose')\n * // => '<Password myse********... (16) />'\n * ```\n */\nimport { observer } from '../observer.js';\nimport type { Settings } from '../settings/types.js';\nimport type { LogLevel } from './types.js';\n\nconst MASK_MAX_LENGTH = 12;\n\n// Set of all masked field name variations (O(1) lookup)\nconst MASKED_FIELDS = new Set<string>();\n\n// ─────────────────────────────────────────────────────────────\n// Case Conversion Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Convert string to camelCase.\n */\nfunction toCamelCase(str: string): string {\n\n return str\n .replace(/[-_\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\n .replace(/^[A-Z]/, (c) => c.toLowerCase());\n\n}\n\n/**\n * Convert string to snake_case.\n */\nfunction toSnakeCase(str: string): string {\n\n return str\n .replace(/[-\\s]+/g, '_')\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .toLowerCase();\n\n}\n\n/**\n * Convert string to kebab-case.\n */\nfunction toKebabCase(str: string): string {\n\n return str\n .replace(/[_\\s]+/g, '-')\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .toLowerCase();\n\n}\n\n/**\n * Convert string to Title Case.\n */\nfunction toTitleCase(str: string): string {\n\n return str\n .replace(/[-_\\s]+/g, ' ')\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .split(' ')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n\n}\n\n/**\n * Remove all separators from string.\n */\nfunction cleanStr(str: string): string {\n\n return str.replace(/[-_\\s]/g, '');\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Field Registration\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Add case variations of field names to masked set.\n * Generates: camelCase, snake_case, kebab-case, Title Case, etc.\n *\n * @param fields - Field names to add\n */\nexport function addMaskedFields(fields: string[]): void {\n\n for (const field of fields) {\n\n // Add with noorm_ prefix variants (NOORM_* env vars)\n const variants = [field, `noorm_${field}`];\n\n for (const variant of variants) {\n\n // Original\n MASKED_FIELDS.add(variant);\n\n // Case variations\n MASKED_FIELDS.add(variant.toLowerCase());\n MASKED_FIELDS.add(variant.toUpperCase());\n MASKED_FIELDS.add(toCamelCase(variant));\n MASKED_FIELDS.add(toSnakeCase(variant));\n MASKED_FIELDS.add(toKebabCase(variant));\n MASKED_FIELDS.add(toTitleCase(variant));\n\n // Without separators\n MASKED_FIELDS.add(cleanStr(variant));\n MASKED_FIELDS.add(cleanStr(variant).toLowerCase());\n MASKED_FIELDS.add(cleanStr(variant).toUpperCase());\n\n }\n\n }\n\n}\n\n// Initialize with common sensitive fields\naddMaskedFields([\n 'password',\n 'pass',\n 'secret',\n 'token',\n 'key',\n 'credential',\n 'api_key',\n 'apikey',\n 'access_key',\n 'secret_key',\n 'db_pass',\n 'db_password',\n 'redis_pass',\n 'client_secret',\n 'private_key',\n 'encryption_key',\n 'auth_token',\n 'bearer_token',\n 'jwt_secret',\n 'session_secret',\n]);\n\n/**\n * Check if a field name should be masked.\n *\n * @param key - Field name to check\n * @returns true if field should be masked\n */\nexport function isMaskedField(key: string): boolean {\n\n return MASKED_FIELDS.has(key);\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Masking\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Mask a value with asterisks.\n *\n * Format: `<FieldName mask (length) />`\n *\n * @param value - Value to mask\n * @param prefix - Field name for label\n * @param level - Current log level (verbose shows first 4 chars)\n * @returns Masked string\n *\n * @example\n * ```typescript\n * maskValue('mysecretpassword', 'Password', 'info')\n * // => '<Password ************... (16) />'\n *\n * maskValue('mysecretpassword', 'Password', 'verbose')\n * // => '<Password myse********... (16) />'\n * ```\n */\nexport function maskValue(value: string, prefix: string, level: LogLevel): string {\n\n const valueLen = value.length;\n const maskLen = Math.min(valueLen, MASK_MAX_LENGTH);\n const reveal = Math.min(Math.ceil(valueLen / 5), 4) || 1;\n\n let masked = '*'.repeat(maskLen);\n\n // In verbose/debug mode, show first 4 chars for debugging\n if (level === 'verbose' && valueLen >= 4) {\n\n const first4 = value.slice(0, reveal);\n masked = first4 + '*'.repeat(Math.max(0, maskLen - 4));\n\n if (masked.length < maskLen) {\n\n masked += '*'.repeat(maskLen - masked.length);\n\n }\n\n }\n\n // Add overflow indicator\n if (valueLen > MASK_MAX_LENGTH) {\n\n masked += '...';\n\n }\n\n // Format: <FieldName mask (length) />\n const label = toTitleCase(prefix);\n\n return `<${label} ${masked} (${valueLen}) />`;\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Settings Integration\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Add settings-defined secrets to masked fields.\n *\n * Extracts secret field names from stage definitions.\n *\n * @param settings - Settings object with stages\n */\nexport function addSettingsSecrets(settings: Settings): void {\n\n if (!settings.stages) return;\n\n for (const stage of Object.values(settings.stages)) {\n\n if (stage.secrets && Array.isArray(stage.secrets)) {\n\n // Extract key names from StageSecret objects\n const keys = stage.secrets.map((secret) => secret.key);\n addMaskedFields(keys);\n\n }\n\n }\n\n}\n\n/**\n * Listen for secret events and dynamically add keys to masked fields.\n *\n * Call this BEFORE instantiating the logger queue to capture all secrets.\n *\n * @returns Cleanup function to stop listening\n */\nexport function listenForSecrets(): () => void {\n\n const cleanups: Array<() => void> = [];\n\n // Config-scoped secrets\n cleanups.push(\n observer.on('secret:set', ({ key }) => {\n\n addMaskedFields([key]);\n\n }),\n );\n\n // Global secrets\n cleanups.push(\n observer.on('global-secret:set', ({ key }) => {\n\n addMaskedFields([key]);\n\n }),\n );\n\n return () => cleanups.forEach((c) => c());\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Data Filtering\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Recursively filter object, masking sensitive fields.\n *\n * Uses O(1) Set lookup for fast field matching.\n * Handles nested objects, skips read-only properties and URL objects.\n *\n * @param entry - Object to filter\n * @param level - Log level (affects masking format)\n * @returns Filtered object with sensitive fields masked\n */\nexport function filterData(\n entry: Record<string, unknown>,\n level: LogLevel,\n): Record<string, unknown> {\n\n // Null/undefined check\n if (entry === null || entry === undefined) {\n\n return entry;\n\n }\n\n // Not an object\n if (typeof entry !== 'object') {\n\n return entry;\n\n }\n\n // Skip URL objects (read-only getters)\n if (entry instanceof URL) {\n\n return entry;\n\n }\n\n // Skip Date objects\n if (entry instanceof Date) {\n\n return entry;\n\n }\n\n // Handle arrays\n if (Array.isArray(entry)) {\n\n return entry.map((item) =>\n typeof item === 'object' && item !== null\n ? filterData(item as Record<string, unknown>, level)\n : item,\n ) as unknown as Record<string, unknown>;\n\n }\n\n // Clone to avoid mutating original\n const filtered = { ...entry };\n\n for (const key in filtered) {\n\n // Check if property is writable\n const descriptor = Object.getOwnPropertyDescriptor(filtered, key);\n\n if (descriptor && !descriptor.writable && !descriptor.set) {\n\n continue;\n\n }\n\n const value = filtered[key];\n\n // O(1) lookup for masked field\n if (MASKED_FIELDS.has(key) && typeof value === 'string') {\n\n filtered[key] = maskValue(value, key, level);\n\n }\n else if (typeof value === 'object' && value !== null) {\n\n // Recurse into nested objects\n filtered[key] = filterData(value as Record<string, unknown>, level);\n\n }\n\n }\n\n return filtered;\n\n}\n","/**\n * Identity sync with database.\n *\n * Registers the current user's identity in the database and syncs\n * known users from the database to local state.\n *\n * Called automatically when connecting to a database with noorm tables.\n */\nimport type { Kysely } from 'kysely';\nimport { attempt } from '@logosdx/utils';\n\nimport type { NoormDatabase } from '../shared/index.js';\nimport type { Config } from '../config/types.js';\nimport type { CryptoIdentity, KnownUser } from './types.js';\nimport { createConnection } from '../connection/factory.js';\nimport { observer } from '../observer.js';\nimport { tablesExist } from '../version/index.js';\nimport { loadExistingIdentity } from './factory.js';\nimport { getInitializedLogger } from '../logger/init.js';\n\n/**\n * Result of identity sync operation.\n */\nexport interface IdentitySyncResult {\n /** Whether the sync was successful */\n ok: boolean;\n\n /** Error message if sync failed */\n error?: string;\n\n /** Whether the identity was newly registered (vs updated) */\n registered?: boolean;\n\n /** Number of known users discovered */\n knownUsersCount?: number;\n\n /** Known users fetched from database (caller can store if needed) */\n knownUsers?: KnownUser[];\n}\n\n/**\n * Register the current user's identity in the database.\n *\n * Upserts the identity - inserts if new, updates last_seen_at if existing.\n *\n * @example\n * ```typescript\n * const identity = await loadExistingIdentity()\n * if (identity) {\n * await registerIdentity(db, identity)\n * }\n * ```\n */\nexport async function registerIdentity(\n db: Kysely<NoormDatabase>,\n identity: CryptoIdentity,\n): Promise<{ ok: boolean; registered: boolean; error?: string }> {\n\n const [existing, selectErr] = await attempt(() =>\n db\n .selectFrom('__noorm_identities__')\n .select(['id'])\n .where('identity_hash', '=', identity.identityHash)\n .executeTakeFirst(),\n );\n\n if (selectErr) {\n\n observer.emit('error', {\n source: 'identity:register:select',\n error: selectErr,\n context: {\n identityHash: identity.identityHash,\n name: identity.name,\n email: identity.email,\n },\n });\n\n return { ok: false, registered: false, error: selectErr.message };\n\n }\n\n if (existing) {\n\n // Update last_seen_at\n const [, updateErr] = await attempt(() =>\n db\n .updateTable('__noorm_identities__')\n .set({ last_seen_at: new Date() })\n .where('identity_hash', '=', identity.identityHash)\n .execute(),\n );\n\n if (updateErr) {\n\n observer.emit('error', {\n source: 'identity:register:update',\n error: updateErr,\n context: {\n identityHash: identity.identityHash,\n name: identity.name,\n email: identity.email,\n },\n });\n\n return { ok: false, registered: false, error: updateErr.message };\n\n }\n\n return { ok: true, registered: false };\n\n }\n\n // Insert new identity\n const [, insertErr] = await attempt(() =>\n db\n .insertInto('__noorm_identities__')\n .values({\n identity_hash: identity.identityHash,\n email: identity.email,\n name: identity.name,\n machine: identity.machine,\n os: identity.os,\n public_key: identity.publicKey,\n })\n .execute(),\n );\n\n if (insertErr) {\n\n observer.emit('error', {\n source: 'identity:register:insert',\n error: insertErr,\n context: {\n identityHash: identity.identityHash,\n name: identity.name,\n email: identity.email,\n },\n });\n\n return { ok: false, registered: false, error: insertErr.message };\n\n }\n\n observer.emit('identity:registered', {\n identityHash: identity.identityHash,\n name: identity.name,\n email: identity.email,\n });\n\n return { ok: true, registered: true };\n\n}\n\n/**\n * Fetch all known users from the database.\n *\n * Converts database rows to KnownUser objects for local caching.\n *\n * @example\n * ```typescript\n * const { users } = await fetchKnownUsers(db, 'my-config')\n * await stateManager.addKnownUsers(users)\n * ```\n */\nexport async function fetchKnownUsers(\n db: Kysely<NoormDatabase>,\n configName: string,\n): Promise<{ ok: boolean; users: KnownUser[]; error?: string }> {\n\n const [rows, err] = await attempt(() =>\n db\n .selectFrom('__noorm_identities__')\n .selectAll()\n .execute(),\n );\n\n if (err) {\n\n return { ok: false, users: [], error: err.message };\n\n }\n\n const users: KnownUser[] = (rows ?? []).map((row) => ({\n identityHash: row.identity_hash,\n email: row.email,\n name: row.name,\n publicKey: row.public_key,\n machine: row.machine,\n os: row.os,\n lastSeen: row.last_seen_at instanceof Date\n ? row.last_seen_at.toISOString()\n : String(row.last_seen_at),\n source: configName,\n }));\n\n return { ok: true, users };\n\n}\n\n/**\n * Sync identity with database.\n *\n * Performs two operations:\n * 1. Registers the current user's identity in the database\n * 2. Fetches all known users from the database\n *\n * Skips sync if:\n * - No identity is provided\n * - Database doesn't have noorm tracking tables\n *\n * @example\n * ```typescript\n * const conn = await createConnection(config.connection, config.name)\n * const identity = await loadExistingIdentity()\n *\n * const result = await syncIdentity(conn.db, identity, config.name)\n * if (result.ok && result.knownUsersCount) {\n * // Fetch known users from database\n * const { users } = await fetchKnownUsers(conn.db, config.name)\n * // Store in local state for caching\n * await stateManager.addKnownUsers(users)\n * }\n * ```\n */\nexport async function syncIdentity(\n db: Kysely<NoormDatabase>,\n identity: CryptoIdentity | null,\n configName: string,\n): Promise<IdentitySyncResult> {\n\n // Check if tracking tables exist\n const [hasTracking, checkErr] = await attempt(() => tablesExist(db));\n\n if (checkErr) {\n\n return { ok: false, error: checkErr.message };\n\n }\n\n if (!hasTracking) {\n\n // Database doesn't have noorm tables yet - skip sync\n return { ok: true, knownUsersCount: 0 };\n\n }\n\n // Register current identity if available\n let registered = false;\n\n if (identity) {\n\n const regResult = await registerIdentity(db, identity);\n\n if (!regResult.ok) {\n\n return { ok: false, error: regResult.error };\n\n }\n\n registered = regResult.registered;\n\n }\n\n // Fetch known users count\n const [count, countErr] = await attempt(() =>\n db\n .selectFrom('__noorm_identities__')\n .select(db.fn.count<number>('id').as('count'))\n .executeTakeFirst(),\n );\n\n if (countErr) {\n\n return { ok: false, error: countErr.message };\n\n }\n\n const knownUsersCount = Number(count?.count ?? 0);\n\n observer.emit('identity:synced', {\n configName,\n registered,\n knownUsersCount,\n });\n\n return { ok: true, registered, knownUsersCount };\n\n}\n\n/**\n * High-level identity sync with a config.\n *\n * Handles the complete flow:\n * 1. Creates a database connection\n * 2. Registers the current user's identity\n * 3. Fetches known users from the database\n * 4. Returns known users for caller to store\n * 5. Closes the connection\n *\n * Silently skips if:\n * - No identity is set up\n * - Database doesn't have noorm tables\n * - Connection fails (non-blocking)\n *\n * @example\n * ```typescript\n * // After activating a config\n * const result = await syncIdentityWithConfig(config);\n * if (result.ok && result.knownUsers?.length) {\n * await stateManager.addKnownUsers(result.knownUsers);\n * }\n * ```\n */\nexport async function syncIdentityWithConfig(\n config: Config,\n): Promise<IdentitySyncResult> {\n\n // Load identity from global ~/.noorm/identity.json\n const [identity] = await attempt(() => loadExistingIdentity());\n\n getInitializedLogger()?.info('Loaded existing identity', { identity });\n\n // Skip if no identity set up\n if (!identity) {\n\n return { ok: true, knownUsersCount: 0 };\n\n }\n\n // Try to connect\n const [conn, connErr] = await attempt(() =>\n createConnection(config.connection, config.name),\n );\n\n if (connErr) {\n\n observer.emit('error', {\n source: 'identity:sync:connection',\n error: connErr,\n context: {\n configName: config.name,\n },\n });\n\n // Connection failed - non-blocking, just skip sync\n return { ok: true, knownUsersCount: 0 };\n\n }\n\n\n const db = conn!.db as Kysely<NoormDatabase>;\n\n // Sync identity\n const syncResult = await syncIdentity(db, identity, config.name);\n\n if (!syncResult.ok) {\n\n return syncResult;\n\n }\n\n // Fetch known users if there are any\n if (syncResult.knownUsersCount && syncResult.knownUsersCount > 0) {\n\n const [res, err] = await attempt(() => fetchKnownUsers(db, config.name));\n\n if (err) {\n\n observer.emit('error', {\n source: 'identity:fetch-known-users',\n error: err,\n context: {\n configName: config.name,\n },\n });\n\n return { ok: false, error: err.message };\n\n }\n\n const { ok, users, error } = res;\n\n if (!ok) {\n\n return { ok: false, error };\n\n }\n\n return {\n ...syncResult,\n knownUsers: users,\n };\n\n }\n\n return syncResult;\n\n}\n","/**\n * Identity module.\n *\n * Two types of identity in noorm:\n * 1. Audit Identity - Simple name/email for tracking \"who executed this\"\n * 2. Cryptographic Identity - Full keypair system for config sharing\n *\n * Audit identity resolution is cached for the duration of a command.\n * Cryptographic identity is created on first run and stored in state.\n*/\nimport { attempt } from '@logosdx/utils';\nimport type { Kysely } from 'kysely';\n\nimport type { NoormDatabase } from '../shared/tables.js';\nimport { observer } from '../observer.js';\n\nimport type { CryptoIdentity, Identity, IdentityOptions } from './types.js';\nimport { resolveIdentity as resolve } from './resolver.js';\nimport { loadExistingIdentity } from './factory.js';\nimport { registerIdentity } from './sync.js';\n\n// =============================================================================\n// Re-exports\n// =============================================================================\n\n// Types\nexport * from './types.js';\n\n// Resolver utilities\nexport { formatIdentity, identityToString } from './resolver.js';\n\n// Cryptographic operations\nexport {\n generateKeyPair,\n encryptForRecipient,\n decryptWithPrivateKey,\n deriveStateKey,\n encryptState,\n decryptState,\n} from './crypto.js';\n\n// Key storage\nexport {\n saveKeyPair,\n loadPrivateKey,\n loadPublicKey,\n loadKeyPair,\n hasKeyFiles,\n validateKeyPermissions,\n isValidKeyHex,\n getPrivateKeyPath,\n getPublicKeyPath,\n getNoormHomePath,\n saveIdentityMetadata,\n loadIdentityMetadata,\n} from './storage.js';\n\n// Hash utilities\nexport { computeIdentityHash, isValidIdentityHash, truncateHash } from './hash.js';\n\n// Factory\nexport {\n detectIdentityDefaults,\n createCryptoIdentity,\n createIdentityForExistingKeys,\n regenerateKeyPair,\n loadExistingIdentity,\n} from './factory.js';\n\nexport type { IdentityDefaults, CreateIdentityResult } from './factory.js';\nexport type { IdentityHashInput } from './hash.js';\n\n// Sync (database identity registration and discovery)\nexport {\n registerIdentity,\n fetchKnownUsers,\n syncIdentity,\n syncIdentityWithConfig,\n} from './sync.js';\n\nexport type { IdentitySyncResult } from './sync.js';\n\n\n// =============================================================================\n// Audit Identity Resolution (cached)\n// =============================================================================\n\nlet cachedIdentity: Identity | null = null;\n\n/**\n * Get the current audit identity (cached).\n *\n * Results are cached unless a config or crypto override is provided,\n * since overrides may vary between calls.\n *\n * @example\n * ```typescript\n * const identity = resolveIdentity()\n * console.log(`Executed by: ${formatIdentity(identity)}`)\n * ```\n *\n * @example\n * ```typescript\n * // With crypto identity from state\n * const identity = resolveIdentity({\n * cryptoIdentity: state.identity,\n * })\n * ```\n */\nexport function resolveIdentity(options: IdentityOptions = {}): Identity {\n\n // Don't cache if using overrides (might change between calls)\n if (options.configIdentity || options.cryptoIdentity) {\n\n return resolve(options);\n\n }\n\n if (!cachedIdentity) {\n\n cachedIdentity = resolve(options);\n\n }\n\n return cachedIdentity;\n\n}\n\n/**\n * Clear the identity cache.\n *\n * Useful for testing or when environment changes.\n */\nexport function clearIdentityCache(): void {\n\n cachedIdentity = null;\n\n}\n\n/**\n * Get audit identity with config awareness.\n *\n * Convenience function that extracts the identity override from a config.\n *\n * @example\n * ```typescript\n * const config = await resolveConfig(state)\n * const identity = getIdentityForConfig(config)\n * ```\n */\nexport function getIdentityForConfig(config: { identity?: string }): Identity {\n\n return resolveIdentity({ configIdentity: config.identity });\n\n}\n\n/**\n * Get audit identity with crypto identity awareness.\n *\n * Convenience function that uses crypto identity if available,\n * falling back to other sources.\n *\n * @example\n * ```typescript\n * const identity = getIdentityWithCrypto(state.identity, config)\n * ```\n */\nexport function getIdentityWithCrypto(\n cryptoIdentity: CryptoIdentity | null,\n config?: { identity?: string },\n): Identity {\n\n return resolveIdentity({\n configIdentity: config?.identity,\n cryptoIdentity,\n });\n\n}\n\nexport async function waitForIdentityToLoad(db: Kysely<NoormDatabase>) {\n\n // Load identity from ~/.noorm/\n const identity = await loadExistingIdentity();\n\n if (!identity) observer.emit('identity:not-found');\n if (!identity) return;\n\n const [, err] = await attempt(() => registerIdentity(db, identity));\n\n if (err) observer.emit('error', {\n error: err,\n source: 'identity:ensure',\n context: { identity },\n });\n\n}\n","/**\n * Configuration Zod schemas and validation.\n *\n * Uses Zod for declarative validation with better error messages\n * and type inference.\n */\nimport { z } from 'zod';\n\n/**\n * Valid database dialects.\n */\nexport const DialectSchema = z.enum(['postgres', 'mysql', 'sqlite', 'mssql']);\n\n/**\n * Config name pattern - alphanumeric with hyphens and underscores.\n */\nconst ConfigNameSchema = z\n .string()\n .min(1, 'Config name is required')\n .regex(\n /^[a-z0-9_-]+$/i,\n 'Config name must contain only letters, numbers, hyphens, and underscores',\n );\n\n/**\n * Port number validation.\n */\nconst PortSchema = z\n .number()\n .int()\n .min(1, 'Port must be at least 1')\n .max(65535, 'Port must be at most 65535');\n\n/**\n * Connection pool configuration.\n */\nconst PoolSchema = z.object({\n min: z.number().int().min(0).optional(),\n max: z.number().int().min(1).optional(),\n});\n\n/**\n * SSL configuration - can be boolean or detailed config.\n */\nconst SSLSchema = z.union([\n z.boolean(),\n z.object({\n rejectUnauthorized: z.boolean().optional(),\n ca: z.string().optional(),\n cert: z.string().optional(),\n key: z.string().optional(),\n }),\n]);\n\n/**\n * Connection configuration schema.\n *\n * SQLite only requires dialect + database (or filename).\n * Other dialects require host.\n */\nexport const ConnectionSchema = z\n .object({\n dialect: DialectSchema,\n host: z.string().optional(),\n port: PortSchema.optional(),\n database: z.string().min(1, 'Database name is required'),\n filename: z.string().optional(),\n user: z.string().optional(),\n password: z.string().optional(),\n ssl: SSLSchema.optional(),\n pool: PoolSchema.optional(),\n })\n .refine((conn) => conn.dialect === 'sqlite' || conn.host, {\n message: 'Host is required for non-SQLite databases',\n path: ['host'],\n });\n\n/**\n * Paths configuration schema.\n */\nconst PathsSchema = z.object({\n sql: z.string().min(1, 'SQL path is required'),\n changes: z.string().min(1, 'Changes path is required'),\n});\n\n/**\n * Full config schema.\n */\nexport const ConfigSchema = z.object({\n name: ConfigNameSchema,\n type: z.enum(['local', 'remote']).default('local'),\n isTest: z.boolean().default(false),\n protected: z.boolean().default(false),\n connection: ConnectionSchema,\n paths: PathsSchema,\n identity: z.string().optional(),\n});\n\n/**\n * Partial connection schema (all fields optional).\n */\nconst PartialConnectionSchema = z.object({\n dialect: DialectSchema.optional(),\n host: z.string().optional(),\n port: PortSchema.optional(),\n database: z.string().optional(),\n filename: z.string().optional(),\n user: z.string().optional(),\n password: z.string().optional(),\n ssl: SSLSchema.optional(),\n pool: PoolSchema.optional(),\n});\n\n/**\n * Partial paths schema.\n */\nconst PartialPathsSchema = z.object({\n sql: z.string().optional(),\n changes: z.string().optional(),\n});\n\n/**\n * Partial config schema for updates.\n *\n * All fields are optional for partial updates.\n */\nexport const ConfigInputSchema = z.object({\n name: z\n .string()\n .regex(/^[a-z0-9_-]+$/i)\n .optional(),\n type: z.enum(['local', 'remote']).optional(),\n isTest: z.boolean().optional(),\n protected: z.boolean().optional(),\n connection: PartialConnectionSchema.optional(),\n paths: PartialPathsSchema.optional(),\n identity: z.string().optional(),\n});\n\n/**\n * Schema for env-only config (CI mode).\n *\n * Allows missing name (will be generated as '__env__').\n */\nexport const EnvConfigSchema = ConfigSchema.extend({\n name: ConfigNameSchema.optional(),\n});\n\n// ─────────────────────────────────────────────────────────────\n// Type Exports\n// ─────────────────────────────────────────────────────────────\n\nexport type ConfigSchemaType = z.infer<typeof ConfigSchema>;\nexport type ConfigInputSchemaType = z.infer<typeof ConfigInputSchema>;\nexport type ConnectionSchemaType = z.infer<typeof ConnectionSchema>;\n\n// ─────────────────────────────────────────────────────────────\n// Validation Functions\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Error thrown when config validation fails.\n *\n * Includes the specific field that failed and all validation issues.\n */\nexport class ConfigValidationError extends Error {\n\n constructor(\n message: string,\n public readonly field: string,\n public readonly issues: z.ZodIssue[],\n ) {\n\n super(message);\n this.name = 'ConfigValidationError';\n\n }\n\n}\n\n/**\n * Validate a complete config object.\n *\n * @throws ConfigValidationError if validation fails\n *\n * @example\n * ```typescript\n * const [_, err] = attemptSync(() => validateConfig(config))\n * if (err) {\n * console.error(`Invalid config: ${err.message}`)\n * }\n * ```\n */\nexport function validateConfig(config: unknown): asserts config is ConfigSchemaType {\n\n const result = ConfigSchema.safeParse(config);\n\n if (!result.success) {\n\n const firstIssue = result.error.issues[0];\n\n throw new ConfigValidationError(\n firstIssue?.message ?? 'Validation failed',\n firstIssue?.path.join('.') || 'unknown',\n result.error.issues,\n );\n\n }\n\n}\n\n/**\n * Validate a partial config for updates.\n *\n * @throws ConfigValidationError if validation fails\n *\n * @example\n * ```typescript\n * // Valid partial - only updating host\n * validateConfigInput({ connection: { host: 'new-host.local' } })\n *\n * // Invalid partial - bad port\n * validateConfigInput({ connection: { port: 99999 } })\n * ```\n */\nexport function validateConfigInput(input: unknown): asserts input is ConfigInputSchemaType {\n\n const result = ConfigInputSchema.safeParse(input);\n\n if (!result.success) {\n\n const firstIssue = result.error.issues[0];\n\n throw new ConfigValidationError(\n firstIssue?.message ?? 'Validation failed',\n firstIssue?.path.join('.') || 'unknown',\n result.error.issues,\n );\n\n }\n\n}\n\n/**\n * Parse and validate config, returning defaults for missing fields.\n *\n * Unlike validateConfig which only validates, this returns the\n * parsed config with defaults applied.\n *\n * @example\n * ```typescript\n * const minimal = {\n * name: 'dev',\n * connection: { dialect: 'sqlite', database: ':memory:' },\n * paths: { sql: './sql', changes: './changes' },\n * }\n *\n * const config = parseConfig(minimal)\n * // config.type === 'local' (default)\n * // config.isTest === false (default)\n * // config.protected === false (default)\n * ```\n */\nexport function parseConfig(config: unknown): ConfigSchemaType {\n\n const result = ConfigSchema.safeParse(config);\n\n if (!result.success) {\n\n const firstIssue = result.error.issues[0];\n\n throw new ConfigValidationError(\n firstIssue?.message ?? 'Validation failed',\n firstIssue?.path.join('.') || 'unknown',\n result.error.issues,\n );\n\n }\n\n return result.data;\n\n}\n","import { makeNestedConfig } from '@logosdx/utils';\nimport type { ConfigInput } from './types.js';\nimport { DialectSchema } from './schema.js';\n\n\n/**\n * Meta env vars that control CLI behavior, not config values.\n * These are excluded from makeNestedConfig processing.\n */\nconst META_ENV_VARS = new Set([\n 'NOORM_CONFIG', // Config selection\n 'NOORM_YES', // Skip confirmations\n 'NOORM_JSON', // JSON output mode\n]);\n\nconst VALID_DIALECTS = ['postgres', 'mysql', 'sqlite', 'mssql'] as const;\n\nexport const { allConfigs, getConfig } = makeNestedConfig<ConfigInput>(process.env as Record<string, string>, {\n filter: (key) => key.startsWith('NOORM_') && !META_ENV_VARS.has(key),\n stripPrefix: 'NOORM_',\n forceAllCapToLower: true,\n memoizeOpts: false,\n skipConversion: (key) => key.toLowerCase().includes('password'),\n});\n\n/**\n * Read config values from environment variables.\n *\n * Uses makeNestedConfig to automatically transform NOORM_* env vars\n * into a nested ConfigInput object. The underscore separator maps\n * directly to object nesting.\n *\n * @example\n * ```typescript\n * // With these env vars set:\n * // NOORM_CONNECTION_DIALECT=postgres\n * // NOORM_CONNECTION_HOST=db.example.com\n * // NOORM_CONNECTION_PORT=5432\n * // NOORM_PATHS_SQL=./sql\n *\n * const envConfig = getEnvConfig()\n * // {\n * // connection: { dialect: 'postgres', host: 'db.example.com', port: 5432 },\n * // paths: { sql: './sql' }\n * // }\n * ```\n */\nexport function getEnvConfig(): ConfigInput {\n\n const config = allConfigs();\n\n // Validate dialect if provided\n if (config.connection?.dialect) {\n\n const result = DialectSchema.safeParse(config.connection.dialect);\n if (!result.success) {\n\n throw new Error(\n `Invalid NOORM_CONNECTION_DIALECT: must be one of ${VALID_DIALECTS.join(', ')}`,\n );\n\n }\n\n }\n\n return config;\n\n}\n\n\n/**\n * Config module - configuration management for noorm.\n *\n * Handles config loading, validation, merging from multiple sources,\n * and protected config handling.\n */\n\n// Types\nexport * from './types.js';\n\n// Schema & Validation\nexport {\n ConfigSchema,\n ConfigInputSchema,\n ConnectionSchema,\n DialectSchema,\n EnvConfigSchema,\n ConfigValidationError,\n validateConfig,\n validateConfigInput,\n parseConfig,\n type ConfigSchemaType,\n type ConfigInputSchemaType,\n type ConnectionSchemaType,\n} from './schema.js';\n\n// Resolver\nexport {\n resolveConfig,\n checkConfigCompleteness,\n canDeleteConfig,\n type ResolveOptions,\n type StateProvider,\n type SettingsProvider,\n type CompletenessCheckOptions,\n} from './resolver.js';\n\n// Protection\nexport {\n checkProtection,\n validateConfirmation,\n type ProtectedAction,\n type ProtectionCheck,\n} from './protection.js';\n\n","/**\n * Config resolver - merges configuration from multiple sources.\n *\n * Priority order (highest to lowest):\n * 1. CLI flags\n * 2. Environment variables\n * 3. Stored config\n * 4. Stage defaults (from settings.yml)\n * 5. Defaults\n */\nimport { merge, clone } from '@logosdx/utils';\n\nimport type { Config, ConfigInput, CompletenessCheck } from './types.js';\nimport { getEnvConfigName } from '../environment.js';\nimport { parseConfig } from './schema.js';\nimport { getEnvConfig } from './index.js';\nimport type { SettingsManager, StageDefaults } from '../settings/index.js';\n\n/**\n * Interface for state manager dependency.\n *\n * Using an interface instead of the class to avoid circular dependencies.\n */\nexport interface StateProvider {\n getConfig(name: string): Config | null;\n getActiveConfigName(): string | null;\n listSecrets(configName: string): string[];\n}\n\n/**\n * Interface for settings provider dependency.\n *\n * Settings provide stage definitions and build rules.\n * Optional - config resolution works without settings.\n */\nexport class SettingsProvider {\n\n #manager: SettingsManager;\n\n constructor(manager: SettingsManager) {\n\n this.#manager = manager;\n\n }\n\n /** Get a stage by name */\n getStage(name: string) {\n\n return this.#manager.getStage(name) ?? null;\n\n }\n\n /** Get stage that matches a config name (for auto-linking) */\n findStageForConfig(configName: string) {\n\n // Auto-link: if a stage exists with same name as config, use it\n return this.#manager.getStage(configName) ?? null;\n\n }\n\n}\n\n/**\n * Default config values.\n */\nconst DEFAULTS: ConfigInput = {\n type: 'local',\n isTest: false,\n protected: false,\n paths: {\n sql: './sql',\n changes: './changes',\n },\n connection: {\n host: 'localhost',\n pool: { min: 0, max: 10 },\n },\n log: {\n level: 'info',\n },\n};\n\n/**\n * Options for resolving a config.\n */\nexport interface ResolveOptions {\n /** Config name to load (overrides env var and active config) */\n name?: string;\n\n /** CLI flag overrides */\n flags?: ConfigInput;\n\n /** Stage name to use for defaults (from --stage flag) */\n stage?: string;\n\n /** Settings provider for stage lookup */\n settings?: SettingsProvider;\n}\n\n/**\n * Resolve the active config from all sources.\n *\n * Merges config from (lowest to highest priority):\n * 1. Defaults\n * 2. Stage defaults (from settings.yml, if stage provided or config name matches)\n * 3. Stored config (if name provided or active config exists)\n * 4. Environment variables (NOORM_*)\n * 5. CLI flags\n *\n * @example\n * ```typescript\n * const state = await getStateManager()\n * const config = resolveConfig(state)\n *\n * if (!config) {\n * console.error('No config found. Run: noorm config add')\n * process.exit(1)\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With CLI flag overrides\n * const config = resolveConfig(state, {\n * name: 'production',\n * flags: { connection: { host: 'db.example.com' } }\n * })\n * ```\n *\n * @example\n * ```typescript\n * // With stage defaults from settings\n * const config = resolveConfig(state, {\n * name: 'prod',\n * stage: 'prod',\n * settings: settingsManager,\n * })\n * ```\n */\nexport function resolveConfig(state: StateProvider, options: ResolveOptions = {}): Config | null {\n\n // 1. Determine which config to use\n const configName = options.name ?? getEnvConfigName() ?? state.getActiveConfigName();\n\n if (!configName) {\n\n // Check if we have enough env vars to run without a stored config\n const envConfig = getEnvConfig();\n if (envConfig.connection?.dialect && envConfig.connection?.database) {\n\n return resolveFromEnvOnly(envConfig, options.flags, options.stage, options.settings);\n\n }\n\n return null;\n\n }\n\n // 2. Load stored config\n const stored = state.getConfig(configName);\n if (!stored) {\n\n throw new Error(`Config \"${configName}\" not found`);\n\n }\n\n // 3. Get stage defaults (if settings available)\n const stageDefaults = getStageDefaults(configName, options.stage, options.settings);\n\n // 4. Merge: defaults <- stage <- stored <- env <- flags\n // Clone DEFAULTS to avoid mutation\n const envConfig = getEnvConfig();\n let merged = clone(DEFAULTS);\n\n if (stageDefaults) {\n\n merged = merge(merged, stageDefaults);\n\n }\n\n merged = merge(merged, stored);\n merged = merge(merged, envConfig) as ConfigInput;\n merged = merge(merged, options.flags ?? {});\n\n // 5. Validate and return with defaults applied\n return parseConfig(merged);\n\n}\n\n/**\n * Get stage defaults for a config.\n *\n * Looks up stage by:\n * 1. Explicit stage name (from --stage flag)\n * 2. Config name matching a stage name\n */\nfunction getStageDefaults(\n configName: string,\n stageName: string | undefined,\n settings: SettingsProvider | undefined,\n): StageDefaults | null {\n\n if (!settings) return null;\n if (stageName) return settings.getStage(stageName)?.defaults ?? null;\n\n return settings.findStageForConfig(configName)?.defaults ?? null;\n\n}\n\n/**\n * Build a config purely from environment variables (CI mode).\n *\n * Useful when no stored config exists but env vars provide all needed values.\n */\nfunction resolveFromEnvOnly(\n envConfig: ConfigInput,\n flags?: ConfigInput,\n stageName?: string,\n settings?: SettingsProvider,\n): Config {\n\n // Generate a name if not provided\n const name = envConfig.name ?? flags?.name ?? '__env__';\n\n // Get stage defaults if available\n const stageDefaults = getStageDefaults(name, stageName, settings);\n\n // Merge: defaults <- stage <- env <- flags\n let merged = clone(DEFAULTS);\n\n if (stageDefaults) {\n\n merged = merge(merged, stageDefaults);\n\n }\n\n merged = merge(merged, envConfig);\n merged = merge(merged, flags ?? {});\n\n // Ensure name is set\n if (!merged.name) {\n\n merged.name = '__env__';\n\n }\n\n return parseConfig(merged);\n\n}\n\n/**\n * Options for config completeness check.\n */\nexport interface CompletenessCheckOptions {\n /** Stage name to check against (defaults to finding stage for config) */\n stageName?: string;\n\n /** Vault secret keys that are available (count as \"set\") */\n vaultSecretKeys?: string[];\n}\n\n/**\n * Check if a config is complete and usable.\n *\n * A config is complete when all required secrets (from its stage) are set.\n * Secrets can come from local state OR the vault.\n * Also checks for stage constraint violations.\n *\n * @example\n * ```typescript\n * const check = checkConfigCompleteness(config, state, settings, {\n * vaultSecretKeys: ['API_KEY', 'DB_PASSWORD'],\n * })\n * if (!check.complete) {\n * console.log('Missing secrets:', check.missingSecrets)\n * console.log('Violations:', check.violations)\n * }\n * ```\n */\nexport function checkConfigCompleteness(\n config: Config,\n state: StateProvider,\n settings?: SettingsProvider,\n options?: CompletenessCheckOptions,\n): CompletenessCheck {\n\n const { stageName, vaultSecretKeys = [] } = options ?? {};\n\n const result: CompletenessCheck = {\n complete: true,\n missingSecrets: [],\n violations: [],\n };\n\n // Get stage for this config\n const stage = settings\n ? stageName\n ? settings.getStage(stageName)\n : settings.findStageForConfig(config.name)\n : null;\n\n if (!stage) {\n\n // No stage = no requirements to check\n return result;\n\n }\n\n // Check required secrets (local secrets + vault secrets count as \"set\")\n const localSecrets = state.listSecrets(config.name);\n const availableSecrets = new Set([...localSecrets, ...vaultSecretKeys]);\n\n for (const secret of stage.secrets ?? []) {\n\n const isRequired = secret.required !== false; // Default to true\n if (isRequired && !availableSecrets.has(secret.key)) {\n\n result.missingSecrets.push(secret.key);\n\n }\n\n }\n\n // Check stage constraint violations\n const defaults = stage.defaults ?? {} as ConfigInput;\n\n // protected: true cannot be overridden to false\n if (defaults.protected === true && config.protected === false) {\n\n result.violations.push(\n `Stage \"${stageName ?? config.name}\" requires protected=true, but config has protected=false`,\n );\n\n }\n\n // isTest: true cannot be overridden to false\n if (defaults.isTest === true && config.isTest === false) {\n\n result.violations.push(\n `Stage \"${stageName ?? config.name}\" requires isTest=true, but config has isTest=false`,\n );\n\n }\n\n // Update complete flag\n result.complete = result.missingSecrets.length === 0 && result.violations.length === 0;\n\n return result;\n\n}\n\n/**\n * Check if a config can be deleted.\n *\n * Locked stages prevent config deletion.\n */\nexport function canDeleteConfig(\n configName: string,\n settings?: SettingsProvider,\n stageName?: string,\n): { allowed: boolean; reason?: string } {\n\n if (!settings) {\n\n return { allowed: true };\n\n }\n\n const stage = stageName\n ? settings.getStage(stageName)\n : settings.findStageForConfig(configName);\n\n if (stage?.locked) {\n\n return {\n allowed: false,\n reason: `Config \"${configName}\" is linked to a locked stage and cannot be deleted`,\n };\n\n }\n\n return { allowed: true };\n\n}\n","/**\n * Dialect-aware SQL builders for stored procedures and functions.\n *\n * Generates parameterized Kysely RawBuilder instances with proper\n * dialect-specific syntax for EXEC/CALL and SELECT function calls.\n * Values are always bound as parameters to prevent SQL injection.\n */\nimport { sql } from 'kysely';\n\nimport type { RawBuilder } from 'kysely';\nimport type { Dialect } from '../core/connection/types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Stored Procedure Builder\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Build a dialect-specific stored procedure call.\n *\n * Generates EXEC (MSSQL) or CALL (PG/MySQL) with proper named\n * or positional parameter syntax. SQLite throws — no procedure support.\n *\n * @example\n * ```typescript\n * // Named params on MSSQL → EXEC get_users @department_id = $1, @active = $2\n * buildProcCall('mssql', 'get_users', { department_id: 1, active: true });\n *\n * // Named params on PG → CALL get_users(department_id => $1, active => $2)\n * buildProcCall('postgres', 'get_users', { department_id: 1, active: true });\n *\n * // Positional on MySQL → CALL get_users(?, ?)\n * buildProcCall('mysql', 'get_users', [1, true]);\n * ```\n */\nexport function buildProcCall<T = unknown>(\n dialect: Dialect,\n name: string,\n params?: Record<string, unknown> | unknown[],\n): RawBuilder<T> {\n\n if (dialect === 'sqlite') {\n\n throw new Error('SQLite does not support stored procedures.');\n\n }\n\n const rawName = sql.raw(name);\n\n if (!params || (Array.isArray(params) && params.length === 0) || (!Array.isArray(params) && Object.keys(params).length === 0)) {\n\n if (dialect === 'mssql') {\n\n return sql<T>`EXEC ${rawName}`;\n\n }\n\n return sql<T>`CALL ${rawName}()`;\n\n }\n\n if (dialect === 'mssql') {\n\n return buildMssqlProc<T>(rawName, params);\n\n }\n\n if (dialect === 'postgres') {\n\n return buildPostgresProc<T>(rawName, params);\n\n }\n\n // MySQL — always positional\n return buildMysqlProc<T>(rawName, params);\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Database Function Builder\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Build a dialect-specific database function call as a SELECT.\n *\n * Generates SELECT name(...) AS column. Named params only on PG;\n * other dialects fall back to positional. SQLite throws.\n *\n * @example\n * ```typescript\n * // PG named → SELECT calc_total(order_id => $1) AS total\n * buildFuncCall('postgres', 'calc_total', 'total', { order_id: 42 });\n *\n * // MSSQL named → DECLARE @__result sql_variant; EXEC @__result = calc_total @order_id = @1; SELECT @__result AS total\n * buildFuncCall('mssql', 'calc_total', 'total', { order_id: 42 });\n *\n * // MSSQL positional → SELECT calc_total(@1) AS total\n * buildFuncCall('mssql', 'calc_total', 'total', [42]);\n * ```\n */\nexport function buildFuncCall<T = unknown>(\n dialect: Dialect,\n name: string,\n column: string,\n params?: Record<string, unknown> | unknown[],\n): RawBuilder<T> {\n\n if (dialect === 'sqlite') {\n\n throw new Error('SQLite does not support database function calls.');\n\n }\n\n const rawName = sql.raw(name);\n const rawCol = sql.raw(column);\n\n if (!params || (Array.isArray(params) && params.length === 0) || (!Array.isArray(params) && Object.keys(params).length === 0)) {\n\n return sql<T>`SELECT ${rawName}() AS ${rawCol}`;\n\n }\n\n // PG supports named params in function calls\n if (dialect === 'postgres' && !Array.isArray(params)) {\n\n const parts = Object.entries(params).map(([key, val]) =>\n sql`${sql.raw(key)} => ${val}`,\n );\n\n return sql<T>`SELECT ${rawName}(${sql.join(parts)}) AS ${rawCol}`;\n\n }\n\n // MSSQL named params — use EXEC pattern with sql_variant capture\n // SELECT dbo.func(...) doesn't support named params in T-SQL,\n // but EXEC @var = func @key = val does. This avoids silent\n // mis-ordering when the user passes an object.\n if (dialect === 'mssql' && !Array.isArray(params)) {\n\n const parts = Object.entries(params).map(([key, val]) =>\n sql`${sql.raw(`@${key}`)} = ${val}`,\n );\n\n return sql<T>`DECLARE @__result sql_variant; EXEC @__result = ${rawName} ${sql.join(parts)}; SELECT @__result AS ${rawCol}`;\n\n }\n\n // MySQL does not support named params — reject objects\n if (dialect === 'mysql' && !Array.isArray(params)) {\n\n throw new Error('MySQL does not support named parameters in function calls. Use positional parameters (array) instead.');\n\n }\n\n // Positional — MSSQL arrays, MySQL arrays\n const values = Array.isArray(params) ? params : Object.values(params);\n const joined = sql.join(values.map((v) => sql`${v}`));\n\n return sql<T>`SELECT ${rawName}(${joined}) AS ${rawCol}`;\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Dialect-Specific Proc Builders\n// ─────────────────────────────────────────────────────────────\n\n/**\n * MSSQL stored procedure call.\n *\n * Named: EXEC name @key = val, @key2 = val2\n * Positional: EXEC name val, val2\n */\nfunction buildMssqlProc<T>(rawName: RawBuilder<unknown>, params: Record<string, unknown> | unknown[]): RawBuilder<T> {\n\n if (Array.isArray(params)) {\n\n const joined = sql.join(params.map((v) => sql`${v}`));\n\n return sql<T>`EXEC ${rawName} ${joined}`;\n\n }\n\n const parts = Object.entries(params).map(([key, val]) =>\n sql`${sql.raw(`@${key}`)} = ${val}`,\n );\n\n return sql<T>`EXEC ${rawName} ${sql.join(parts)}`;\n\n}\n\n/**\n * PostgreSQL stored procedure call.\n *\n * Named: CALL name(key => val, key2 => val2)\n * Positional: CALL name(val, val2)\n */\nfunction buildPostgresProc<T>(rawName: RawBuilder<unknown>, params: Record<string, unknown> | unknown[]): RawBuilder<T> {\n\n if (Array.isArray(params)) {\n\n const joined = sql.join(params.map((v) => sql`${v}`));\n\n return sql<T>`CALL ${rawName}(${joined})`;\n\n }\n\n const parts = Object.entries(params).map(([key, val]) =>\n sql`${sql.raw(key)} => ${val}`,\n );\n\n return sql<T>`CALL ${rawName}(${sql.join(parts)})`;\n\n}\n\n/**\n * MySQL stored procedure call.\n *\n * Always positional: CALL name(val, val2)\n * Named params fall back to positional (MySQL has no named param syntax).\n */\nfunction buildMysqlProc<T>(rawName: RawBuilder<unknown>, params: Record<string, unknown> | unknown[]): RawBuilder<T> {\n\n const values = Array.isArray(params) ? params : Object.values(params);\n const joined = sql.join(values.map((v) => sql`${v}`));\n\n return sql<T>`CALL ${rawName}(${joined})`;\n\n}\n","/**\n * PostgreSQL schema exploration operations.\n *\n * Queries PostgreSQL system catalogs (pg_catalog, information_schema)\n * to retrieve database object metadata.\n */\nimport { sql } from 'kysely';\n\nimport type { Kysely } from 'kysely';\nimport type {\n DialectExploreOperations,\n ExploreOverview,\n TableSummary,\n ViewSummary,\n ProcedureSummary,\n FunctionSummary,\n TypeSummary,\n IndexSummary,\n ForeignKeySummary,\n TriggerSummary,\n LockSummary,\n ConnectionSummary,\n TableDetail,\n ViewDetail,\n ProcedureDetail,\n FunctionDetail,\n TypeDetail,\n TriggerDetail,\n ColumnDetail,\n ParameterDetail,\n} from '../types.js';\n\n/**\n * Schemas to exclude from exploration (system schemas).\n */\nconst EXCLUDED_SCHEMAS = ['pg_catalog', 'information_schema', 'pg_toast'];\n\n/**\n * PostgreSQL explore operations.\n */\nexport const postgresExploreOperations: DialectExploreOperations = {\n\n async getOverview(db: Kysely<unknown>): Promise<ExploreOverview> {\n\n // All counts exclude extension objects (pg_depend with deptype='e')\n const [tables, views, procedures, functions, types, indexes, foreignKeys] =\n await Promise.all([\n sql<{ count: string }>`\n SELECT COUNT(*)::text as count\n FROM information_schema.tables\n WHERE table_schema NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n AND table_type = 'BASE TABLE'\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*)::text as count\n FROM information_schema.views\n WHERE table_schema NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*)::text as count\n FROM pg_proc p\n JOIN pg_namespace n ON p.pronamespace = n.oid\n WHERE n.nspname NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n AND p.prokind = 'p'\n AND NOT EXISTS (\n SELECT 1 FROM pg_depend d\n WHERE d.objid = p.oid\n AND d.deptype = 'e'\n )\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*)::text as count\n FROM pg_proc p\n JOIN pg_namespace n ON p.pronamespace = n.oid\n WHERE n.nspname NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n AND p.prokind = 'f'\n AND NOT EXISTS (\n SELECT 1 FROM pg_depend d\n WHERE d.objid = p.oid\n AND d.deptype = 'e'\n )\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*)::text as count\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n AND t.typtype IN ('e', 'c', 'd')\n AND NOT EXISTS (\n SELECT 1 FROM pg_depend d\n WHERE d.objid = t.oid\n AND d.deptype = 'e'\n )\n AND NOT EXISTS (\n SELECT 1 FROM pg_class c\n WHERE c.reltype = t.oid\n AND c.relkind IN ('r', 'v', 'm', 'p')\n )\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*)::text as count\n FROM pg_indexes\n WHERE schemaname NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*)::text as count\n FROM information_schema.table_constraints\n WHERE constraint_type = 'FOREIGN KEY'\n AND table_schema NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n ]);\n\n return {\n tables: parseInt(tables.rows[0]?.count ?? '0', 10),\n views: parseInt(views.rows[0]?.count ?? '0', 10),\n procedures: parseInt(procedures.rows[0]?.count ?? '0', 10),\n functions: parseInt(functions.rows[0]?.count ?? '0', 10),\n types: parseInt(types.rows[0]?.count ?? '0', 10),\n indexes: parseInt(indexes.rows[0]?.count ?? '0', 10),\n foreignKeys: parseInt(foreignKeys.rows[0]?.count ?? '0', 10),\n triggers: 0, // TODO: implement count\n locks: 0, // TODO: implement count\n connections: 0, // TODO: implement count\n };\n\n },\n\n async listTables(db: Kysely<unknown>): Promise<TableSummary[]> {\n\n const result = await sql<{\n table_name: string;\n table_schema: string;\n column_count: string;\n row_estimate: string;\n }>`\n SELECT\n t.table_name,\n t.table_schema,\n (\n SELECT COUNT(*)::text\n FROM information_schema.columns c\n WHERE c.table_schema = t.table_schema\n AND c.table_name = t.table_name\n ) as column_count,\n COALESCE(\n (\n SELECT reltuples::bigint::text\n FROM pg_class pc\n JOIN pg_namespace pn ON pc.relnamespace = pn.oid\n WHERE pc.relname = t.table_name\n AND pn.nspname = t.table_schema\n ),\n '0'\n ) as row_estimate\n FROM information_schema.tables t\n WHERE t.table_schema NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n AND t.table_type = 'BASE TABLE'\n ORDER BY t.table_schema, t.table_name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.table_name,\n schema: row.table_schema,\n columnCount: parseInt(row.column_count, 10),\n rowCountEstimate: parseInt(row.row_estimate, 10) > 0\n ? parseInt(row.row_estimate, 10)\n : undefined,\n }));\n\n },\n\n async listViews(db: Kysely<unknown>): Promise<ViewSummary[]> {\n\n const result = await sql<{\n table_name: string;\n table_schema: string;\n column_count: string;\n is_updatable: string;\n }>`\n SELECT\n v.table_name,\n v.table_schema,\n (\n SELECT COUNT(*)::text\n FROM information_schema.columns c\n WHERE c.table_schema = v.table_schema\n AND c.table_name = v.table_name\n ) as column_count,\n v.is_updatable\n FROM information_schema.views v\n WHERE v.table_schema NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY v.table_schema, v.table_name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.table_name,\n schema: row.table_schema,\n columnCount: parseInt(row.column_count, 10),\n isUpdatable: row.is_updatable === 'YES',\n }));\n\n },\n\n async listProcedures(db: Kysely<unknown>): Promise<ProcedureSummary[]> {\n\n // Exclude procedures that belong to extensions (pg_depend with deptype='e')\n const result = await sql<{\n proname: string;\n nspname: string;\n param_count: string;\n }>`\n SELECT\n p.proname,\n n.nspname,\n p.pronargs::text as param_count\n FROM pg_proc p\n JOIN pg_namespace n ON p.pronamespace = n.oid\n WHERE n.nspname NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n AND p.prokind = 'p'\n AND NOT EXISTS (\n SELECT 1 FROM pg_depend d\n WHERE d.objid = p.oid\n AND d.deptype = 'e'\n )\n ORDER BY n.nspname, p.proname\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.proname,\n schema: row.nspname,\n parameterCount: parseInt(row.param_count, 10),\n }));\n\n },\n\n async listFunctions(db: Kysely<unknown>): Promise<FunctionSummary[]> {\n\n // Exclude functions that belong to extensions (pg_depend with deptype='e')\n const result = await sql<{\n proname: string;\n nspname: string;\n param_count: string;\n return_type: string;\n }>`\n SELECT\n p.proname,\n n.nspname,\n p.pronargs::text as param_count,\n pg_get_function_result(p.oid) as return_type\n FROM pg_proc p\n JOIN pg_namespace n ON p.pronamespace = n.oid\n WHERE n.nspname NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n AND p.prokind = 'f'\n AND NOT EXISTS (\n SELECT 1 FROM pg_depend d\n WHERE d.objid = p.oid\n AND d.deptype = 'e'\n )\n ORDER BY n.nspname, p.proname\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.proname,\n schema: row.nspname,\n parameterCount: parseInt(row.param_count, 10),\n returnType: row.return_type,\n }));\n\n },\n\n async listTypes(db: Kysely<unknown>): Promise<TypeSummary[]> {\n\n // Exclude:\n // - Types that belong to extensions (pg_depend with deptype='e')\n // - Auto-generated row types for tables/views (pg_class.reltype)\n const result = await sql<{\n typname: string;\n nspname: string;\n typtype: string;\n value_count: string | null;\n }>`\n SELECT\n t.typname,\n n.nspname,\n t.typtype,\n CASE\n WHEN t.typtype = 'e' THEN (\n SELECT COUNT(*)::text\n FROM pg_enum e\n WHERE e.enumtypid = t.oid\n )\n ELSE NULL\n END as value_count\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n AND t.typtype IN ('e', 'c', 'd')\n AND NOT EXISTS (\n SELECT 1 FROM pg_depend d\n WHERE d.objid = t.oid\n AND d.deptype = 'e'\n )\n AND NOT EXISTS (\n SELECT 1 FROM pg_class c\n WHERE c.reltype = t.oid\n AND c.relkind IN ('r', 'v', 'm', 'p')\n )\n ORDER BY n.nspname, t.typname\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.typname,\n schema: row.nspname,\n kind: row.typtype === 'e'\n ? 'enum'\n : row.typtype === 'c'\n ? 'composite'\n : row.typtype === 'd'\n ? 'domain'\n : 'other',\n valueCount: row.value_count ? parseInt(row.value_count, 10) : undefined,\n }));\n\n },\n\n async listIndexes(db: Kysely<unknown>): Promise<IndexSummary[]> {\n\n // Query indexes with primary key constraint info from pg_constraint\n const result = await sql<{\n indexname: string;\n schemaname: string;\n tablename: string;\n indexdef: string;\n is_primary: boolean;\n }>`\n SELECT\n i.indexname,\n i.schemaname,\n i.tablename,\n i.indexdef,\n COALESCE(\n EXISTS (\n SELECT 1 FROM pg_constraint c\n JOIN pg_class idx ON idx.oid = c.conindid\n JOIN pg_class tbl ON tbl.oid = c.conrelid\n JOIN pg_namespace n ON n.oid = tbl.relnamespace\n WHERE c.contype = 'p'\n AND idx.relname = i.indexname\n AND n.nspname = i.schemaname\n ),\n false\n ) as is_primary\n FROM pg_indexes i\n WHERE i.schemaname NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY i.schemaname, i.tablename, i.indexname\n `.execute(db);\n\n return result.rows.map((row) => {\n\n const isPrimary = row.is_primary;\n const isUnique = row.indexdef.includes('UNIQUE') || isPrimary;\n\n // Extract columns from index definition\n const columnsMatch = row.indexdef.match(/\\(([^)]+)\\)/);\n const columns = columnsMatch?.[1]\n ? columnsMatch[1].split(',').map((c) => c.trim())\n : [];\n\n return {\n name: row.indexname,\n schema: row.schemaname,\n tableName: row.tablename,\n tableSchema: row.schemaname,\n columns,\n isUnique,\n isPrimary,\n };\n\n });\n\n },\n\n async listForeignKeys(db: Kysely<unknown>): Promise<ForeignKeySummary[]> {\n\n const result = await sql<{\n constraint_name: string;\n table_schema: string;\n table_name: string;\n column_name: string;\n foreign_table_schema: string;\n foreign_table_name: string;\n foreign_column_name: string;\n update_rule: string;\n delete_rule: string;\n }>`\n SELECT\n tc.constraint_name,\n tc.table_schema,\n tc.table_name,\n kcu.column_name,\n ccu.table_schema AS foreign_table_schema,\n ccu.table_name AS foreign_table_name,\n ccu.column_name AS foreign_column_name,\n rc.update_rule,\n rc.delete_rule\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n JOIN information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\n AND tc.table_schema = ccu.table_schema\n JOIN information_schema.referential_constraints rc\n ON tc.constraint_name = rc.constraint_name\n AND tc.table_schema = rc.constraint_schema\n WHERE tc.constraint_type = 'FOREIGN KEY'\n AND tc.table_schema NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY tc.table_schema, tc.table_name, tc.constraint_name\n `.execute(db);\n\n // Group by constraint name (multi-column FKs)\n const fkMap = new Map<string, ForeignKeySummary>();\n\n for (const row of result.rows) {\n\n const key = `${row.table_schema}.${row.constraint_name}`;\n\n if (!fkMap.has(key)) {\n\n fkMap.set(key, {\n name: row.constraint_name,\n schema: row.table_schema,\n tableName: row.table_name,\n tableSchema: row.table_schema,\n columns: [row.column_name],\n referencedTable: row.foreign_table_name,\n referencedSchema: row.foreign_table_schema,\n referencedColumns: [row.foreign_column_name],\n onUpdate: row.update_rule,\n onDelete: row.delete_rule,\n });\n\n }\n else {\n\n const fk = fkMap.get(key)!;\n fk.columns.push(row.column_name);\n fk.referencedColumns.push(row.foreign_column_name);\n\n }\n\n }\n\n return Array.from(fkMap.values());\n\n },\n\n async getTableDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'public',\n ): Promise<TableDetail | null> {\n\n // Get columns\n const columnsResult = await sql<{\n column_name: string;\n data_type: string;\n is_nullable: string;\n column_default: string | null;\n ordinal_position: string;\n }>`\n SELECT\n column_name,\n data_type,\n is_nullable,\n column_default,\n ordinal_position::text\n FROM information_schema.columns\n WHERE table_schema = ${schema}\n AND table_name = ${name}\n ORDER BY ordinal_position\n `.execute(db);\n\n if (columnsResult.rows.length === 0) {\n\n return null;\n\n }\n\n // Get primary key columns\n const pkResult = await sql<{ column_name: string }>`\n SELECT kcu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.constraint_type = 'PRIMARY KEY'\n AND tc.table_schema = ${schema}\n AND tc.table_name = ${name}\n `.execute(db);\n\n const pkColumns = new Set(pkResult.rows.map((r) => r.column_name));\n\n // Get row estimate\n const rowEstimateResult = await sql<{ reltuples: string }>`\n SELECT reltuples::bigint::text\n FROM pg_class pc\n JOIN pg_namespace pn ON pc.relnamespace = pn.oid\n WHERE pc.relname = ${name}\n AND pn.nspname = ${schema}\n `.execute(db);\n\n const rowEstimate = parseInt(rowEstimateResult.rows[0]?.reltuples ?? '0', 10);\n\n const columns: ColumnDetail[] = columnsResult.rows.map((row) => ({\n name: row.column_name,\n dataType: row.data_type,\n isNullable: row.is_nullable === 'YES',\n defaultValue: row.column_default ?? undefined,\n isPrimaryKey: pkColumns.has(row.column_name),\n ordinalPosition: parseInt(row.ordinal_position, 10),\n }));\n\n // Get indexes for this table\n const allIndexes = await this.listIndexes(db);\n const indexes = allIndexes.filter(\n (idx) => idx.tableName === name && idx.tableSchema === schema,\n );\n\n // Get foreign keys for this table\n const allFks = await this.listForeignKeys(db);\n const foreignKeys = allFks.filter(\n (fk) => fk.tableName === name && fk.tableSchema === schema,\n );\n\n return {\n name,\n schema,\n columns,\n indexes,\n foreignKeys,\n rowCountEstimate: rowEstimate > 0 ? rowEstimate : undefined,\n };\n\n },\n\n async getViewDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'public',\n ): Promise<ViewDetail | null> {\n\n // Get view info\n const viewResult = await sql<{\n is_updatable: string;\n view_definition: string | null;\n }>`\n SELECT is_updatable, view_definition\n FROM information_schema.views\n WHERE table_schema = ${schema}\n AND table_name = ${name}\n `.execute(db);\n\n if (viewResult.rows.length === 0) {\n\n return null;\n\n }\n\n // Get columns\n const columnsResult = await sql<{\n column_name: string;\n data_type: string;\n is_nullable: string;\n column_default: string | null;\n ordinal_position: string;\n }>`\n SELECT\n column_name,\n data_type,\n is_nullable,\n column_default,\n ordinal_position::text\n FROM information_schema.columns\n WHERE table_schema = ${schema}\n AND table_name = ${name}\n ORDER BY ordinal_position\n `.execute(db);\n\n const columns: ColumnDetail[] = columnsResult.rows.map((row) => ({\n name: row.column_name,\n dataType: row.data_type,\n isNullable: row.is_nullable === 'YES',\n defaultValue: row.column_default ?? undefined,\n isPrimaryKey: false,\n ordinalPosition: parseInt(row.ordinal_position, 10),\n }));\n\n const viewRow = viewResult.rows[0];\n\n return {\n name,\n schema,\n columns,\n definition: viewRow?.view_definition ?? undefined,\n isUpdatable: viewRow?.is_updatable === 'YES',\n };\n\n },\n\n async getProcedureDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'public',\n ): Promise<ProcedureDetail | null> {\n\n const result = await sql<{\n oid: string;\n prosrc: string;\n }>`\n SELECT p.oid::text, p.prosrc\n FROM pg_proc p\n JOIN pg_namespace n ON p.pronamespace = n.oid\n WHERE n.nspname = ${schema}\n AND p.proname = ${name}\n AND p.prokind = 'p'\n `.execute(db);\n\n const procRow = result.rows[0];\n\n if (!procRow) {\n\n return null;\n\n }\n\n const oid = procRow.oid;\n\n // Get parameters\n const paramsResult = await sql<{\n parameter_name: string | null;\n data_type: string;\n parameter_mode: string;\n ordinal_position: string;\n parameter_default: string | null;\n }>`\n SELECT\n parameter_name,\n data_type,\n parameter_mode,\n ordinal_position::text,\n parameter_default\n FROM information_schema.parameters\n WHERE specific_schema = ${schema}\n AND specific_name = ${name || sql.raw(`'_' || ${oid}`)}\n ORDER BY ordinal_position\n `.execute(db);\n\n const parameters: ParameterDetail[] = paramsResult.rows.map((row) => ({\n name: row.parameter_name ?? `$${row.ordinal_position}`,\n dataType: row.data_type,\n mode: row.parameter_mode as 'IN' | 'OUT' | 'INOUT',\n defaultValue: row.parameter_default ?? undefined,\n ordinalPosition: parseInt(row.ordinal_position, 10),\n }));\n\n return {\n name,\n schema,\n parameters,\n definition: procRow.prosrc,\n };\n\n },\n\n async getFunctionDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'public',\n ): Promise<FunctionDetail | null> {\n\n const result = await sql<{\n oid: string;\n prosrc: string;\n return_type: string;\n language: string;\n }>`\n SELECT\n p.oid::text,\n p.prosrc,\n pg_get_function_result(p.oid) as return_type,\n l.lanname as language\n FROM pg_proc p\n JOIN pg_namespace n ON p.pronamespace = n.oid\n JOIN pg_language l ON p.prolang = l.oid\n WHERE n.nspname = ${schema}\n AND p.proname = ${name}\n AND p.prokind = 'f'\n `.execute(db);\n\n const funcRow = result.rows[0];\n\n if (!funcRow) {\n\n return null;\n\n }\n\n const oid = funcRow.oid;\n\n // Get parameters using specific_name which is function_name_oid format\n const paramsResult = await sql<{\n parameter_name: string | null;\n data_type: string;\n parameter_mode: string;\n ordinal_position: string;\n parameter_default: string | null;\n }>`\n SELECT\n parameter_name,\n data_type,\n parameter_mode,\n ordinal_position::text,\n parameter_default\n FROM information_schema.parameters\n WHERE specific_schema = ${schema}\n AND specific_name = ${name + '_' + oid}\n AND parameter_mode IN ('IN', 'INOUT')\n ORDER BY ordinal_position\n `.execute(db);\n\n const parameters: ParameterDetail[] = paramsResult.rows.map((row) => ({\n name: row.parameter_name ?? `$${row.ordinal_position}`,\n dataType: row.data_type,\n mode: row.parameter_mode as 'IN' | 'OUT' | 'INOUT',\n defaultValue: row.parameter_default ?? undefined,\n ordinalPosition: parseInt(row.ordinal_position, 10),\n }));\n\n return {\n name,\n schema,\n parameters,\n returnType: funcRow.return_type,\n definition: funcRow.prosrc,\n language: funcRow.language,\n };\n\n },\n\n async getTypeDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'public',\n ): Promise<TypeDetail | null> {\n\n const result = await sql<{\n oid: string;\n typtype: string;\n basetype: string | null;\n }>`\n SELECT\n t.oid::text,\n t.typtype,\n CASE\n WHEN t.typtype = 'd' THEN pg_catalog.format_type(t.typbasetype, t.typtypmod)\n ELSE NULL\n END as basetype\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname = ${schema}\n AND t.typname = ${name}\n AND t.typtype IN ('e', 'c', 'd')\n `.execute(db);\n\n const typeRow = result.rows[0];\n\n if (!typeRow) {\n\n return null;\n\n }\n\n const kind = typeRow.typtype === 'e'\n ? 'enum'\n : typeRow.typtype === 'c'\n ? 'composite'\n : typeRow.typtype === 'd'\n ? 'domain'\n : 'other';\n\n let values: string[] | undefined;\n let attributes: ColumnDetail[] | undefined;\n\n if (kind === 'enum') {\n\n const enumResult = await sql<{ enumlabel: string }>`\n SELECT enumlabel\n FROM pg_enum\n WHERE enumtypid = ${typeRow.oid}::oid\n ORDER BY enumsortorder\n `.execute(db);\n\n values = enumResult.rows.map((r) => r.enumlabel);\n\n }\n else if (kind === 'composite') {\n\n const attrResult = await sql<{\n attname: string;\n typname: string;\n attnotnull: boolean;\n attnum: string;\n }>`\n SELECT\n a.attname,\n t.typname,\n a.attnotnull,\n a.attnum::text\n FROM pg_attribute a\n JOIN pg_type t ON a.atttypid = t.oid\n WHERE a.attrelid = ${typeRow.oid}::oid::regclass\n AND a.attnum > 0\n ORDER BY a.attnum\n `.execute(db);\n\n attributes = attrResult.rows.map((r) => ({\n name: r.attname,\n dataType: r.typname,\n isNullable: !r.attnotnull,\n isPrimaryKey: false,\n ordinalPosition: parseInt(r.attnum, 10),\n }));\n\n }\n\n return {\n name,\n schema,\n kind,\n values,\n attributes,\n baseType: typeRow.basetype ?? undefined,\n };\n\n },\n\n async listTriggers(db: Kysely<unknown>): Promise<TriggerSummary[]> {\n\n const result = await sql<{\n trigger_name: string;\n trigger_schema: string;\n event_object_table: string;\n event_object_schema: string;\n action_timing: string;\n event_manipulation: string;\n }>`\n SELECT DISTINCT\n trigger_name,\n trigger_schema,\n event_object_table,\n event_object_schema,\n action_timing,\n event_manipulation\n FROM information_schema.triggers\n WHERE trigger_schema NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY trigger_schema, event_object_table, trigger_name\n `.execute(db);\n\n // Group by trigger name to combine events\n const triggerMap = new Map<string, TriggerSummary>();\n\n for (const row of result.rows) {\n\n const key = `${row.trigger_schema}.${row.trigger_name}`;\n const existing = triggerMap.get(key);\n\n if (existing) {\n\n existing.events.push(row.event_manipulation as 'INSERT' | 'UPDATE' | 'DELETE');\n\n }\n else {\n\n triggerMap.set(key, {\n name: row.trigger_name,\n schema: row.trigger_schema,\n tableName: row.event_object_table,\n tableSchema: row.event_object_schema,\n timing: row.action_timing as 'BEFORE' | 'AFTER' | 'INSTEAD OF',\n events: [row.event_manipulation as 'INSERT' | 'UPDATE' | 'DELETE'],\n });\n\n }\n\n }\n\n return Array.from(triggerMap.values());\n\n },\n\n async listLocks(db: Kysely<unknown>): Promise<LockSummary[]> {\n\n const result = await sql<{\n pid: number;\n locktype: string;\n relation: string | null;\n mode: string;\n granted: boolean;\n }>`\n SELECT\n l.pid,\n l.locktype,\n l.relation::regclass::text as relation,\n l.mode,\n l.granted\n FROM pg_locks l\n WHERE l.locktype != 'virtualxid'\n ORDER BY l.pid, l.locktype\n `.execute(db);\n\n return result.rows.map((row) => ({\n pid: row.pid,\n lockType: row.locktype,\n objectName: row.relation ?? undefined,\n mode: row.mode,\n granted: row.granted,\n }));\n\n },\n\n async listConnections(db: Kysely<unknown>): Promise<ConnectionSummary[]> {\n\n const result = await sql<{\n pid: number;\n usename: string;\n datname: string;\n application_name: string;\n client_addr: string | null;\n backend_start: Date;\n state: string;\n }>`\n SELECT\n pid,\n usename,\n datname,\n application_name,\n client_addr::text,\n backend_start,\n COALESCE(state, 'unknown') as state\n FROM pg_stat_activity\n WHERE datname = current_database()\n AND pid != pg_backend_pid()\n ORDER BY backend_start DESC\n `.execute(db);\n\n return result.rows.map((row) => ({\n pid: row.pid,\n username: row.usename,\n database: row.datname,\n applicationName: row.application_name || undefined,\n clientAddress: row.client_addr ?? undefined,\n backendStart: row.backend_start,\n state: row.state,\n }));\n\n },\n\n async getTriggerDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'public',\n ): Promise<TriggerDetail | null> {\n\n const result = await sql<{\n trigger_name: string;\n event_object_table: string;\n action_timing: string;\n event_manipulation: string;\n action_statement: string;\n }>`\n SELECT\n trigger_name,\n event_object_table,\n action_timing,\n event_manipulation,\n action_statement\n FROM information_schema.triggers\n WHERE trigger_name = ${name}\n AND trigger_schema = ${schema}\n `.execute(db);\n\n if (result.rows.length === 0) {\n\n return null;\n\n }\n\n const events = result.rows.map((r) => r.event_manipulation);\n const row = result.rows[0]!;\n\n return {\n name: row.trigger_name,\n schema,\n tableName: row.event_object_table,\n tableSchema: schema,\n timing: row.action_timing,\n events,\n definition: row.action_statement,\n isEnabled: true, // PostgreSQL triggers are always enabled when they exist\n };\n\n },\n\n};\n","/**\n * MySQL schema exploration operations.\n *\n * Queries MySQL information_schema to retrieve database object metadata.\n */\nimport { attempt } from '@logosdx/utils';\nimport { sql } from 'kysely';\n\nimport type { Kysely } from 'kysely';\nimport type {\n DialectExploreOperations,\n ExploreOverview,\n TableSummary,\n ViewSummary,\n ProcedureSummary,\n FunctionSummary,\n TypeSummary,\n IndexSummary,\n ForeignKeySummary,\n TriggerSummary,\n LockSummary,\n ConnectionSummary,\n TableDetail,\n ViewDetail,\n ProcedureDetail,\n FunctionDetail,\n TypeDetail,\n TriggerDetail,\n ColumnDetail,\n ParameterDetail,\n} from '../types.js';\n\n/**\n * MySQL explore operations.\n */\nexport const mysqlExploreOperations: DialectExploreOperations = {\n\n async getOverview(db: Kysely<unknown>): Promise<ExploreOverview> {\n\n // Get current database name\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = dbNameResult.rows[0]?.db;\n\n if (!dbName) {\n\n return {\n tables: 0,\n views: 0,\n procedures: 0,\n functions: 0,\n types: 0,\n indexes: 0,\n foreignKeys: 0,\n triggers: 0,\n locks: 0,\n connections: 0,\n };\n\n }\n\n const [tables, views, procedures, functions, indexes, foreignKeys] =\n await Promise.all([\n sql<{ count: string }>`\n SELECT COUNT(*) as count\n FROM information_schema.tables\n WHERE table_schema = ${dbName}\n AND table_type = 'BASE TABLE'\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*) as count\n FROM information_schema.views\n WHERE table_schema = ${dbName}\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*) as count\n FROM information_schema.routines\n WHERE routine_schema = ${dbName}\n AND routine_type = 'PROCEDURE'\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*) as count\n FROM information_schema.routines\n WHERE routine_schema = ${dbName}\n AND routine_type = 'FUNCTION'\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(DISTINCT index_name) as count\n FROM information_schema.statistics\n WHERE table_schema = ${dbName}\n `.execute(db),\n\n sql<{ count: string }>`\n SELECT COUNT(*) as count\n FROM information_schema.table_constraints\n WHERE constraint_schema = ${dbName}\n AND constraint_type = 'FOREIGN KEY'\n `.execute(db),\n ]);\n\n return {\n tables: parseInt(String(tables.rows[0]?.count ?? '0'), 10),\n views: parseInt(String(views.rows[0]?.count ?? '0'), 10),\n procedures: parseInt(String(procedures.rows[0]?.count ?? '0'), 10),\n functions: parseInt(String(functions.rows[0]?.count ?? '0'), 10),\n types: 0, // MySQL doesn't have custom types like PostgreSQL\n indexes: parseInt(String(indexes.rows[0]?.count ?? '0'), 10),\n foreignKeys: parseInt(String(foreignKeys.rows[0]?.count ?? '0'), 10),\n triggers: 0, // TODO: implement count\n locks: 0, // TODO: implement count\n connections: 0, // TODO: implement count\n };\n\n },\n\n async listTables(db: Kysely<unknown>): Promise<TableSummary[]> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = dbNameResult.rows[0]?.db;\n\n if (!dbName) return [];\n\n const result = await sql<{\n table_name: string;\n table_schema: string;\n column_count: string;\n table_rows: string | null;\n }>`\n SELECT\n t.table_name AS table_name,\n t.table_schema AS table_schema,\n (\n SELECT COUNT(*)\n FROM information_schema.columns c\n WHERE c.table_schema = t.table_schema\n AND c.table_name = t.table_name\n ) AS column_count,\n t.table_rows AS table_rows\n FROM information_schema.tables t\n WHERE t.table_schema = ${dbName}\n AND t.table_type = 'BASE TABLE'\n ORDER BY t.table_name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.table_name,\n schema: row.table_schema,\n columnCount: parseInt(String(row.column_count), 10),\n rowCountEstimate: row.table_rows\n ? parseInt(String(row.table_rows), 10)\n : undefined,\n }));\n\n },\n\n async listViews(db: Kysely<unknown>): Promise<ViewSummary[]> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = dbNameResult.rows[0]?.db;\n\n if (!dbName) return [];\n\n const result = await sql<{\n table_name: string;\n table_schema: string;\n column_count: string;\n is_updatable: string;\n }>`\n SELECT\n v.table_name AS table_name,\n v.table_schema AS table_schema,\n (\n SELECT COUNT(*)\n FROM information_schema.columns c\n WHERE c.table_schema = v.table_schema\n AND c.table_name = v.table_name\n ) AS column_count,\n v.is_updatable AS is_updatable\n FROM information_schema.views v\n WHERE v.table_schema = ${dbName}\n ORDER BY v.table_name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.table_name,\n schema: row.table_schema,\n columnCount: parseInt(String(row.column_count), 10),\n isUpdatable: row.is_updatable === 'YES',\n }));\n\n },\n\n async listProcedures(db: Kysely<unknown>): Promise<ProcedureSummary[]> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = dbNameResult.rows[0]?.db;\n\n if (!dbName) return [];\n\n const result = await sql<{\n routine_name: string;\n routine_schema: string;\n param_count: string;\n }>`\n SELECT\n r.routine_name AS routine_name,\n r.routine_schema AS routine_schema,\n (\n SELECT COUNT(*)\n FROM information_schema.parameters p\n WHERE p.specific_schema = r.routine_schema\n AND p.specific_name = r.specific_name\n AND p.ordinal_position > 0\n ) AS param_count\n FROM information_schema.routines r\n WHERE r.routine_schema = ${dbName}\n AND r.routine_type = 'PROCEDURE'\n ORDER BY r.routine_name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.routine_name,\n schema: row.routine_schema,\n parameterCount: parseInt(String(row.param_count), 10),\n }));\n\n },\n\n async listFunctions(db: Kysely<unknown>): Promise<FunctionSummary[]> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = dbNameResult.rows[0]?.db;\n\n if (!dbName) return [];\n\n const result = await sql<{\n routine_name: string;\n routine_schema: string;\n param_count: string;\n data_type: string;\n }>`\n SELECT\n r.routine_name AS routine_name,\n r.routine_schema AS routine_schema,\n (\n SELECT COUNT(*)\n FROM information_schema.parameters p\n WHERE p.specific_schema = r.routine_schema\n AND p.specific_name = r.specific_name\n AND p.ordinal_position > 0\n ) AS param_count,\n COALESCE(r.data_type, 'unknown') AS data_type\n FROM information_schema.routines r\n WHERE r.routine_schema = ${dbName}\n AND r.routine_type = 'FUNCTION'\n ORDER BY r.routine_name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.routine_name,\n schema: row.routine_schema,\n parameterCount: parseInt(String(row.param_count), 10),\n returnType: row.data_type,\n }));\n\n },\n\n async listTypes(_db: Kysely<unknown>): Promise<TypeSummary[]> {\n\n // MySQL doesn't have custom types like PostgreSQL\n return [];\n\n },\n\n async listIndexes(db: Kysely<unknown>): Promise<IndexSummary[]> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = dbNameResult.rows[0]?.db;\n\n if (!dbName) return [];\n\n const result = await sql<{\n index_name: string;\n table_name: string;\n column_name: string;\n non_unique: number;\n seq_in_index: number;\n }>`\n SELECT\n index_name AS index_name,\n table_name AS table_name,\n column_name AS column_name,\n non_unique AS non_unique,\n seq_in_index AS seq_in_index\n FROM information_schema.statistics\n WHERE table_schema = ${dbName}\n ORDER BY table_name, index_name, seq_in_index\n `.execute(db);\n\n // Group by index name\n const indexMap = new Map<string, IndexSummary>();\n\n for (const row of result.rows) {\n\n const key = `${row.table_name}.${row.index_name}`;\n\n if (!indexMap.has(key)) {\n\n indexMap.set(key, {\n name: row.index_name,\n schema: dbName,\n tableName: row.table_name,\n tableSchema: dbName,\n columns: [row.column_name],\n isUnique: row.non_unique === 0,\n isPrimary: row.index_name === 'PRIMARY',\n });\n\n }\n else {\n\n indexMap.get(key)!.columns.push(row.column_name);\n\n }\n\n }\n\n return Array.from(indexMap.values());\n\n },\n\n async listForeignKeys(db: Kysely<unknown>): Promise<ForeignKeySummary[]> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = dbNameResult.rows[0]?.db;\n\n if (!dbName) return [];\n\n const result = await sql<{\n constraint_name: string;\n table_name: string;\n column_name: string;\n referenced_table_name: string;\n referenced_column_name: string;\n update_rule: string;\n delete_rule: string;\n }>`\n SELECT\n kcu.constraint_name AS constraint_name,\n kcu.table_name AS table_name,\n kcu.column_name AS column_name,\n kcu.referenced_table_name AS referenced_table_name,\n kcu.referenced_column_name AS referenced_column_name,\n rc.update_rule AS update_rule,\n rc.delete_rule AS delete_rule\n FROM information_schema.key_column_usage kcu\n JOIN information_schema.referential_constraints rc\n ON kcu.constraint_name = rc.constraint_name\n AND kcu.constraint_schema = rc.constraint_schema\n WHERE kcu.constraint_schema = ${dbName}\n AND kcu.referenced_table_name IS NOT NULL\n ORDER BY kcu.table_name, kcu.constraint_name, kcu.ordinal_position\n `.execute(db);\n\n // Group by constraint name\n const fkMap = new Map<string, ForeignKeySummary>();\n\n for (const row of result.rows) {\n\n const key = `${row.table_name}.${row.constraint_name}`;\n\n if (!fkMap.has(key)) {\n\n fkMap.set(key, {\n name: row.constraint_name,\n schema: dbName,\n tableName: row.table_name,\n tableSchema: dbName,\n columns: [row.column_name],\n referencedTable: row.referenced_table_name,\n referencedSchema: dbName,\n referencedColumns: [row.referenced_column_name],\n onUpdate: row.update_rule,\n onDelete: row.delete_rule,\n });\n\n }\n else {\n\n const fk = fkMap.get(key)!;\n fk.columns.push(row.column_name);\n fk.referencedColumns.push(row.referenced_column_name);\n\n }\n\n }\n\n return Array.from(fkMap.values());\n\n },\n\n async getTableDetail(\n db: Kysely<unknown>,\n name: string,\n schema?: string,\n ): Promise<TableDetail | null> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = schema ?? dbNameResult.rows[0]?.db;\n\n if (!dbName) return null;\n\n // Get columns\n const columnsResult = await sql<{\n column_name: string;\n data_type: string;\n is_nullable: string;\n column_default: string | null;\n ordinal_position: number;\n column_key: string;\n }>`\n SELECT\n column_name AS column_name,\n data_type AS data_type,\n is_nullable AS is_nullable,\n column_default AS column_default,\n ordinal_position AS ordinal_position,\n column_key AS column_key\n FROM information_schema.columns\n WHERE table_schema = ${dbName}\n AND table_name = ${name}\n ORDER BY ordinal_position\n `.execute(db);\n\n if (columnsResult.rows.length === 0) {\n\n return null;\n\n }\n\n const columns: ColumnDetail[] = columnsResult.rows.map((row) => ({\n name: row.column_name,\n dataType: row.data_type,\n isNullable: row.is_nullable === 'YES',\n defaultValue: row.column_default ?? undefined,\n isPrimaryKey: row.column_key === 'PRI',\n ordinalPosition: row.ordinal_position,\n }));\n\n // Get row estimate\n const rowResult = await sql<{ table_rows: string | null }>`\n SELECT table_rows AS table_rows\n FROM information_schema.tables\n WHERE table_schema = ${dbName}\n AND table_name = ${name}\n `.execute(db);\n\n const rowEstimate = rowResult.rows[0]?.table_rows\n ? parseInt(String(rowResult.rows[0].table_rows), 10)\n : undefined;\n\n // Get indexes\n const allIndexes = await this.listIndexes(db);\n const indexes = allIndexes.filter((idx) => idx.tableName === name);\n\n // Get foreign keys\n const allFks = await this.listForeignKeys(db);\n const foreignKeys = allFks.filter((fk) => fk.tableName === name);\n\n return {\n name,\n schema: dbName,\n columns,\n indexes,\n foreignKeys,\n rowCountEstimate: rowEstimate,\n };\n\n },\n\n async getViewDetail(\n db: Kysely<unknown>,\n name: string,\n schema?: string,\n ): Promise<ViewDetail | null> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = schema ?? dbNameResult.rows[0]?.db;\n\n if (!dbName) return null;\n\n // Get view info\n const viewResult = await sql<{\n is_updatable: string;\n view_definition: string | null;\n }>`\n SELECT is_updatable AS is_updatable, view_definition AS view_definition\n FROM information_schema.views\n WHERE table_schema = ${dbName}\n AND table_name = ${name}\n `.execute(db);\n\n if (viewResult.rows.length === 0) {\n\n return null;\n\n }\n\n // Get columns\n const columnsResult = await sql<{\n column_name: string;\n data_type: string;\n is_nullable: string;\n column_default: string | null;\n ordinal_position: number;\n }>`\n SELECT\n column_name AS column_name,\n data_type AS data_type,\n is_nullable AS is_nullable,\n column_default AS column_default,\n ordinal_position AS ordinal_position\n FROM information_schema.columns\n WHERE table_schema = ${dbName}\n AND table_name = ${name}\n ORDER BY ordinal_position\n `.execute(db);\n\n const columns: ColumnDetail[] = columnsResult.rows.map((row) => ({\n name: row.column_name,\n dataType: row.data_type,\n isNullable: row.is_nullable === 'YES',\n defaultValue: row.column_default ?? undefined,\n isPrimaryKey: false,\n ordinalPosition: row.ordinal_position,\n }));\n\n const viewRow = viewResult.rows[0];\n\n return {\n name,\n schema: dbName,\n columns,\n definition: viewRow?.view_definition ?? undefined,\n isUpdatable: viewRow?.is_updatable === 'YES',\n };\n\n },\n\n async getProcedureDetail(\n db: Kysely<unknown>,\n name: string,\n schema?: string,\n ): Promise<ProcedureDetail | null> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = schema ?? dbNameResult.rows[0]?.db;\n\n if (!dbName) return null;\n\n const result = await sql<{\n routine_definition: string | null;\n specific_name: string;\n }>`\n SELECT routine_definition AS routine_definition, specific_name AS specific_name\n FROM information_schema.routines\n WHERE routine_schema = ${dbName}\n AND routine_name = ${name}\n AND routine_type = 'PROCEDURE'\n `.execute(db);\n\n const procRow = result.rows[0];\n\n if (!procRow) {\n\n return null;\n\n }\n\n // Get parameters\n const paramsResult = await sql<{\n parameter_name: string | null;\n data_type: string;\n parameter_mode: string | null;\n ordinal_position: number;\n }>`\n SELECT\n parameter_name AS parameter_name,\n data_type AS data_type,\n parameter_mode AS parameter_mode,\n ordinal_position AS ordinal_position\n FROM information_schema.parameters\n WHERE specific_schema = ${dbName}\n AND specific_name = ${procRow.specific_name}\n AND ordinal_position > 0\n ORDER BY ordinal_position\n `.execute(db);\n\n const parameters: ParameterDetail[] = paramsResult.rows.map((row) => ({\n name: row.parameter_name ?? `param${row.ordinal_position}`,\n dataType: row.data_type,\n mode: (row.parameter_mode ?? 'IN') as 'IN' | 'OUT' | 'INOUT',\n ordinalPosition: row.ordinal_position,\n }));\n\n return {\n name,\n schema: dbName,\n parameters,\n definition: procRow.routine_definition ?? undefined,\n };\n\n },\n\n async getFunctionDetail(\n db: Kysely<unknown>,\n name: string,\n schema?: string,\n ): Promise<FunctionDetail | null> {\n\n const dbNameResult = await sql<{ db: string }>`SELECT DATABASE() as db`.execute(db);\n const dbName = schema ?? dbNameResult.rows[0]?.db;\n\n if (!dbName) return null;\n\n const result = await sql<{\n routine_definition: string | null;\n specific_name: string;\n data_type: string;\n }>`\n SELECT routine_definition AS routine_definition, specific_name AS specific_name, data_type AS data_type\n FROM information_schema.routines\n WHERE routine_schema = ${dbName}\n AND routine_name = ${name}\n AND routine_type = 'FUNCTION'\n `.execute(db);\n\n const funcRow = result.rows[0];\n\n if (!funcRow) {\n\n return null;\n\n }\n\n // Get parameters\n const paramsResult = await sql<{\n parameter_name: string | null;\n data_type: string;\n parameter_mode: string | null;\n ordinal_position: number;\n }>`\n SELECT\n parameter_name AS parameter_name,\n data_type AS data_type,\n parameter_mode AS parameter_mode,\n ordinal_position AS ordinal_position\n FROM information_schema.parameters\n WHERE specific_schema = ${dbName}\n AND specific_name = ${funcRow.specific_name}\n AND ordinal_position > 0\n ORDER BY ordinal_position\n `.execute(db);\n\n const parameters: ParameterDetail[] = paramsResult.rows.map((row) => ({\n name: row.parameter_name ?? `param${row.ordinal_position}`,\n dataType: row.data_type,\n mode: (row.parameter_mode ?? 'IN') as 'IN' | 'OUT' | 'INOUT',\n ordinalPosition: row.ordinal_position,\n }));\n\n return {\n name,\n schema: dbName,\n parameters,\n returnType: funcRow.data_type,\n definition: funcRow.routine_definition ?? undefined,\n };\n\n },\n\n async getTypeDetail(\n _db: Kysely<unknown>,\n _name: string,\n _schema?: string,\n ): Promise<TypeDetail | null> {\n\n // MySQL doesn't have custom types\n return null;\n\n },\n\n async listTriggers(db: Kysely<unknown>): Promise<TriggerSummary[]> {\n\n const result = await sql<{\n TRIGGER_NAME: string;\n TRIGGER_SCHEMA: string;\n EVENT_OBJECT_TABLE: string;\n ACTION_TIMING: string;\n EVENT_MANIPULATION: string;\n }>`\n SELECT\n TRIGGER_NAME,\n TRIGGER_SCHEMA,\n EVENT_OBJECT_TABLE,\n ACTION_TIMING,\n EVENT_MANIPULATION\n FROM information_schema.TRIGGERS\n WHERE TRIGGER_SCHEMA = DATABASE()\n ORDER BY EVENT_OBJECT_TABLE, TRIGGER_NAME\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.TRIGGER_NAME,\n schema: row.TRIGGER_SCHEMA,\n tableName: row.EVENT_OBJECT_TABLE,\n tableSchema: row.TRIGGER_SCHEMA,\n timing: row.ACTION_TIMING as 'BEFORE' | 'AFTER' | 'INSTEAD OF',\n events: [row.EVENT_MANIPULATION as 'INSERT' | 'UPDATE' | 'DELETE'],\n }));\n\n },\n\n async listLocks(db: Kysely<unknown>): Promise<LockSummary[]> {\n\n // MySQL 8.0+ uses performance_schema.metadata_locks\n // Requires SELECT privilege on performance_schema which may not be granted\n const [result, err] = await attempt(() =>\n sql<{\n OBJECT_TYPE: string;\n OBJECT_NAME: string | null;\n LOCK_TYPE: string;\n LOCK_STATUS: string;\n OWNER_THREAD_ID: number;\n }>`\n SELECT\n OBJECT_TYPE,\n OBJECT_NAME,\n LOCK_TYPE,\n LOCK_STATUS,\n OWNER_THREAD_ID\n FROM performance_schema.metadata_locks\n WHERE OBJECT_SCHEMA = DATABASE()\n ORDER BY OWNER_THREAD_ID\n `.execute(db),\n );\n\n // Gracefully handle permission denied errors\n if (err) {\n\n return [];\n\n }\n\n return result.rows.map((row) => ({\n pid: row.OWNER_THREAD_ID,\n lockType: row.OBJECT_TYPE,\n objectName: row.OBJECT_NAME ?? undefined,\n mode: row.LOCK_TYPE,\n granted: row.LOCK_STATUS === 'GRANTED',\n }));\n\n },\n\n async listConnections(db: Kysely<unknown>): Promise<ConnectionSummary[]> {\n\n const result = await sql<{\n ID: number;\n USER: string;\n HOST: string;\n DB: string;\n STATE: string | null;\n INFO: string | null;\n }>`\n SELECT\n ID,\n USER,\n HOST,\n DB,\n STATE,\n INFO\n FROM information_schema.PROCESSLIST\n WHERE DB = DATABASE()\n AND ID != CONNECTION_ID()\n ORDER BY ID\n `.execute(db);\n\n return result.rows.map((row) => ({\n pid: row.ID,\n username: row.USER,\n database: row.DB,\n clientAddress: row.HOST,\n state: row.STATE || 'unknown',\n }));\n\n },\n\n async getTriggerDetail(\n db: Kysely<unknown>,\n name: string,\n schema?: string,\n ): Promise<TriggerDetail | null> {\n\n const result = await sql<{\n TRIGGER_NAME: string;\n EVENT_OBJECT_TABLE: string;\n ACTION_TIMING: string;\n EVENT_MANIPULATION: string;\n ACTION_STATEMENT: string;\n }>`\n SELECT\n TRIGGER_NAME,\n EVENT_OBJECT_TABLE,\n ACTION_TIMING,\n EVENT_MANIPULATION,\n ACTION_STATEMENT\n FROM information_schema.TRIGGERS\n WHERE TRIGGER_NAME = ${name}\n AND TRIGGER_SCHEMA = DATABASE()\n `.execute(db);\n\n if (result.rows.length === 0) {\n\n return null;\n\n }\n\n const row = result.rows[0]!;\n\n return {\n name: row.TRIGGER_NAME,\n schema: schema || undefined,\n tableName: row.EVENT_OBJECT_TABLE,\n tableSchema: schema,\n timing: row.ACTION_TIMING,\n events: [row.EVENT_MANIPULATION],\n definition: row.ACTION_STATEMENT,\n isEnabled: true,\n };\n\n },\n\n};\n","/**\n * MSSQL schema exploration operations.\n *\n * Queries SQL Server system views (sys.*) to retrieve database object metadata.\n */\nimport { sql } from 'kysely';\n\nimport type { Kysely } from 'kysely';\nimport type {\n DialectExploreOperations,\n ExploreOverview,\n TableSummary,\n ViewSummary,\n ProcedureSummary,\n FunctionSummary,\n TypeSummary,\n IndexSummary,\n ForeignKeySummary,\n TriggerSummary,\n LockSummary,\n ConnectionSummary,\n TableDetail,\n ViewDetail,\n ProcedureDetail,\n FunctionDetail,\n TypeDetail,\n TriggerDetail,\n ColumnDetail,\n ParameterDetail,\n} from '../types.js';\n\n/**\n * Schemas to exclude from exploration (system schemas).\n */\nconst EXCLUDED_SCHEMAS = ['sys', 'INFORMATION_SCHEMA', 'guest'];\n\n/**\n * MSSQL explore operations.\n */\nexport const mssqlExploreOperations: DialectExploreOperations = {\n\n async getOverview(db: Kysely<unknown>): Promise<ExploreOverview> {\n\n const [tables, views, procedures, functions, types, indexes, foreignKeys] =\n await Promise.all([\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sys.tables t\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sys.views v\n JOIN sys.schemas s ON v.schema_id = s.schema_id\n WHERE s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sys.procedures p\n JOIN sys.schemas s ON p.schema_id = s.schema_id\n WHERE s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sys.objects o\n JOIN sys.schemas s ON o.schema_id = s.schema_id\n WHERE o.type IN ('FN', 'IF', 'TF')\n AND s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sys.types t\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE t.is_user_defined = 1\n AND s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sys.indexes i\n JOIN sys.tables t ON i.object_id = t.object_id\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE i.name IS NOT NULL\n AND s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sys.foreign_keys fk\n JOIN sys.schemas s ON fk.schema_id = s.schema_id\n WHERE s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n `.execute(db),\n ]);\n\n return {\n tables: tables.rows[0]?.count ?? 0,\n views: views.rows[0]?.count ?? 0,\n procedures: procedures.rows[0]?.count ?? 0,\n functions: functions.rows[0]?.count ?? 0,\n types: types.rows[0]?.count ?? 0,\n indexes: indexes.rows[0]?.count ?? 0,\n foreignKeys: foreignKeys.rows[0]?.count ?? 0,\n triggers: 0, // TODO: implement count\n locks: 0, // TODO: implement count\n connections: 0, // TODO: implement count\n };\n\n },\n\n async listTables(db: Kysely<unknown>): Promise<TableSummary[]> {\n\n const result = await sql<{\n table_name: string;\n schema_name: string;\n column_count: number;\n row_count: number;\n }>`\n SELECT\n t.name as table_name,\n s.name as schema_name,\n (\n SELECT COUNT(*)\n FROM sys.columns c\n WHERE c.object_id = t.object_id\n ) as column_count,\n ISNULL(p.rows, 0) as row_count\n FROM sys.tables t\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n LEFT JOIN sys.partitions p ON t.object_id = p.object_id AND p.index_id IN (0, 1)\n WHERE s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY s.name, t.name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.table_name,\n schema: row.schema_name,\n columnCount: row.column_count,\n rowCountEstimate: row.row_count > 0 ? row.row_count : undefined,\n }));\n\n },\n\n async listViews(db: Kysely<unknown>): Promise<ViewSummary[]> {\n\n const result = await sql<{\n view_name: string;\n schema_name: string;\n column_count: number;\n }>`\n SELECT\n v.name as view_name,\n s.name as schema_name,\n (\n SELECT COUNT(*)\n FROM sys.columns c\n WHERE c.object_id = v.object_id\n ) as column_count\n FROM sys.views v\n JOIN sys.schemas s ON v.schema_id = s.schema_id\n WHERE s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY s.name, v.name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.view_name,\n schema: row.schema_name,\n columnCount: row.column_count,\n isUpdatable: false, // Would need additional check\n }));\n\n },\n\n async listProcedures(db: Kysely<unknown>): Promise<ProcedureSummary[]> {\n\n const result = await sql<{\n proc_name: string;\n schema_name: string;\n param_count: number;\n }>`\n SELECT\n p.name as proc_name,\n s.name as schema_name,\n (\n SELECT COUNT(*)\n FROM sys.parameters pr\n WHERE pr.object_id = p.object_id\n AND pr.parameter_id > 0\n ) as param_count\n FROM sys.procedures p\n JOIN sys.schemas s ON p.schema_id = s.schema_id\n WHERE s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY s.name, p.name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.proc_name,\n schema: row.schema_name,\n parameterCount: row.param_count,\n }));\n\n },\n\n async listFunctions(db: Kysely<unknown>): Promise<FunctionSummary[]> {\n\n const result = await sql<{\n func_name: string;\n schema_name: string;\n param_count: number;\n return_type: string;\n }>`\n SELECT\n o.name as func_name,\n s.name as schema_name,\n (\n SELECT COUNT(*)\n FROM sys.parameters p\n WHERE p.object_id = o.object_id\n AND p.parameter_id > 0\n ) as param_count,\n CASE o.type\n WHEN 'FN' THEN 'scalar'\n WHEN 'IF' THEN 'inline table'\n WHEN 'TF' THEN 'table'\n ELSE 'unknown'\n END as return_type\n FROM sys.objects o\n JOIN sys.schemas s ON o.schema_id = s.schema_id\n WHERE o.type IN ('FN', 'IF', 'TF')\n AND s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY s.name, o.name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.func_name,\n schema: row.schema_name,\n parameterCount: row.param_count,\n returnType: row.return_type,\n }));\n\n },\n\n async listTypes(db: Kysely<unknown>): Promise<TypeSummary[]> {\n\n const result = await sql<{\n type_name: string;\n schema_name: string;\n is_table_type: boolean;\n }>`\n SELECT\n t.name as type_name,\n s.name as schema_name,\n t.is_table_type\n FROM sys.types t\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE t.is_user_defined = 1\n AND s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY s.name, t.name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.type_name,\n schema: row.schema_name,\n kind: row.is_table_type ? 'composite' : 'domain',\n }));\n\n },\n\n async listIndexes(db: Kysely<unknown>): Promise<IndexSummary[]> {\n\n const result = await sql<{\n index_name: string;\n schema_name: string;\n table_name: string;\n is_unique: boolean;\n is_primary_key: boolean;\n column_names: string;\n }>`\n SELECT\n i.name as index_name,\n s.name as schema_name,\n t.name as table_name,\n i.is_unique,\n i.is_primary_key,\n STRING_AGG(c.name, ', ') WITHIN GROUP (ORDER BY ic.key_ordinal) as column_names\n FROM sys.indexes i\n JOIN sys.tables t ON i.object_id = t.object_id\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id\n JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id\n WHERE i.name IS NOT NULL\n AND s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n GROUP BY i.name, s.name, t.name, i.is_unique, i.is_primary_key\n ORDER BY s.name, t.name, i.name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.index_name,\n schema: row.schema_name,\n tableName: row.table_name,\n tableSchema: row.schema_name,\n columns: row.column_names.split(', '),\n isUnique: row.is_unique,\n isPrimary: row.is_primary_key,\n }));\n\n },\n\n async listForeignKeys(db: Kysely<unknown>): Promise<ForeignKeySummary[]> {\n\n const result = await sql<{\n fk_name: string;\n schema_name: string;\n table_name: string;\n column_name: string;\n ref_schema: string;\n ref_table: string;\n ref_column: string;\n delete_action: string;\n update_action: string;\n }>`\n SELECT\n fk.name as fk_name,\n s.name as schema_name,\n t.name as table_name,\n c.name as column_name,\n rs.name as ref_schema,\n rt.name as ref_table,\n rc.name as ref_column,\n CASE fk.delete_referential_action\n WHEN 0 THEN 'NO ACTION'\n WHEN 1 THEN 'CASCADE'\n WHEN 2 THEN 'SET NULL'\n WHEN 3 THEN 'SET DEFAULT'\n END as delete_action,\n CASE fk.update_referential_action\n WHEN 0 THEN 'NO ACTION'\n WHEN 1 THEN 'CASCADE'\n WHEN 2 THEN 'SET NULL'\n WHEN 3 THEN 'SET DEFAULT'\n END as update_action\n FROM sys.foreign_keys fk\n JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id\n JOIN sys.tables t ON fk.parent_object_id = t.object_id\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n JOIN sys.columns c ON fkc.parent_object_id = c.object_id AND fkc.parent_column_id = c.column_id\n JOIN sys.tables rt ON fk.referenced_object_id = rt.object_id\n JOIN sys.schemas rs ON rt.schema_id = rs.schema_id\n JOIN sys.columns rc ON fkc.referenced_object_id = rc.object_id AND fkc.referenced_column_id = rc.column_id\n WHERE s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY s.name, t.name, fk.name, fkc.constraint_column_id\n `.execute(db);\n\n // Group by FK name\n const fkMap = new Map<string, ForeignKeySummary>();\n\n for (const row of result.rows) {\n\n const key = `${row.schema_name}.${row.fk_name}`;\n\n if (!fkMap.has(key)) {\n\n fkMap.set(key, {\n name: row.fk_name,\n schema: row.schema_name,\n tableName: row.table_name,\n tableSchema: row.schema_name,\n columns: [row.column_name],\n referencedTable: row.ref_table,\n referencedSchema: row.ref_schema,\n referencedColumns: [row.ref_column],\n onDelete: row.delete_action,\n onUpdate: row.update_action,\n });\n\n }\n else {\n\n const fk = fkMap.get(key)!;\n fk.columns.push(row.column_name);\n fk.referencedColumns.push(row.ref_column);\n\n }\n\n }\n\n return Array.from(fkMap.values());\n\n },\n\n async getTableDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'dbo',\n ): Promise<TableDetail | null> {\n\n // Get columns\n const columnsResult = await sql<{\n column_name: string;\n data_type: string;\n is_nullable: boolean;\n column_default: string | null;\n ordinal_position: number;\n is_identity: boolean;\n }>`\n SELECT\n c.name as column_name,\n TYPE_NAME(c.user_type_id) as data_type,\n c.is_nullable,\n OBJECT_DEFINITION(c.default_object_id) as column_default,\n c.column_id as ordinal_position,\n c.is_identity\n FROM sys.columns c\n JOIN sys.tables t ON c.object_id = t.object_id\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE t.name = ${name}\n AND s.name = ${schema}\n ORDER BY c.column_id\n `.execute(db);\n\n if (columnsResult.rows.length === 0) {\n\n return null;\n\n }\n\n // Get primary key columns\n const pkResult = await sql<{ column_name: string }>`\n SELECT c.name as column_name\n FROM sys.indexes i\n JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id\n JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id\n JOIN sys.tables t ON i.object_id = t.object_id\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE i.is_primary_key = 1\n AND t.name = ${name}\n AND s.name = ${schema}\n `.execute(db);\n\n const pkColumns = new Set(pkResult.rows.map((r) => r.column_name));\n\n // Get row count\n const rowResult = await sql<{ row_count: number }>`\n SELECT SUM(p.rows) as row_count\n FROM sys.partitions p\n JOIN sys.tables t ON p.object_id = t.object_id\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE p.index_id IN (0, 1)\n AND t.name = ${name}\n AND s.name = ${schema}\n `.execute(db);\n\n const columns: ColumnDetail[] = columnsResult.rows.map((row) => ({\n name: row.column_name,\n dataType: row.data_type,\n isNullable: row.is_nullable,\n defaultValue: row.column_default ?? undefined,\n isPrimaryKey: pkColumns.has(row.column_name),\n ordinalPosition: row.ordinal_position,\n }));\n\n // Get indexes\n const allIndexes = await this.listIndexes(db);\n const indexes = allIndexes.filter(\n (idx) => idx.tableName === name && idx.tableSchema === schema,\n );\n\n // Get foreign keys\n const allFks = await this.listForeignKeys(db);\n const foreignKeys = allFks.filter(\n (fk) => fk.tableName === name && fk.tableSchema === schema,\n );\n\n return {\n name,\n schema,\n columns,\n indexes,\n foreignKeys,\n rowCountEstimate: rowResult.rows[0]?.row_count ?? undefined,\n };\n\n },\n\n async getViewDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'dbo',\n ): Promise<ViewDetail | null> {\n\n // Check if view exists\n const viewCheck = await sql<{ object_id: number }>`\n SELECT v.object_id\n FROM sys.views v\n JOIN sys.schemas s ON v.schema_id = s.schema_id\n WHERE v.name = ${name}\n AND s.name = ${schema}\n `.execute(db);\n\n if (viewCheck.rows.length === 0) {\n\n return null;\n\n }\n\n // Get columns\n const columnsResult = await sql<{\n column_name: string;\n data_type: string;\n is_nullable: boolean;\n ordinal_position: number;\n }>`\n SELECT\n c.name as column_name,\n TYPE_NAME(c.user_type_id) as data_type,\n c.is_nullable,\n c.column_id as ordinal_position\n FROM sys.columns c\n JOIN sys.views v ON c.object_id = v.object_id\n JOIN sys.schemas s ON v.schema_id = s.schema_id\n WHERE v.name = ${name}\n AND s.name = ${schema}\n ORDER BY c.column_id\n `.execute(db);\n\n // Get view definition\n const defResult = await sql<{ definition: string | null }>`\n SELECT OBJECT_DEFINITION(OBJECT_ID(${schema + '.' + name})) as definition\n `.execute(db);\n\n const columns: ColumnDetail[] = columnsResult.rows.map((row) => ({\n name: row.column_name,\n dataType: row.data_type,\n isNullable: row.is_nullable,\n isPrimaryKey: false,\n ordinalPosition: row.ordinal_position,\n }));\n\n return {\n name,\n schema,\n columns,\n definition: defResult.rows[0]?.definition ?? undefined,\n isUpdatable: false,\n };\n\n },\n\n async getProcedureDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'dbo',\n ): Promise<ProcedureDetail | null> {\n\n // Check if procedure exists and get definition\n const procResult = await sql<{ definition: string | null }>`\n SELECT OBJECT_DEFINITION(p.object_id) as definition\n FROM sys.procedures p\n JOIN sys.schemas s ON p.schema_id = s.schema_id\n WHERE p.name = ${name}\n AND s.name = ${schema}\n `.execute(db);\n\n const procRow = procResult.rows[0];\n\n if (!procRow) {\n\n return null;\n\n }\n\n // Get parameters\n const paramsResult = await sql<{\n parameter_name: string;\n data_type: string;\n is_output: boolean;\n ordinal_position: number;\n has_default: boolean;\n }>`\n SELECT\n pr.name as parameter_name,\n TYPE_NAME(pr.user_type_id) as data_type,\n pr.is_output,\n pr.parameter_id as ordinal_position,\n pr.has_default_value as has_default\n FROM sys.parameters pr\n JOIN sys.procedures p ON pr.object_id = p.object_id\n JOIN sys.schemas s ON p.schema_id = s.schema_id\n WHERE p.name = ${name}\n AND s.name = ${schema}\n AND pr.parameter_id > 0\n ORDER BY pr.parameter_id\n `.execute(db);\n\n const parameters: ParameterDetail[] = paramsResult.rows.map((row) => ({\n name: row.parameter_name.replace(/^@/, ''),\n dataType: row.data_type,\n mode: row.is_output ? 'OUT' : 'IN',\n ordinalPosition: row.ordinal_position,\n }));\n\n return {\n name,\n schema,\n parameters,\n definition: procRow.definition ?? undefined,\n };\n\n },\n\n async getFunctionDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'dbo',\n ): Promise<FunctionDetail | null> {\n\n // Check if function exists and get definition\n const funcResult = await sql<{\n definition: string | null;\n func_type: string;\n }>`\n SELECT\n OBJECT_DEFINITION(o.object_id) as definition,\n o.type as func_type\n FROM sys.objects o\n JOIN sys.schemas s ON o.schema_id = s.schema_id\n WHERE o.name = ${name}\n AND s.name = ${schema}\n AND o.type IN ('FN', 'IF', 'TF')\n `.execute(db);\n\n const funcRow = funcResult.rows[0];\n\n if (!funcRow) {\n\n return null;\n\n }\n\n // Get parameters\n const paramsResult = await sql<{\n parameter_name: string;\n data_type: string;\n ordinal_position: number;\n }>`\n SELECT\n pr.name as parameter_name,\n TYPE_NAME(pr.user_type_id) as data_type,\n pr.parameter_id as ordinal_position\n FROM sys.parameters pr\n JOIN sys.objects o ON pr.object_id = o.object_id\n JOIN sys.schemas s ON o.schema_id = s.schema_id\n WHERE o.name = ${name}\n AND s.name = ${schema}\n AND pr.parameter_id > 0\n ORDER BY pr.parameter_id\n `.execute(db);\n\n const parameters: ParameterDetail[] = paramsResult.rows.map((row) => ({\n name: row.parameter_name.replace(/^@/, ''),\n dataType: row.data_type,\n mode: 'IN',\n ordinalPosition: row.ordinal_position,\n }));\n\n const returnType = funcRow.func_type === 'FN'\n ? 'scalar'\n : funcRow.func_type === 'IF'\n ? 'inline table'\n : 'table';\n\n return {\n name,\n schema,\n parameters,\n returnType,\n definition: funcRow.definition ?? undefined,\n };\n\n },\n\n async getTypeDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'dbo',\n ): Promise<TypeDetail | null> {\n\n const result = await sql<{\n is_table_type: boolean;\n base_type: string | null;\n }>`\n SELECT\n t.is_table_type,\n TYPE_NAME(t.system_type_id) as base_type\n FROM sys.types t\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE t.name = ${name}\n AND s.name = ${schema}\n AND t.is_user_defined = 1\n `.execute(db);\n\n const row = result.rows[0];\n\n if (!row) {\n\n return null;\n\n }\n\n let attributes: ColumnDetail[] | undefined;\n\n if (row.is_table_type) {\n\n // Get table type columns\n const colsResult = await sql<{\n column_name: string;\n data_type: string;\n is_nullable: boolean;\n ordinal_position: number;\n }>`\n SELECT\n c.name as column_name,\n TYPE_NAME(c.user_type_id) as data_type,\n c.is_nullable,\n c.column_id as ordinal_position\n FROM sys.table_types tt\n JOIN sys.columns c ON tt.type_table_object_id = c.object_id\n JOIN sys.schemas s ON tt.schema_id = s.schema_id\n WHERE tt.name = ${name}\n AND s.name = ${schema}\n ORDER BY c.column_id\n `.execute(db);\n\n attributes = colsResult.rows.map((r) => ({\n name: r.column_name,\n dataType: r.data_type,\n isNullable: r.is_nullable,\n isPrimaryKey: false,\n ordinalPosition: r.ordinal_position,\n }));\n\n }\n\n return {\n name,\n schema,\n kind: row.is_table_type ? 'composite' : 'domain',\n attributes,\n baseType: row.base_type ?? undefined,\n };\n\n },\n\n async listTriggers(db: Kysely<unknown>): Promise<TriggerSummary[]> {\n\n const result = await sql<{\n trigger_name: string;\n schema_name: string;\n table_name: string;\n is_instead_of_trigger: boolean;\n is_disabled: boolean;\n type_desc: string;\n }>`\n SELECT\n t.name AS trigger_name,\n s.name AS schema_name,\n OBJECT_NAME(t.parent_id) AS table_name,\n t.is_instead_of_trigger,\n t.is_disabled,\n te.type_desc\n FROM sys.triggers t\n INNER JOIN sys.trigger_events te ON t.object_id = te.object_id\n INNER JOIN sys.tables tab ON t.parent_id = tab.object_id\n INNER JOIN sys.schemas s ON tab.schema_id = s.schema_id\n WHERE s.name NOT IN (${sql.join(EXCLUDED_SCHEMAS)})\n ORDER BY s.name, table_name, t.name\n `.execute(db);\n\n // Group triggers by name\n const triggerMap = new Map<string, TriggerSummary>();\n\n for (const row of result.rows) {\n\n const key = `${row.schema_name}.${row.trigger_name}`;\n const event = row.type_desc as 'INSERT' | 'UPDATE' | 'DELETE';\n const existing = triggerMap.get(key);\n\n if (existing) {\n\n if (!existing.events.includes(event)) {\n\n existing.events.push(event);\n\n }\n\n }\n else {\n\n triggerMap.set(key, {\n name: row.trigger_name,\n schema: row.schema_name,\n tableName: row.table_name,\n tableSchema: row.schema_name,\n timing: row.is_instead_of_trigger ? 'INSTEAD OF' : 'AFTER',\n events: [event],\n });\n\n }\n\n }\n\n return Array.from(triggerMap.values());\n\n },\n\n async listLocks(db: Kysely<unknown>): Promise<LockSummary[]> {\n\n const result = await sql<{\n request_session_id: number;\n resource_type: string;\n resource_description: string;\n request_mode: string;\n request_status: string;\n }>`\n SELECT\n request_session_id,\n resource_type,\n resource_description,\n request_mode,\n request_status\n FROM sys.dm_tran_locks\n WHERE resource_database_id = DB_ID()\n ORDER BY request_session_id\n `.execute(db);\n\n return result.rows.map((row) => ({\n pid: row.request_session_id,\n lockType: row.resource_type,\n objectName: row.resource_description || undefined,\n mode: row.request_mode,\n granted: row.request_status === 'GRANT',\n }));\n\n },\n\n async listConnections(db: Kysely<unknown>): Promise<ConnectionSummary[]> {\n\n const result = await sql<{\n session_id: number;\n login_name: string;\n host_name: string;\n program_name: string;\n status: string;\n login_time: Date;\n }>`\n SELECT\n s.session_id,\n s.login_name,\n s.host_name,\n s.program_name,\n s.status,\n s.login_time\n FROM sys.dm_exec_sessions s\n WHERE s.database_id = DB_ID()\n AND s.session_id != @@SPID\n ORDER BY s.login_time DESC\n `.execute(db);\n\n return result.rows.map((row) => ({\n pid: row.session_id,\n username: row.login_name,\n database: 'current',\n applicationName: row.program_name || undefined,\n clientAddress: row.host_name || undefined,\n backendStart: row.login_time,\n state: row.status,\n }));\n\n },\n\n async getTriggerDetail(\n db: Kysely<unknown>,\n name: string,\n schema = 'dbo',\n ): Promise<TriggerDetail | null> {\n\n const result = await sql<{\n trigger_name: string;\n table_name: string;\n is_instead_of_trigger: boolean;\n is_disabled: boolean;\n definition: string;\n type_desc: string;\n }>`\n SELECT\n t.name AS trigger_name,\n OBJECT_NAME(t.parent_id) AS table_name,\n t.is_instead_of_trigger,\n t.is_disabled,\n OBJECT_DEFINITION(t.object_id) AS definition,\n te.type_desc\n FROM sys.triggers t\n INNER JOIN sys.trigger_events te ON t.object_id = te.object_id\n INNER JOIN sys.tables tab ON t.parent_id = tab.object_id\n INNER JOIN sys.schemas s ON tab.schema_id = s.schema_id\n WHERE t.name = ${name}\n AND s.name = ${schema}\n `.execute(db);\n\n if (result.rows.length === 0) {\n\n return null;\n\n }\n\n const events = [...new Set(result.rows.map((r) => r.type_desc))];\n const row = result.rows[0]!;\n\n return {\n name: row.trigger_name,\n schema,\n tableName: row.table_name,\n tableSchema: schema,\n timing: row.is_instead_of_trigger ? 'INSTEAD OF' : 'AFTER',\n events,\n definition: row.definition,\n isEnabled: !row.is_disabled,\n };\n\n },\n\n};\n","/**\n * SQLite schema exploration operations.\n *\n * Queries SQLite system tables (sqlite_master) and PRAGMAs\n * to retrieve database object metadata.\n */\nimport { sql } from 'kysely';\n\nimport type { Kysely } from 'kysely';\nimport type {\n DialectExploreOperations,\n ExploreOverview,\n TableSummary,\n ViewSummary,\n ProcedureSummary,\n FunctionSummary,\n TypeSummary,\n IndexSummary,\n ForeignKeySummary,\n TriggerSummary,\n LockSummary,\n ConnectionSummary,\n TableDetail,\n ViewDetail,\n ProcedureDetail,\n FunctionDetail,\n TypeDetail,\n TriggerDetail,\n ColumnDetail,\n} from '../types.js';\n\n/**\n * SQLite explore operations.\n *\n * Note: SQLite has limited metadata compared to other databases:\n * - No stored procedures or functions\n * - No custom types\n * - No schemas (single schema per database)\n */\nexport const sqliteExploreOperations: DialectExploreOperations = {\n\n async getOverview(db: Kysely<unknown>): Promise<ExploreOverview> {\n\n const [tables, views, indexes] = await Promise.all([\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sqlite_master\n WHERE type = 'table'\n AND name NOT LIKE 'sqlite_%'\n `.execute(db),\n\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sqlite_master\n WHERE type = 'view'\n `.execute(db),\n\n sql<{ count: number }>`\n SELECT COUNT(*) as count\n FROM sqlite_master\n WHERE type = 'index'\n AND name NOT LIKE 'sqlite_%'\n `.execute(db),\n ]);\n\n // Count foreign keys by parsing all tables\n const tablesResult = await sql<{ name: string }>`\n SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'\n `.execute(db);\n\n let fkCount = 0;\n\n for (const table of tablesResult.rows) {\n\n const fks = await sql<{ id: number }>`\n PRAGMA foreign_key_list(${sql.raw(`\"${table.name}\"`)})\n `.execute(db);\n\n // Count unique FK ids\n const uniqueIds = new Set(fks.rows.map((r) => r.id));\n fkCount += uniqueIds.size;\n\n }\n\n return {\n tables: tables.rows[0]?.count ?? 0,\n views: views.rows[0]?.count ?? 0,\n procedures: 0, // SQLite doesn't support stored procedures\n functions: 0, // SQLite doesn't support user-defined functions via SQL\n types: 0, // SQLite doesn't support custom types\n indexes: indexes.rows[0]?.count ?? 0,\n foreignKeys: fkCount,\n triggers: 0, // TODO: implement count\n locks: 0, // SQLite doesn't expose lock information\n connections: 0, // SQLite doesn't have connection tracking\n };\n\n },\n\n async listTables(db: Kysely<unknown>): Promise<TableSummary[]> {\n\n const result = await sql<{ name: string }>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name NOT LIKE 'sqlite_%'\n ORDER BY name\n `.execute(db);\n\n const tables: TableSummary[] = [];\n\n for (const row of result.rows) {\n\n // Get column count\n const colsResult = await sql<{ cid: number }>`\n PRAGMA table_info(${sql.raw(`\"${row.name}\"`)})\n `.execute(db);\n\n // Get row count estimate\n const countResult = await sql<{ count: number }>`\n SELECT COUNT(*) as count FROM ${sql.raw(`\"${row.name}\"`)}\n `.execute(db);\n\n tables.push({\n name: row.name,\n columnCount: colsResult.rows.length,\n rowCountEstimate: countResult.rows[0]?.count,\n });\n\n }\n\n return tables;\n\n },\n\n async listViews(db: Kysely<unknown>): Promise<ViewSummary[]> {\n\n const result = await sql<{ name: string }>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'view'\n ORDER BY name\n `.execute(db);\n\n const views: ViewSummary[] = [];\n\n for (const row of result.rows) {\n\n // Get column count by querying the view\n const colsResult = await sql<{ cid: number }>`\n PRAGMA table_info(${sql.raw(`\"${row.name}\"`)})\n `.execute(db);\n\n views.push({\n name: row.name,\n columnCount: colsResult.rows.length,\n isUpdatable: false, // SQLite views are generally not updatable\n });\n\n }\n\n return views;\n\n },\n\n async listProcedures(_db: Kysely<unknown>): Promise<ProcedureSummary[]> {\n\n // SQLite doesn't support stored procedures\n return [];\n\n },\n\n async listFunctions(_db: Kysely<unknown>): Promise<FunctionSummary[]> {\n\n // SQLite doesn't support user-defined functions via SQL\n return [];\n\n },\n\n async listTypes(_db: Kysely<unknown>): Promise<TypeSummary[]> {\n\n // SQLite doesn't support custom types\n return [];\n\n },\n\n async listIndexes(db: Kysely<unknown>): Promise<IndexSummary[]> {\n\n const result = await sql<{\n name: string;\n tbl_name: string;\n sql: string | null;\n }>`\n SELECT name, tbl_name, sql\n FROM sqlite_master\n WHERE type = 'index'\n AND name NOT LIKE 'sqlite_%'\n ORDER BY tbl_name, name\n `.execute(db);\n\n const indexes: IndexSummary[] = [];\n\n for (const row of result.rows) {\n\n // Get index info\n const infoResult = await sql<{\n seqno: number;\n cid: number;\n name: string;\n }>`\n PRAGMA index_info(${sql.raw(`\"${row.name}\"`)})\n `.execute(db);\n\n const columns = infoResult.rows.map((r) => r.name);\n const isUnique = row.sql?.toUpperCase().includes('UNIQUE') ?? false;\n const isPrimary = row.name.startsWith('sqlite_autoindex_');\n\n indexes.push({\n name: row.name,\n tableName: row.tbl_name,\n columns,\n isUnique: isUnique || isPrimary,\n isPrimary,\n });\n\n }\n\n return indexes;\n\n },\n\n async listForeignKeys(db: Kysely<unknown>): Promise<ForeignKeySummary[]> {\n\n const tablesResult = await sql<{ name: string }>`\n SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'\n `.execute(db);\n\n const foreignKeys: ForeignKeySummary[] = [];\n\n for (const table of tablesResult.rows) {\n\n const fksResult = await sql<{\n id: number;\n seq: number;\n table: string;\n from: string;\n to: string;\n on_update: string;\n on_delete: string;\n }>`\n PRAGMA foreign_key_list(${sql.raw(`\"${table.name}\"`)})\n `.execute(db);\n\n // Group by FK id\n const fkMap = new Map<number, ForeignKeySummary>();\n\n for (const row of fksResult.rows) {\n\n if (!fkMap.has(row.id)) {\n\n fkMap.set(row.id, {\n name: `fk_${table.name}_${row.id}`,\n tableName: table.name,\n columns: [row.from],\n referencedTable: row.table,\n referencedColumns: [row.to],\n onUpdate: row.on_update,\n onDelete: row.on_delete,\n });\n\n }\n else {\n\n const fk = fkMap.get(row.id)!;\n fk.columns.push(row.from);\n fk.referencedColumns.push(row.to);\n\n }\n\n }\n\n foreignKeys.push(...fkMap.values());\n\n }\n\n return foreignKeys;\n\n },\n\n async getTableDetail(\n db: Kysely<unknown>,\n name: string,\n _schema?: string,\n ): Promise<TableDetail | null> {\n\n // Check if table exists\n const tableCheck = await sql<{ name: string }>`\n SELECT name FROM sqlite_master WHERE type = 'table' AND name = ${name}\n `.execute(db);\n\n if (tableCheck.rows.length === 0) {\n\n return null;\n\n }\n\n // Get columns\n const colsResult = await sql<{\n cid: number;\n name: string;\n type: string;\n notnull: number;\n dflt_value: string | null;\n pk: number;\n }>`\n PRAGMA table_info(${sql.raw(`\"${name}\"`)})\n `.execute(db);\n\n const columns: ColumnDetail[] = colsResult.rows.map((row) => ({\n name: row.name,\n dataType: row.type || 'ANY',\n isNullable: row.notnull === 0,\n defaultValue: row.dflt_value ?? undefined,\n isPrimaryKey: row.pk > 0,\n ordinalPosition: row.cid + 1,\n }));\n\n // Get row count\n const countResult = await sql<{ count: number }>`\n SELECT COUNT(*) as count FROM ${sql.raw(`\"${name}\"`)}\n `.execute(db);\n\n // Get indexes for this table\n const allIndexes = await this.listIndexes(db);\n const indexes = allIndexes.filter((idx) => idx.tableName === name);\n\n // Get foreign keys for this table\n const allFks = await this.listForeignKeys(db);\n const foreignKeys = allFks.filter((fk) => fk.tableName === name);\n\n return {\n name,\n columns,\n indexes,\n foreignKeys,\n rowCountEstimate: countResult.rows[0]?.count,\n };\n\n },\n\n async getViewDetail(\n db: Kysely<unknown>,\n name: string,\n _schema?: string,\n ): Promise<ViewDetail | null> {\n\n // Check if view exists and get definition\n const viewResult = await sql<{ sql: string | null }>`\n SELECT sql FROM sqlite_master WHERE type = 'view' AND name = ${name}\n `.execute(db);\n\n const viewRow = viewResult.rows[0];\n\n if (!viewRow) {\n\n return null;\n\n }\n\n // Get columns\n const colsResult = await sql<{\n cid: number;\n name: string;\n type: string;\n notnull: number;\n dflt_value: string | null;\n }>`\n PRAGMA table_info(${sql.raw(`\"${name}\"`)})\n `.execute(db);\n\n const columns: ColumnDetail[] = colsResult.rows.map((row) => ({\n name: row.name,\n dataType: row.type || 'ANY',\n isNullable: row.notnull === 0,\n defaultValue: row.dflt_value ?? undefined,\n isPrimaryKey: false,\n ordinalPosition: row.cid + 1,\n }));\n\n return {\n name,\n columns,\n definition: viewRow.sql ?? undefined,\n isUpdatable: false,\n };\n\n },\n\n async getProcedureDetail(\n _db: Kysely<unknown>,\n _name: string,\n _schema?: string,\n ): Promise<ProcedureDetail | null> {\n\n // SQLite doesn't support stored procedures\n return null;\n\n },\n\n async getFunctionDetail(\n _db: Kysely<unknown>,\n _name: string,\n _schema?: string,\n ): Promise<FunctionDetail | null> {\n\n // SQLite doesn't support user-defined functions via SQL\n return null;\n\n },\n\n async getTypeDetail(\n _db: Kysely<unknown>,\n _name: string,\n _schema?: string,\n ): Promise<TypeDetail | null> {\n\n // SQLite doesn't support custom types\n return null;\n\n },\n\n async listTriggers(db: Kysely<unknown>): Promise<TriggerSummary[]> {\n\n const result = await sql<{\n name: string;\n tbl_name: string;\n sql: string;\n }>`\n SELECT name, tbl_name, sql\n FROM sqlite_master\n WHERE type = 'trigger'\n ORDER BY tbl_name, name\n `.execute(db);\n\n return result.rows.map((row) => {\n\n // Parse timing and events from SQL\n const sqlUpper = row.sql.toUpperCase();\n let timing: 'BEFORE' | 'AFTER' | 'INSTEAD OF' = 'AFTER';\n\n if (sqlUpper.includes('BEFORE')) {\n\n timing = 'BEFORE';\n\n }\n else if (sqlUpper.includes('INSTEAD OF')) {\n\n timing = 'INSTEAD OF';\n\n }\n\n const events: ('INSERT' | 'UPDATE' | 'DELETE')[] = [];\n\n if (sqlUpper.includes('INSERT')) {\n\n events.push('INSERT');\n\n }\n\n if (sqlUpper.includes('UPDATE')) {\n\n events.push('UPDATE');\n\n }\n\n if (sqlUpper.includes('DELETE')) {\n\n events.push('DELETE');\n\n }\n\n return {\n name: row.name,\n tableName: row.tbl_name,\n timing,\n events: events.length > 0 ? events : ['INSERT'],\n };\n\n });\n\n },\n\n async listLocks(_db: Kysely<unknown>): Promise<LockSummary[]> {\n\n // SQLite doesn't expose lock information via SQL\n return [];\n\n },\n\n async listConnections(_db: Kysely<unknown>): Promise<ConnectionSummary[]> {\n\n // SQLite doesn't have connection tracking (single-user database)\n return [];\n\n },\n\n async getTriggerDetail(\n db: Kysely<unknown>,\n name: string,\n ): Promise<TriggerDetail | null> {\n\n const result = await sql<{\n name: string;\n tbl_name: string;\n sql: string;\n }>`\n SELECT name, tbl_name, sql\n FROM sqlite_master\n WHERE type = 'trigger'\n AND name = ${name}\n `.execute(db);\n\n if (result.rows.length === 0) {\n\n return null;\n\n }\n\n const row = result.rows[0]!;\n\n const sqlUpper = row.sql.toUpperCase();\n let timing = 'AFTER';\n\n if (sqlUpper.includes('BEFORE')) {\n\n timing = 'BEFORE';\n\n }\n else if (sqlUpper.includes('INSTEAD OF')) {\n\n timing = 'INSTEAD OF';\n\n }\n\n const events: string[] = [];\n\n if (sqlUpper.includes('INSERT')) {\n\n events.push('INSERT');\n\n }\n\n if (sqlUpper.includes('UPDATE')) {\n\n events.push('UPDATE');\n\n }\n\n if (sqlUpper.includes('DELETE')) {\n\n events.push('DELETE');\n\n }\n\n return {\n name: row.name,\n tableName: row.tbl_name,\n timing,\n events: events.length > 0 ? events : ['INSERT'],\n definition: row.sql,\n isEnabled: true, // SQLite triggers are always enabled\n };\n\n },\n\n};\n","/**\n * Dialect factory for explore operations.\n *\n * Returns the appropriate explore operations implementation\n * based on the database dialect.\n */\nimport type { Dialect } from '../../connection/types.js';\nimport type { DialectExploreOperations } from '../types.js';\n\nimport { postgresExploreOperations } from './postgres.js';\nimport { mysqlExploreOperations } from './mysql.js';\nimport { mssqlExploreOperations } from './mssql.js';\nimport { sqliteExploreOperations } from './sqlite.js';\n\n/**\n * Dialect-to-operations mapping.\n */\nconst dialectOperations: Record<Dialect, DialectExploreOperations> = {\n postgres: postgresExploreOperations,\n mysql: mysqlExploreOperations,\n mssql: mssqlExploreOperations,\n sqlite: sqliteExploreOperations,\n};\n\n/**\n * Get explore operations for a specific dialect.\n *\n * @param dialect - The database dialect\n * @returns Dialect-specific explore operations\n *\n * @example\n * ```typescript\n * const ops = getExploreOperations('postgres')\n * const overview = await ops.getOverview(db)\n * ```\n */\nexport function getExploreOperations(dialect: Dialect): DialectExploreOperations {\n\n return dialectOperations[dialect];\n\n}\n\nexport {\n postgresExploreOperations,\n mysqlExploreOperations,\n mssqlExploreOperations,\n sqliteExploreOperations,\n};\n","/**\n * Database schema exploration operations.\n *\n * High-level API for exploring database schema metadata.\n * Delegates to dialect-specific implementations.\n */\nimport { attempt } from '@logosdx/utils';\n\nimport type { Kysely } from 'kysely';\nimport type { Dialect } from '../connection/types.js';\nimport type {\n ExploreCategory,\n ExploreOverview,\n TableSummary,\n ViewSummary,\n ProcedureSummary,\n FunctionSummary,\n TypeSummary,\n IndexSummary,\n ForeignKeySummary,\n TriggerSummary,\n LockSummary,\n ConnectionSummary,\n TableDetail,\n ViewDetail,\n ProcedureDetail,\n FunctionDetail,\n TypeDetail,\n TriggerDetail,\n} from './types.js';\nimport { getExploreOperations } from './dialects/index.js';\nimport { observer } from '../observer.js';\n\n/**\n * Options for explore operations.\n */\nexport interface ExploreOptions {\n\n /** Include noorm internal tables (__noorm_*). Default: false */\n includeNoormTables?: boolean;\n\n}\n\n/**\n * Check if a name is a noorm internal table.\n */\nfunction isNoormTable(name: string | undefined | null): boolean {\n\n return name?.startsWith('__noorm_') ?? false;\n\n}\n\n/**\n * Fetch overview counts for all object categories.\n *\n * @param db - Kysely database instance\n * @param dialect - Database dialect\n * @param options - Explore options\n * @returns Overview with counts for each category\n *\n * @example\n * ```typescript\n * const overview = await fetchOverview(db, 'postgres')\n * console.log(`Tables: ${overview.tables}`)\n * ```\n */\nexport async function fetchOverview(\n db: Kysely<unknown>,\n dialect: Dialect,\n options: ExploreOptions = {},\n): Promise<ExploreOverview> {\n\n const ops = getExploreOperations(dialect);\n\n // If excluding noorm tables, we need to fetch lists and count manually\n if (!options.includeNoormTables) {\n\n const [tables, views, procedures, functions, types, indexes, foreignKeys, triggers, locks, connections] =\n await Promise.all([\n ops.listTables(db),\n ops.listViews(db),\n ops.listProcedures(db),\n ops.listFunctions(db),\n ops.listTypes(db),\n ops.listIndexes(db),\n ops.listForeignKeys(db),\n ops.listTriggers(db),\n ops.listLocks(db),\n ops.listConnections(db),\n ]);\n\n return {\n tables: tables.filter((t) => !isNoormTable(t.name)).length,\n views: views.length,\n procedures: procedures.length,\n functions: functions.length,\n types: types.length,\n indexes: indexes.filter((i) => !isNoormTable(i.tableName)).length,\n foreignKeys: foreignKeys.filter((fk) => !isNoormTable(fk.tableName)).length,\n triggers: triggers.filter((t) => !isNoormTable(t.tableName)).length,\n locks: locks.length,\n connections: connections.length,\n };\n\n }\n\n const [result, err] = await attempt(() => ops.getOverview(db));\n\n if (err) {\n\n observer.emit('error', { source: 'explore', error: err });\n throw err;\n\n }\n\n return result;\n\n}\n\n/**\n * Category to list method mapping.\n */\ntype ListMethodMap = {\n tables: TableSummary[];\n views: ViewSummary[];\n procedures: ProcedureSummary[];\n functions: FunctionSummary[];\n types: TypeSummary[];\n indexes: IndexSummary[];\n foreignKeys: ForeignKeySummary[];\n triggers: TriggerSummary[];\n locks: LockSummary[];\n connections: ConnectionSummary[];\n};\n\n/**\n * Fetch list of items for a category.\n *\n * @param db - Kysely database instance\n * @param dialect - Database dialect\n * @param category - Object category to list\n * @param options - Explore options\n * @returns Array of summary items\n *\n * @example\n * ```typescript\n * const tables = await fetchList(db, 'postgres', 'tables')\n * for (const table of tables) {\n * console.log(`${table.name}: ${table.columnCount} columns`)\n * }\n * ```\n */\nexport async function fetchList<C extends ExploreCategory>(\n db: Kysely<unknown>,\n dialect: Dialect,\n category: C,\n options: ExploreOptions = {},\n): Promise<ListMethodMap[C]> {\n\n const ops = getExploreOperations(dialect);\n\n const methodMap: Record<ExploreCategory, () => Promise<unknown>> = {\n tables: () => ops.listTables(db),\n views: () => ops.listViews(db),\n procedures: () => ops.listProcedures(db),\n functions: () => ops.listFunctions(db),\n types: () => ops.listTypes(db),\n indexes: () => ops.listIndexes(db),\n foreignKeys: () => ops.listForeignKeys(db),\n triggers: () => ops.listTriggers(db),\n locks: () => ops.listLocks(db),\n connections: () => ops.listConnections(db),\n };\n\n const [result, err] = await attempt(() => methodMap[category]());\n\n if (err) {\n\n observer.emit('error', { source: 'explore', error: err });\n throw err;\n\n }\n\n // Filter out noorm tables unless explicitly included\n if (!options.includeNoormTables) {\n\n if (category === 'tables') {\n\n return (result as TableSummary[]).filter(\n (t) => !isNoormTable(t.name),\n ) as ListMethodMap[C];\n\n }\n\n if (category === 'indexes') {\n\n return (result as IndexSummary[]).filter(\n (i) => !isNoormTable(i.tableName),\n ) as ListMethodMap[C];\n\n }\n\n if (category === 'foreignKeys') {\n\n return (result as ForeignKeySummary[]).filter(\n (fk) => !isNoormTable(fk.tableName),\n ) as ListMethodMap[C];\n\n }\n\n if (category === 'triggers') {\n\n return (result as TriggerSummary[]).filter(\n (t) => !isNoormTable(t.tableName),\n ) as ListMethodMap[C];\n\n }\n\n }\n\n return result as ListMethodMap[C];\n\n}\n\n/**\n * Category to detail type mapping.\n */\ntype DetailTypeMap = {\n tables: TableDetail;\n views: ViewDetail;\n procedures: ProcedureDetail;\n functions: FunctionDetail;\n types: TypeDetail;\n triggers: TriggerDetail;\n};\n\n/**\n * Categories that support detail views.\n */\nexport type DetailCategory = keyof DetailTypeMap;\n\n/**\n * Fetch full detail for a specific object.\n *\n * @param db - Kysely database instance\n * @param dialect - Database dialect\n * @param category - Object category\n * @param name - Object name\n * @param schema - Optional schema name\n * @returns Full detail or null if not found\n *\n * @example\n * ```typescript\n * const table = await fetchDetail(db, 'postgres', 'tables', 'users', 'public')\n * if (table) {\n * for (const col of table.columns) {\n * console.log(`${col.name}: ${col.dataType}`)\n * }\n * }\n * ```\n */\nexport async function fetchDetail<C extends DetailCategory>(\n db: Kysely<unknown>,\n dialect: Dialect,\n category: C,\n name: string,\n schema?: string,\n): Promise<DetailTypeMap[C] | null> {\n\n const ops = getExploreOperations(dialect);\n\n const methodMap: Record<DetailCategory, () => Promise<unknown>> = {\n tables: () => ops.getTableDetail(db, name, schema),\n views: () => ops.getViewDetail(db, name, schema),\n procedures: () => ops.getProcedureDetail(db, name, schema),\n functions: () => ops.getFunctionDetail(db, name, schema),\n types: () => ops.getTypeDetail(db, name, schema),\n triggers: () => ops.getTriggerDetail(db, name, schema),\n };\n\n const [result, err] = await attempt(() => methodMap[category]());\n\n if (err) {\n\n observer.emit('error', { source: 'explore', error: err });\n throw err;\n\n }\n\n return result as DetailTypeMap[C] | null;\n\n}\n\n/**\n * Format a summary description for list display.\n *\n * @param category - Object category\n * @param item - Summary item\n * @returns Formatted description string\n */\nexport function formatSummaryDescription(\n category: ExploreCategory | string,\n item: unknown,\n): string {\n\n switch (category) {\n\n case 'tables': {\n\n const t = item as TableSummary;\n const parts = [`${t.columnCount} columns`];\n\n if (t.rowCountEstimate !== undefined) {\n\n parts.push(`~${formatNumber(t.rowCountEstimate)} rows`);\n\n }\n\n return parts.join(', ');\n\n }\n\n case 'views': {\n\n const v = item as ViewSummary;\n\n return `${v.columnCount} columns${v.isUpdatable ? ', updatable' : ''}`;\n\n }\n\n case 'procedures': {\n\n const p = item as ProcedureSummary;\n\n return `${p.parameterCount} parameters`;\n\n }\n\n case 'functions': {\n\n const f = item as FunctionSummary;\n\n return `${f.parameterCount} params → ${f.returnType}`;\n\n }\n\n case 'types': {\n\n const t = item as TypeSummary;\n\n if (t.kind === 'enum' && t.valueCount !== undefined) {\n\n return `enum (${t.valueCount} values)`;\n\n }\n\n return t.kind;\n\n }\n\n case 'indexes': {\n\n const i = item as IndexSummary;\n const parts = [`on ${i.tableName}`];\n\n if (i.isPrimary) {\n\n parts.push('PRIMARY');\n\n }\n else if (i.isUnique) {\n\n parts.push('UNIQUE');\n\n }\n\n return parts.join(', ');\n\n }\n\n case 'foreignKeys': {\n\n const fk = item as ForeignKeySummary;\n\n return `${fk.tableName} → ${fk.referencedTable}`;\n\n }\n\n case 'triggers': {\n\n const t = item as TriggerSummary;\n\n return `${t.timing} ${t.events.join('/')} on ${t.tableName}`;\n\n }\n\n case 'locks': {\n\n const l = item as LockSummary;\n\n return `${l.lockType} ${l.mode}${l.objectName ? ` on ${l.objectName}` : ''}${l.granted ? '' : ' (waiting)'}`;\n\n }\n\n case 'connections': {\n\n const c = item as ConnectionSummary;\n\n return `${c.username}@${c.database} (${c.state})`;\n\n }\n\n default:\n return '';\n\n }\n\n}\n\n/**\n * Format a number with thousands separators.\n */\nfunction formatNumber(n: number): string {\n\n if (n >= 1_000_000) {\n\n return `${(n / 1_000_000).toFixed(1)}M`;\n\n }\n\n if (n >= 1_000) {\n\n return `${(n / 1_000).toFixed(1)}K`;\n\n }\n\n return n.toString();\n\n}\n","/**\n * PostgreSQL Teardown Dialect\n *\n * PostgreSQL-specific SQL generation for teardown operations.\n */\nimport type { TeardownDialectOperations } from '../types.js';\n\n/**\n * Quote a PostgreSQL identifier.\n */\nfunction quote(name: string): string {\n\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n\n}\n\n/**\n * Build fully qualified name with optional schema.\n */\nfunction qualifiedName(name: string, schema?: string): string {\n\n if (schema && schema !== 'public') {\n\n return `${quote(schema)}.${quote(name)}`;\n\n }\n\n return quote(name);\n\n}\n\n/**\n * PostgreSQL teardown operations.\n */\nexport const postgresTeardownOperations: TeardownDialectOperations = {\n\n disableForeignKeyChecks(): string {\n\n // Session-level setting that disables FK triggers\n return 'SET session_replication_role = \\'replica\\'';\n\n },\n\n enableForeignKeyChecks(): string {\n\n return 'SET session_replication_role = \\'origin\\'';\n\n },\n\n truncateTable(tableName: string, schema?: string, restartIdentity = true): string {\n\n const fullName = qualifiedName(tableName, schema);\n const restart = restartIdentity ? ' RESTART IDENTITY' : '';\n\n // CASCADE is needed to truncate tables with FK dependencies\n return `TRUNCATE TABLE ${fullName}${restart} CASCADE`;\n\n },\n\n dropTable(tableName: string, schema?: string): string {\n\n return `DROP TABLE IF EXISTS ${qualifiedName(tableName, schema)} CASCADE`;\n\n },\n\n dropView(viewName: string, schema?: string): string {\n\n return `DROP VIEW IF EXISTS ${qualifiedName(viewName, schema)} CASCADE`;\n\n },\n\n dropFunction(name: string, schema?: string): string {\n\n // PostgreSQL functions may have overloads, CASCADE drops all\n return `DROP FUNCTION IF EXISTS ${qualifiedName(name, schema)} CASCADE`;\n\n },\n\n dropProcedure(name: string, schema?: string): string {\n\n // PostgreSQL procedures (introduced in v11)\n return `DROP PROCEDURE IF EXISTS ${qualifiedName(name, schema)} CASCADE`;\n\n },\n\n dropType(typeName: string, schema?: string): string {\n\n return `DROP TYPE IF EXISTS ${qualifiedName(typeName, schema)} CASCADE`;\n\n },\n\n dropForeignKey(constraintName: string, tableName: string, schema?: string): string {\n\n return `ALTER TABLE ${qualifiedName(tableName, schema)} DROP CONSTRAINT IF EXISTS ${quote(constraintName)}`;\n\n },\n\n};\n","/**\n * MySQL Teardown Dialect\n *\n * MySQL-specific SQL generation for teardown operations.\n */\nimport type { TeardownDialectOperations } from '../types.js';\n\n/**\n * Quote a MySQL identifier.\n */\nfunction quote(name: string): string {\n\n return `\\`${name.replace(/`/g, '``')}\\``;\n\n}\n\n/**\n * Build fully qualified name with optional schema.\n * MySQL uses database instead of schema.\n */\nfunction qualifiedName(name: string, schema?: string): string {\n\n if (schema) {\n\n return `${quote(schema)}.${quote(name)}`;\n\n }\n\n return quote(name);\n\n}\n\n/**\n * MySQL teardown operations.\n */\nexport const mysqlTeardownOperations: TeardownDialectOperations = {\n\n disableForeignKeyChecks(): string {\n\n return 'SET FOREIGN_KEY_CHECKS = 0';\n\n },\n\n enableForeignKeyChecks(): string {\n\n return 'SET FOREIGN_KEY_CHECKS = 1';\n\n },\n\n truncateTable(tableName: string, schema?: string, _restartIdentity = true): string {\n\n // MySQL TRUNCATE always resets AUTO_INCREMENT\n return `TRUNCATE TABLE ${qualifiedName(tableName, schema)}`;\n\n },\n\n dropTable(tableName: string, schema?: string): string {\n\n return `DROP TABLE IF EXISTS ${qualifiedName(tableName, schema)}`;\n\n },\n\n dropView(viewName: string, schema?: string): string {\n\n return `DROP VIEW IF EXISTS ${qualifiedName(viewName, schema)}`;\n\n },\n\n dropFunction(name: string, schema?: string): string {\n\n // MySQL user-defined functions\n return `DROP FUNCTION IF EXISTS ${qualifiedName(name, schema)}`;\n\n },\n\n dropProcedure(name: string, schema?: string): string {\n\n // MySQL stored procedures\n return `DROP PROCEDURE IF EXISTS ${qualifiedName(name, schema)}`;\n\n },\n\n dropType(_typeName: string, _schema?: string): string {\n\n // MySQL doesn't support custom types\n return '-- MySQL does not support custom types';\n\n },\n\n dropForeignKey(constraintName: string, tableName: string, schema?: string): string {\n\n return `ALTER TABLE ${qualifiedName(tableName, schema)} DROP FOREIGN KEY ${quote(constraintName)}`;\n\n },\n\n};\n","/**\n * MSSQL Teardown Dialect\n *\n * Microsoft SQL Server-specific SQL generation for teardown operations.\n */\nimport type { TeardownDialectOperations } from '../types.js';\n\n/**\n * Quote a MSSQL identifier.\n */\nfunction quote(name: string): string {\n\n return `[${name.replace(/\\]/g, ']]')}]`;\n\n}\n\n/**\n * Build fully qualified name with optional schema.\n */\nfunction qualifiedName(name: string, schema?: string): string {\n\n if (schema && schema !== 'dbo') {\n\n return `${quote(schema)}.${quote(name)}`;\n\n }\n\n return quote(name);\n\n}\n\n/**\n * MSSQL teardown operations.\n *\n * MSSQL doesn't have a session-level FK disable like PostgreSQL or MySQL.\n * We have to explicitly drop FK constraints first.\n */\nexport const mssqlTeardownOperations: TeardownDialectOperations = {\n\n disableForeignKeyChecks(): string {\n\n // MSSQL uses NOCHECK per-table, but we'll use sp_MSforeachtable\n // for a session-wide effect during teardown\n return 'EXEC sp_MSforeachtable \\'ALTER TABLE ? NOCHECK CONSTRAINT ALL\\'';\n\n },\n\n enableForeignKeyChecks(): string {\n\n return 'EXEC sp_MSforeachtable \\'ALTER TABLE ? CHECK CONSTRAINT ALL\\'';\n\n },\n\n truncateTable(tableName: string, schema?: string, restartIdentity = true): string {\n\n // MSSQL TRUNCATE cannot be used on tables referenced by FK constraints\n // even with NOCHECK CONSTRAINT. Use DELETE instead.\n const qualified = qualifiedName(tableName, schema);\n const deleteStmt = `DELETE FROM ${qualified}`;\n\n // If restarting identity, also reset the seed\n if (restartIdentity) {\n\n // DBCC CHECKIDENT resets identity; IF EXISTS check prevents error if no identity column\n // Use schemaName.tableName format for DBCC (without brackets)\n const dbccName = schema && schema !== 'dbo'\n ? `${schema}.${tableName}`\n : tableName;\n\n // eslint-disable-next-line max-len\n return `${deleteStmt}; IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(object_id) = '${tableName}') DBCC CHECKIDENT ('${dbccName}', RESEED, 0)`;\n\n }\n\n return deleteStmt;\n\n },\n\n dropTable(tableName: string, schema?: string): string {\n\n return `DROP TABLE IF EXISTS ${qualifiedName(tableName, schema)}`;\n\n },\n\n dropView(viewName: string, schema?: string): string {\n\n return `DROP VIEW IF EXISTS ${qualifiedName(viewName, schema)}`;\n\n },\n\n dropFunction(name: string, schema?: string): string {\n\n // MSSQL functions (FN=scalar, IF=inline table, TF=table-valued)\n return `DROP FUNCTION IF EXISTS ${qualifiedName(name, schema)}`;\n\n },\n\n dropProcedure(name: string, schema?: string): string {\n\n // MSSQL stored procedures\n return `DROP PROCEDURE IF EXISTS ${qualifiedName(name, schema)}`;\n\n },\n\n dropType(typeName: string, schema?: string): string {\n\n return `DROP TYPE IF EXISTS ${qualifiedName(typeName, schema)}`;\n\n },\n\n dropForeignKey(constraintName: string, tableName: string, schema?: string): string {\n\n return `ALTER TABLE ${qualifiedName(tableName, schema)} DROP CONSTRAINT ${quote(constraintName)}`;\n\n },\n\n};\n","/**\n * SQLite Teardown Dialect\n *\n * SQLite-specific SQL generation for teardown operations.\n */\nimport type { TeardownDialectOperations } from '../types.js';\n\n/**\n * Quote a SQLite identifier with double quotes.\n */\nfunction quote(name: string): string {\n\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n\n}\n\n/**\n * SQLite teardown operations.\n *\n * SQLite has limited DDL compared to other databases:\n * - No TRUNCATE statement (use DELETE)\n * - No stored procedures\n * - No custom types\n * - No schemas (single namespace)\n */\nexport const sqliteTeardownOperations: TeardownDialectOperations = {\n\n disableForeignKeyChecks(): string {\n\n return 'PRAGMA foreign_keys = OFF';\n\n },\n\n enableForeignKeyChecks(): string {\n\n return 'PRAGMA foreign_keys = ON';\n\n },\n\n truncateTable(tableName: string, _schema?: string, _restartIdentity = false): string {\n\n // SQLite doesn't have TRUNCATE, use DELETE\n // Note: restartIdentity is ignored because sqlite_sequence only exists\n // when tables use AUTOINCREMENT, and we can't safely check that here\n return `DELETE FROM ${quote(tableName)}`;\n\n },\n\n dropTable(tableName: string, _schema?: string): string {\n\n return `DROP TABLE IF EXISTS ${quote(tableName)}`;\n\n },\n\n dropView(viewName: string, _schema?: string): string {\n\n return `DROP VIEW IF EXISTS ${quote(viewName)}`;\n\n },\n\n dropFunction(_name: string, _schema?: string): string {\n\n // SQLite doesn't support user-defined functions in SQL\n return '-- SQLite does not support user-defined functions';\n\n },\n\n dropProcedure(_name: string, _schema?: string): string {\n\n // SQLite doesn't support stored procedures\n return '-- SQLite does not support stored procedures';\n\n },\n\n dropType(_typeName: string, _schema?: string): string {\n\n // SQLite doesn't support custom types\n return '-- SQLite does not support custom types';\n\n },\n\n dropForeignKey(_constraintName: string, _tableName: string, _schema?: string): string {\n\n // SQLite doesn't support ALTER TABLE DROP CONSTRAINT\n // FK constraints are disabled globally instead\n return '-- SQLite does not support dropping individual FK constraints';\n\n },\n\n};\n","/**\n * Teardown Dialect Factory\n *\n * Provides dialect-specific teardown operations.\n */\nimport type { Dialect } from '../../connection/types.js';\nimport type { TeardownDialectOperations } from '../types.js';\nimport { postgresTeardownOperations } from './postgres.js';\nimport { mysqlTeardownOperations } from './mysql.js';\nimport { mssqlTeardownOperations } from './mssql.js';\nimport { sqliteTeardownOperations } from './sqlite.js';\n\n/**\n * Get teardown operations for a specific dialect.\n *\n * @param dialect - Database dialect\n * @returns Dialect-specific teardown operations\n *\n * @example\n * ```typescript\n * const ops = getTeardownOperations('postgres')\n * const sql = ops.truncateTable('users', 'public', true)\n * ```\n */\nexport function getTeardownOperations(dialect: Dialect): TeardownDialectOperations {\n\n switch (dialect) {\n\n case 'postgres':\n return postgresTeardownOperations;\n\n case 'mysql':\n return mysqlTeardownOperations;\n\n case 'mssql':\n return mssqlTeardownOperations;\n\n case 'sqlite':\n return sqliteTeardownOperations;\n\n default: {\n\n const exhaustiveCheck: never = dialect;\n throw new Error(`Unknown dialect: ${exhaustiveCheck}`);\n\n }\n\n }\n\n}\n\n// Re-export individual dialect operations for direct access if needed\nexport { postgresTeardownOperations } from './postgres.js';\nexport { mysqlTeardownOperations } from './mysql.js';\nexport { mssqlTeardownOperations } from './mssql.js';\nexport { sqliteTeardownOperations } from './sqlite.js';\n","/**\n * Change module types.\n *\n * Defines interfaces for changes - versioned database modifications\n * applied after initial schema build. Changes support forward changes\n * and rollbacks with execution tracking.\n *\n * WHY: Centralized type definitions ensure consistency across\n * parser, executor, history, and manager components.\n */\nimport type { Kysely } from 'kysely';\n\nimport type {\n NoormDatabase,\n OperationStatus,\n Direction,\n ExecutionStatus,\n} from '../shared/index.js';\nimport type { Identity } from '../identity/index.js';\n\n// ─────────────────────────────────────────────────────────────\n// File Types\n// ─────────────────────────────────────────────────────────────\n\n/**\n * File extension type in changes.\n *\n * - 'sql' for direct SQL files (.sql, .sql.tmpl)\n * - 'txt' for manifest files referencing build SQL\n */\nexport type ChangeFileType = 'sql' | 'txt';\n\n/**\n * A single file within a change.\n *\n * @example\n * ```typescript\n * const file: ChangeFile = {\n * filename: '001_alter-users.sql',\n * path: '/project/changes/2024-01-15-add-users/change/001_alter-users.sql',\n * type: 'sql',\n * }\n * ```\n */\nexport interface ChangeFile {\n /** Filename (e.g., \"001_alter-users.sql\") */\n filename: string;\n\n /** Absolute path to file */\n path: string;\n\n /** File type */\n type: ChangeFileType;\n\n /** For .txt files, the resolved SQL paths (relative to schema dir) */\n resolvedPaths?: string[];\n\n /** Execution status after running */\n status?: ExecutionStatus;\n\n /** Why the file was skipped */\n skipReason?: string;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Change (from disk)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * A change parsed from disk.\n *\n * Contains the folder structure with change and revert files.\n *\n * @example\n * ```typescript\n * const change: Change = {\n * name: '2024-01-15-add-email-verification',\n * path: '/project/changes/2024-01-15-add-email-verification',\n * date: new Date('2024-01-15'),\n * description: 'add-email-verification',\n * changeFiles: [...],\n * revertFiles: [...],\n * hasChangelog: true,\n * }\n * ```\n */\nexport interface Change {\n /** Folder name (e.g., \"2024-01-15-add-email-verification\") */\n name: string;\n\n /** Absolute path to change folder */\n path: string;\n\n /** Date parsed from name (null if no date prefix) */\n date: Date | null;\n\n /** Human-readable description from name */\n description: string;\n\n /** Files in change/ folder */\n changeFiles: ChangeFile[];\n\n /** Files in revert/ folder */\n revertFiles: ChangeFile[];\n\n /** Whether changelog.md exists */\n hasChangelog: boolean;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Change Status (from database)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Status of a change from database records.\n *\n * Represents the most recent execution state.\n *\n * @example\n * ```typescript\n * const status: ChangeStatus = {\n * name: '2024-01-15-add-users',\n * status: 'success',\n * appliedAt: new Date('2024-01-15T10:30:00Z'),\n * appliedBy: 'Alice <alice@example.com>',\n * revertedAt: null,\n * errorMessage: null,\n * }\n * ```\n */\nexport interface ChangeStatus {\n /** Change name */\n name: string;\n\n /** Current status */\n status: OperationStatus;\n\n /** When last applied (null if never) */\n appliedAt: Date | null;\n\n /** Who applied it */\n appliedBy: string | null;\n\n /** When reverted (null if not reverted) */\n revertedAt: Date | null;\n\n /** Error message if failed */\n errorMessage: string | null;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Change List Item (merged disk + DB)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * A change with merged disk and database information.\n *\n * Used by the list command to show all changes with status.\n *\n * @example\n * ```typescript\n * const item: ChangeListItem = {\n * // From disk\n * name: '2024-01-15-add-users',\n * path: '/project/changes/...',\n * // ...other Change fields\n *\n * // From DB\n * status: 'success',\n * appliedAt: new Date(),\n * // ...other ChangeStatus fields\n *\n * // Computed\n * isNew: false,\n * orphaned: false,\n * }\n * ```\n */\nexport interface ChangeListItem {\n /** Change name (always present) */\n name: string;\n\n // From disk (optional for orphaned)\n /** Absolute path to change folder */\n path?: string;\n\n /** Date parsed from name (null if no date prefix) */\n date?: Date | null;\n\n /** Human-readable description from name */\n description?: string;\n\n /** Files in change/ folder */\n changeFiles?: ChangeFile[];\n\n /** Files in revert/ folder */\n revertFiles?: ChangeFile[];\n\n /** Whether changelog.md exists */\n hasChangelog?: boolean;\n\n // From DB\n /** Current status */\n status: OperationStatus;\n\n /** When last applied (null if never) */\n appliedAt: Date | null;\n\n /** Who applied it */\n appliedBy: string | null;\n\n /** When reverted (null if not reverted) */\n revertedAt: Date | null;\n\n /** Error message if failed */\n errorMessage: string | null;\n\n // Computed\n /** True if exists on disk but no DB record */\n isNew: boolean;\n\n /** True if exists in DB but folder deleted from disk */\n orphaned: boolean;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Execution Options\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Options for executing a change.\n *\n * @example\n * ```typescript\n * const options: ChangeOptions = {\n * force: false,\n * dryRun: false,\n * preview: false,\n * }\n * ```\n */\nexport interface ChangeOptions {\n /** Re-run even if already applied. Default: false */\n force?: boolean;\n\n /** Render to tmp/ without executing. Default: false */\n dryRun?: boolean;\n\n /** Output rendered SQL without executing. Default: false */\n preview?: boolean;\n\n /** Write preview output to file. Default: null */\n output?: string | null;\n}\n\n/**\n * Options for batch operations (next, ff, rewind).\n */\nexport interface BatchChangeOptions extends ChangeOptions {\n /** Stop on first failure. Default: true */\n abortOnError?: boolean;\n}\n\n/**\n * Default change options.\n */\nexport const DEFAULT_CHANGE_OPTIONS: Required<Omit<ChangeOptions, 'output'>> & {\n output: string | null;\n} = {\n force: false,\n dryRun: false,\n preview: false,\n output: null,\n};\n\n/**\n * Default batch options.\n */\nexport const DEFAULT_BATCH_OPTIONS: Required<Omit<BatchChangeOptions, 'output'>> & {\n output: string | null;\n} = {\n ...DEFAULT_CHANGE_OPTIONS,\n abortOnError: true,\n};\n\n// ─────────────────────────────────────────────────────────────\n// Execution Context\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Context required to execute changes.\n *\n * @example\n * ```typescript\n * const context: ChangeContext = {\n * db,\n * configName: 'dev',\n * identity: { name: 'Alice', email: 'alice@example.com' },\n * projectRoot: '/project',\n * changesDir: '/project/changes',\n * sqlDir: '/project/sql',\n * }\n * ```\n */\nexport interface ChangeContext {\n /** Kysely database connection */\n db: Kysely<NoormDatabase>;\n\n /** Name of the active config */\n configName: string;\n\n /** User identity for tracking */\n identity: Identity;\n\n /** Project root for template resolution */\n projectRoot: string;\n\n /** Directory containing changes */\n changesDir: string;\n\n /** Schema directory for resolving .txt references */\n sqlDir: string;\n\n /** Config object for template context */\n config?: Record<string, unknown>;\n\n /** Secrets for template context */\n secrets?: Record<string, string>;\n\n /** Global secrets for template context */\n globalSecrets?: Record<string, string>;\n\n /** Database dialect for lock formatting. Default: 'postgres' */\n dialect?: 'postgres' | 'mysql' | 'sqlite' | 'mssql';\n}\n\n// ─────────────────────────────────────────────────────────────\n// Execution Results\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Result of executing a single change.\n *\n * @example\n * ```typescript\n * const result: ChangeResult = {\n * name: '2024-01-15-add-users',\n * direction: 'change',\n * status: 'success',\n * files: [...],\n * durationMs: 1234,\n * }\n * ```\n */\nexport interface ChangeResult {\n /** Change name */\n name: string;\n\n /** Operation direction */\n direction: Direction;\n\n /** Final status */\n status: OperationStatus;\n\n /** Individual file results */\n files: ChangeFileResult[];\n\n /** Total execution time */\n durationMs: number;\n\n /** Error message if failed */\n error?: string;\n\n /** Operation ID in tracking table */\n operationId?: number;\n}\n\n/**\n * Result of executing a single file within a change.\n */\nexport interface ChangeFileResult {\n /** File path */\n filepath: string;\n\n /** File checksum */\n checksum: string;\n\n /** Execution status */\n status: ExecutionStatus;\n\n /** Why skipped (if skipped) */\n skipReason?: string;\n\n /** Execution time in milliseconds */\n durationMs?: number;\n\n /** Error message if failed */\n error?: string;\n\n /** Rendered SQL (only in preview mode) */\n renderedSql?: string;\n}\n\n/**\n * Result of a batch operation (next, ff, rewind).\n */\nexport interface BatchChangeResult {\n /** Overall status */\n status: 'success' | 'failed' | 'partial';\n\n /** Results for each change */\n changes: ChangeResult[];\n\n /** Number of changes executed */\n executed: number;\n\n /** Number of changes skipped */\n skipped: number;\n\n /** Number of changes that failed */\n failed: number;\n\n /** Total execution time */\n durationMs: number;\n}\n\n// ─────────────────────────────────────────────────────────────\n// History Types\n// ─────────────────────────────────────────────────────────────\n\n/**\n * A single execution record from history.\n */\nexport interface ChangeHistoryRecord {\n /** Record ID */\n id: number;\n\n /** Change name */\n name: string;\n\n /** Operation direction */\n direction: Direction;\n\n /** Status */\n status: OperationStatus;\n\n /** When executed */\n executedAt: Date;\n\n /** Who executed */\n executedBy: string;\n\n /** Duration in milliseconds */\n durationMs: number;\n\n /** Error message if failed */\n errorMessage: string | null;\n\n /** Checksum of files */\n checksum: string;\n}\n\n/**\n * Unified history record that includes the change type.\n *\n * Used to display all operation types (builds, runs, changes)\n * in a unified activity view.\n */\nexport interface UnifiedHistoryRecord extends ChangeHistoryRecord {\n /** Type of change operation */\n changeType: 'build' | 'run' | 'change';\n}\n\n/**\n * File execution record from history.\n */\nexport interface FileHistoryRecord {\n /** Record ID */\n id: number;\n\n /** Parent change ID */\n changeId: number;\n\n /** File path */\n filepath: string;\n\n /** File type */\n fileType: ChangeFileType;\n\n /** File checksum */\n checksum: string;\n\n /** Execution status */\n status: ExecutionStatus;\n\n /** Skip reason if skipped */\n skipReason: string | null;\n\n /** Error message if failed */\n errorMessage: string | null;\n\n /** Duration in milliseconds */\n durationMs: number;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Change Detection\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Why a change needs to run.\n */\nexport type ChangeRunReason = 'new' | 'changed' | 'failed' | 'reverted' | 'stale' | 'force';\n\n/**\n * Result of checking if a change needs to run.\n */\nexport interface NeedsRunResult {\n /** Whether the change needs to run */\n needsRun: boolean;\n\n /** Why it needs to run (if needsRun is true) */\n reason?: ChangeRunReason;\n\n /** Why it was skipped (if needsRun is false) */\n skipReason?: string;\n\n /** Previous checksum if exists */\n previousChecksum?: string;\n\n /** Previous status if exists */\n previousStatus?: OperationStatus;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Scaffold Types\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Options for creating a new change.\n */\nexport interface CreateChangeOptions {\n /** Description for the change name */\n description: string;\n\n /** Optional date (defaults to today) */\n date?: Date;\n}\n\n/**\n * Options for adding a file to a change.\n */\nexport interface AddFileOptions {\n /** Descriptive name for the file */\n name: string;\n\n /** File type */\n type: ChangeFileType;\n\n /** For 'txt' type, the paths to include */\n paths?: string[];\n\n /** Initial content (optional) */\n content?: string;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Error Types\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Error when change structure is invalid.\n */\nexport class ChangeValidationError extends Error {\n\n override readonly name = 'ChangeValidationError' as const;\n\n constructor(\n public readonly changeName: string,\n public readonly issue: string,\n ) {\n\n super(`Invalid change '${changeName}': ${issue}`);\n\n }\n\n}\n\n/**\n * Error when change is not found.\n */\nexport class ChangeNotFoundError extends Error {\n\n override readonly name = 'ChangeNotFoundError' as const;\n\n constructor(public readonly changeName: string) {\n\n super(`Change not found: ${changeName}`);\n\n }\n\n}\n\n/**\n * Error when change is already applied.\n */\nexport class ChangeAlreadyAppliedError extends Error {\n\n override readonly name = 'ChangeAlreadyAppliedError' as const;\n\n constructor(\n public readonly changeName: string,\n public readonly appliedAt: Date,\n ) {\n\n super(`Change '${changeName}' already applied at ${appliedAt.toISOString()}`);\n\n }\n\n}\n\n/**\n * Error when trying to revert an unapplied change.\n */\nexport class ChangeNotAppliedError extends Error {\n\n override readonly name = 'ChangeNotAppliedError' as const;\n\n constructor(public readonly changeName: string) {\n\n super(`Cannot revert '${changeName}': not applied`);\n\n }\n\n}\n\n/**\n * Error when change is orphaned (in DB but not on disk).\n */\nexport class ChangeOrphanedError extends Error {\n\n override readonly name = 'ChangeOrphanedError' as const;\n\n constructor(public readonly changeName: string) {\n\n super(`Change '${changeName}' is orphaned (folder deleted from disk)`);\n\n }\n\n}\n\n/**\n * Error when .txt manifest has invalid references.\n */\nexport class ManifestReferenceError extends Error {\n\n override readonly name = 'ManifestReferenceError' as const;\n\n constructor(\n public readonly manifestPath: string,\n public readonly missingPath: string,\n ) {\n\n super(`Manifest '${manifestPath}' references missing file: ${missingPath}`);\n\n }\n\n}\n","/**\n * Change parser.\n *\n * Reads changes from disk, resolves manifest files, and validates\n * change structure. Provides the foundation for all change operations.\n *\n * WHY: Changes are stored as folder structures on disk. The parser\n * transforms these into typed objects for the executor and manager.\n *\n * @example\n * ```typescript\n * import { parseChange, discoverChanges } from './parser'\n *\n * // Load a single change\n * const change = await parseChange('/path/to/2024-01-15-add-users')\n *\n * // Discover all changes in a directory\n * const all = await discoverChanges('/project/changes')\n * ```\n */\nimport path from 'node:path';\nimport { readdir, readFile, stat, access } from 'node:fs/promises';\nimport { constants as fsConstants } from 'node:fs';\n\nimport { attempt } from '@logosdx/utils';\n\nimport { observer } from '../observer.js';\nimport type { Change, ChangeFile, ChangeFileType } from './types.js';\nimport {\n ChangeValidationError,\n ChangeNotFoundError,\n ManifestReferenceError,\n} from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Constants\n// ─────────────────────────────────────────────────────────────\n\n/** Valid SQL file extensions */\nconst SQL_EXTENSIONS = ['.sql', '.sql.tmpl'];\n\n/** Valid manifest extension */\nconst MANIFEST_EXTENSION = '.txt';\n\n/** Date prefix regex: YYYY-MM-DD */\nconst DATE_PREFIX_REGEX = /^(\\d{4}-\\d{2}-\\d{2})-(.+)$/;\n\n/** File sequence regex: 001_description */\nconst SEQUENCE_REGEX = /^(\\d{3})_(.+)$/;\n\n// ─────────────────────────────────────────────────────────────\n// Parse Single Change\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Parse a change from a folder path.\n *\n * @param folderPath - Absolute path to change folder\n * @param sqlDir - Schema directory for resolving .txt references\n * @returns Parsed change\n * @throws ChangeNotFoundError if folder doesn't exist\n * @throws ChangeValidationError if structure is invalid\n *\n * @example\n * ```typescript\n * const change = await parseChange(\n * '/project/changes/2024-01-15-add-users',\n * '/project/sql'\n * )\n *\n * console.log(change.name) // '2024-01-15-add-users'\n * console.log(change.changeFiles) // [{ filename: '001_create-table.sql', ... }]\n * ```\n */\nexport async function parseChange(folderPath: string, sqlDir?: string): Promise<Change> {\n\n // Check folder exists\n const [folderStat, statErr] = await attempt(() => stat(folderPath));\n\n if (statErr || !folderStat?.isDirectory()) {\n\n throw new ChangeNotFoundError(path.basename(folderPath));\n\n }\n\n // Parse name\n const name = path.basename(folderPath);\n const { date, description } = parseName(name);\n\n // Scan change/ folder\n const changePath = path.join(folderPath, 'change');\n const [changeFiles, changeErr] = await attempt(() => scanFolder(changePath, sqlDir));\n\n if (changeErr && !isNotFoundError(changeErr)) {\n\n throw changeErr;\n\n }\n\n // Scan revert/ folder\n const revertPath = path.join(folderPath, 'revert');\n const [revertFiles, revertErr] = await attempt(() => scanFolder(revertPath, sqlDir));\n\n if (revertErr && !isNotFoundError(revertErr)) {\n\n throw revertErr;\n\n }\n\n // Check for changelog.md\n const changelogPath = path.join(folderPath, 'changelog.md');\n const hasChangelog = await fileExists(changelogPath);\n\n // Validate: must have at least change/ or revert/\n if ((!changeFiles || changeFiles.length === 0) && (!revertFiles || revertFiles.length === 0)) {\n\n throw new ChangeValidationError(\n name,\n 'Must have at least change/ or revert/ folder with files',\n );\n\n }\n\n return {\n name,\n path: folderPath,\n date,\n description,\n changeFiles: changeFiles ?? [],\n revertFiles: revertFiles ?? [],\n hasChangelog,\n };\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Discover All Changes\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Discover all changes in a directory.\n *\n * @param changesDir - Directory containing change folders\n * @param sqlDir - Schema directory for resolving .txt references\n * @returns Array of parsed changes, sorted by name\n *\n * @example\n * ```typescript\n * const changes = await discoverChanges('/project/changes', '/project/sql')\n *\n * for (const cs of changes) {\n * console.log(cs.name, cs.date)\n * }\n * ```\n */\nexport async function discoverChanges(\n changesDir: string,\n sqlDir?: string,\n): Promise<Change[]> {\n\n // Check directory exists\n const [exists] = await attempt(() => stat(changesDir));\n\n if (!exists) {\n\n return [];\n\n }\n\n // Read directory entries\n const [entries, readErr] = await attempt(() => readdir(changesDir, { withFileTypes: true }));\n\n if (readErr) {\n\n observer.emit('error', {\n source: 'change',\n error: readErr,\n context: { changesDir, operation: 'discover' },\n });\n\n return [];\n\n }\n\n // Filter to directories only\n const folders = entries.filter((e) => e.isDirectory());\n\n // Parse each change\n const changes: Change[] = [];\n\n for (const folder of folders) {\n\n const folderPath = path.join(changesDir, folder.name);\n\n const [change, parseErr] = await attempt(() => parseChange(folderPath, sqlDir));\n\n if (parseErr) {\n\n // Log error but continue with other changes\n observer.emit('error', {\n source: 'change',\n error: parseErr,\n context: { folder: folder.name, operation: 'parse' },\n });\n\n continue;\n\n }\n\n changes.push(change);\n\n }\n\n // Sort by name (date prefix ensures chronological order)\n return changes.sort((a, b) => a.name.localeCompare(b.name));\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Resolve Manifest Files\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Resolve a .txt manifest file to actual SQL paths.\n *\n * @param manifestPath - Path to the .txt manifest file\n * @param sqlDir - Schema directory for resolving relative paths\n * @returns Array of absolute paths to SQL files\n * @throws ManifestReferenceError if any referenced file is missing\n *\n * @example\n * ```typescript\n * // Manifest contains:\n * // sql/tables/users.sql\n * // sql/views/active_users.sql\n *\n * const paths = await resolveManifest(\n * '/project/changes/.../change/001_refs.txt',\n * '/project/sql'\n * )\n * // => ['/project/sql/tables/users.sql', '/project/sql/views/active_users.sql']\n * ```\n */\nexport async function resolveManifest(manifestPath: string, sqlDir: string): Promise<string[]> {\n\n // Read manifest content\n const [content, readErr] = await attempt(() => readFile(manifestPath, 'utf-8'));\n\n if (readErr) {\n\n throw new Error(`Failed to read manifest: ${manifestPath}`, { cause: readErr });\n\n }\n\n // Parse lines (skip empty and comments)\n const lines = content\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#'));\n\n if (lines.length === 0) {\n\n throw new ChangeValidationError(\n path.basename(path.dirname(path.dirname(manifestPath))),\n `Empty manifest file: ${path.basename(manifestPath)}`,\n );\n\n }\n\n // Resolve each path\n const resolvedPaths: string[] = [];\n\n for (const relativePath of lines) {\n\n const absolutePath = path.join(sqlDir, relativePath);\n\n // Validate file exists\n const [exists] = await attempt(() => access(absolutePath, fsConstants.R_OK));\n\n if (exists === undefined) {\n\n resolvedPaths.push(absolutePath);\n\n }\n else {\n\n throw new ManifestReferenceError(manifestPath, relativePath);\n\n }\n\n }\n\n // Sort alphabetically (as per plan: files executed in sorted order)\n return resolvedPaths.sort();\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Validation\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Validate a change structure.\n *\n * @param change - Change to validate\n * @throws ChangeValidationError if invalid\n */\nexport function validateChange(change: Change): void {\n\n // Check for duplicate filenames in change/\n const changeFilenames = change.changeFiles.map((f) => f.filename);\n const changeDuplicates = findDuplicates(changeFilenames);\n\n if (changeDuplicates.length > 0) {\n\n throw new ChangeValidationError(\n change.name,\n `Duplicate files in change/: ${changeDuplicates.join(', ')}`,\n );\n\n }\n\n // Check for duplicate filenames in revert/\n const revertFilenames = change.revertFiles.map((f) => f.filename);\n const revertDuplicates = findDuplicates(revertFilenames);\n\n if (revertDuplicates.length > 0) {\n\n throw new ChangeValidationError(\n change.name,\n `Duplicate files in revert/: ${revertDuplicates.join(', ')}`,\n );\n\n }\n\n}\n\n/**\n * Check if a change has revert files.\n */\nexport function hasRevertFiles(change: Change): boolean {\n\n return change.revertFiles.length > 0;\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Internal Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Parse change name into date and description.\n */\nfunction parseName(name: string): { date: Date | null; description: string } {\n\n const match = name.match(DATE_PREFIX_REGEX);\n\n if (match && match[1] && match[2]) {\n\n const dateStr = match[1];\n const description = match[2];\n const date = new Date(dateStr);\n\n // Validate date is valid\n if (!isNaN(date.getTime())) {\n\n return { date, description };\n\n }\n\n }\n\n // No date prefix - use entire name as description\n return { date: null, description: name };\n\n}\n\n/**\n * Scan a folder for SQL and manifest files.\n */\nasync function scanFolder(folderPath: string, sqlDir?: string): Promise<ChangeFile[]> {\n\n // Read directory\n const [entries, err] = await attempt(() => readdir(folderPath, { withFileTypes: true }));\n\n if (err) {\n\n throw err;\n\n }\n\n const files: ChangeFile[] = [];\n\n for (const entry of entries) {\n\n if (!entry.isFile()) continue;\n\n const filename = entry.name;\n const filePath = path.join(folderPath, filename);\n\n // Determine file type\n const type = getFileType(filename);\n\n if (!type) continue;\n\n const file: ChangeFile = {\n filename,\n path: filePath,\n type,\n };\n\n // Resolve manifest references\n if (type === 'txt' && sqlDir) {\n\n const [resolvedPaths, resolveErr] = await attempt(() =>\n resolveManifest(filePath, sqlDir),\n );\n\n if (resolveErr) {\n\n throw resolveErr;\n\n }\n\n file.resolvedPaths = resolvedPaths;\n\n }\n\n files.push(file);\n\n }\n\n // Sort by filename for deterministic order\n return files.sort((a, b) => a.filename.localeCompare(b.filename));\n\n}\n\n/**\n * Determine file type from filename.\n */\nfunction getFileType(filename: string): ChangeFileType | null {\n\n if (filename.endsWith(MANIFEST_EXTENSION)) {\n\n return 'txt';\n\n }\n\n for (const ext of SQL_EXTENSIONS) {\n\n if (filename.endsWith(ext)) {\n\n return 'sql';\n\n }\n\n }\n\n return null;\n\n}\n\n/**\n * Check if a file exists.\n */\nasync function fileExists(filePath: string): Promise<boolean> {\n\n const [, err] = await attempt(() => access(filePath, fsConstants.R_OK));\n\n return err === null;\n\n}\n\n/**\n * Check if error is a \"not found\" error.\n */\nfunction isNotFoundError(err: Error): boolean {\n\n return (err as NodeJS.ErrnoException).code === 'ENOENT';\n\n}\n\n/**\n * Find duplicate items in an array.\n */\nfunction findDuplicates(items: string[]): string[] {\n\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n\n for (const item of items) {\n\n if (seen.has(item)) {\n\n duplicates.add(item);\n\n }\n\n seen.add(item);\n\n }\n\n return Array.from(duplicates);\n\n}\n\n/**\n * Parse sequence number from filename.\n *\n * @example\n * ```typescript\n * parseSequence('001_create-table.sql') // => 1\n * parseSequence('invalid.sql') // => null\n * ```\n */\nexport function parseSequence(filename: string): number | null {\n\n const match = filename.match(SEQUENCE_REGEX);\n\n if (match && match[1]) {\n\n return parseInt(match[1], 10);\n\n }\n\n return null;\n\n}\n\n/**\n * Extract description from filename.\n *\n * @example\n * ```typescript\n * parseDescription('001_create-users-table.sql') // => 'create-users-table'\n * ```\n */\nexport function parseDescription(filename: string): string {\n\n // Remove extension\n let name = filename;\n\n if (name.endsWith('.sql.tmpl')) {\n\n name = name.slice(0, -9);\n\n }\n else if (name.endsWith('.sql')) {\n\n name = name.slice(0, -4);\n\n }\n else if (name.endsWith('.txt')) {\n\n name = name.slice(0, -4);\n\n }\n\n // Remove sequence prefix\n const match = name.match(SEQUENCE_REGEX);\n\n if (match && match[2]) {\n\n return match[2];\n\n }\n\n return name;\n\n}\n","/**\n * Change scaffolding.\n *\n * File system operations for creating and modifying change directories.\n * Provides the building blocks for interactive change creation.\n *\n * WHY: Changes have a specific folder structure. The scaffold module\n * ensures consistent naming and structure when creating or modifying them.\n *\n * @example\n * ```typescript\n * import { createChange, addFile, reorderFiles } from './scaffold'\n *\n * // Create a new change\n * const change = await createChange('/project/changes', {\n * description: 'add-email-verification',\n * })\n *\n * // Add a file\n * await addFile(change, 'change', {\n * name: 'create-tokens-table',\n * type: 'sql',\n * })\n * ```\n */\nimport path from 'node:path';\nimport { mkdir, writeFile, rename, unlink, rm, stat } from 'node:fs/promises';\n\nimport { attempt } from '@logosdx/utils';\n\nimport { observer } from '../observer.js';\nimport { parseSequence, parseDescription } from './parser.js';\nimport type {\n Change,\n ChangeFile,\n CreateChangeOptions,\n AddFileOptions,\n} from './types.js';\nimport { ChangeValidationError } from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Constants\n// ─────────────────────────────────────────────────────────────\n\n/** Default template for new SQL files */\nconst SQL_TEMPLATE = `-- TODO: Add SQL statements here\n`;\n\n/** Default template for changelog */\nconst CHANGELOG_TEMPLATE = `# Changelog\n\n## Description\n\nTODO: Describe the purpose of this change.\n\n## Changes\n\n- TODO: List changes\n\n## Impact\n\nTODO: Describe any impact on existing data or functionality.\n`;\n\n// ─────────────────────────────────────────────────────────────\n// Create Change\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create a new change directory.\n *\n * @param changesDir - Parent directory for changes\n * @param options - Creation options\n * @returns Parsed change (empty, ready for files)\n *\n * @example\n * ```typescript\n * const change = await createChange('/project/changes', {\n * description: 'add-user-roles',\n * date: new Date('2024-01-15'),\n * })\n *\n * console.log(change.name) // '2024-01-15-add-user-roles'\n * ```\n */\nexport async function createChange(\n changesDir: string,\n options: CreateChangeOptions,\n): Promise<Change> {\n\n // Generate name\n const date = options.date ?? new Date();\n const dateStr = formatDate(date);\n const slug = slugify(options.description);\n const name = `${dateStr}-${slug}`;\n\n const changeDir = path.join(changesDir, name);\n\n // Check if change already exists\n const [existingStats] = await attempt(() => stat(changeDir));\n\n if (existingStats) {\n\n throw new Error(`Change already exists: ${name}`);\n\n }\n\n // Create directory structure\n const [, mkdirErr] = await attempt(() => mkdir(changeDir, { recursive: true }));\n\n if (mkdirErr) {\n\n throw new Error(`Failed to create change directory: ${changeDir}`, {\n cause: mkdirErr,\n });\n\n }\n\n // Create change/ and revert/ folders\n const changePath = path.join(changeDir, 'change');\n const revertPath = path.join(changeDir, 'revert');\n\n await mkdir(changePath, { recursive: true });\n await mkdir(revertPath, { recursive: true });\n\n // Create changelog.md\n const changelogPath = path.join(changeDir, 'changelog.md');\n await writeFile(changelogPath, CHANGELOG_TEMPLATE, 'utf-8');\n\n // Emit event\n observer.emit('change:created', {\n name,\n path: changeDir,\n });\n\n // Return parsed change\n return {\n name,\n path: changeDir,\n date,\n description: slug,\n changeFiles: [],\n revertFiles: [],\n hasChangelog: true,\n };\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Add File\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Add a file to a change.\n *\n * @param change - Change to modify\n * @param folder - 'change' or 'revert'\n * @param options - File options\n * @returns Updated change\n *\n * @example\n * ```typescript\n * // Add a new SQL file\n * const updated = await addFile(change, 'change', {\n * name: 'create-tokens-table',\n * type: 'sql',\n * })\n *\n * // Add a manifest file\n * const updated = await addFile(change, 'change', {\n * name: 'rerun-views',\n * type: 'txt',\n * paths: ['sql/views/active_users.sql'],\n * })\n * ```\n */\nexport async function addFile(\n change: Change,\n folder: 'change' | 'revert',\n options: AddFileOptions,\n): Promise<Change> {\n\n const files = folder === 'change' ? change.changeFiles : change.revertFiles;\n\n // Determine next sequence number\n const maxSequence = getMaxSequence(files);\n const sequence = maxSequence + 1;\n\n // Generate filename\n const slug = slugify(options.name);\n const extension = options.type === 'txt' ? '.txt' : '.sql';\n const filename = `${padSequence(sequence)}_${slug}${extension}`;\n\n const folderPath = path.join(change.path, folder);\n const filePath = path.join(folderPath, filename);\n\n // Determine content\n let content: string;\n\n if (options.content) {\n\n content = options.content;\n\n }\n else if (options.type === 'txt' && options.paths) {\n\n content = options.paths.join('\\n') + '\\n';\n\n }\n else {\n\n content = SQL_TEMPLATE;\n\n }\n\n // Write file\n const [, writeErr] = await attempt(() => writeFile(filePath, content, 'utf-8'));\n\n if (writeErr) {\n\n throw new Error(`Failed to create file: ${filePath}`, { cause: writeErr });\n\n }\n\n // Create file object\n const file: ChangeFile = {\n filename,\n path: filePath,\n type: options.type,\n };\n\n if (options.type === 'txt' && options.paths) {\n\n file.resolvedPaths = options.paths;\n\n }\n\n // Update change\n const updatedFiles = [...files, file].sort((a, b) => a.filename.localeCompare(b.filename));\n\n if (folder === 'change') {\n\n return { ...change, changeFiles: updatedFiles };\n\n }\n\n return { ...change, revertFiles: updatedFiles };\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Remove File\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Remove a file from a change.\n *\n * @param change - Change to modify\n * @param folder - 'change' or 'revert'\n * @param filename - Filename to remove\n * @returns Updated change\n */\nexport async function removeFile(\n change: Change,\n folder: 'change' | 'revert',\n filename: string,\n): Promise<Change> {\n\n const files = folder === 'change' ? change.changeFiles : change.revertFiles;\n\n // Find file\n const file = files.find((f) => f.filename === filename);\n\n if (!file) {\n\n throw new ChangeValidationError(change.name, `File not found: ${filename}`);\n\n }\n\n // Delete file\n const [, unlinkErr] = await attempt(() => unlink(file.path));\n\n if (unlinkErr) {\n\n throw new Error(`Failed to delete file: ${file.path}`, { cause: unlinkErr });\n\n }\n\n // Update change\n const updatedFiles = files.filter((f) => f.filename !== filename);\n\n if (folder === 'change') {\n\n return { ...change, changeFiles: updatedFiles };\n\n }\n\n return { ...change, revertFiles: updatedFiles };\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Rename File\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Rename a file in a change.\n *\n * @param change - Change to modify\n * @param folder - 'change' or 'revert'\n * @param oldFilename - Current filename\n * @param newDescription - New description part\n * @returns Updated change\n */\nexport async function renameFile(\n change: Change,\n folder: 'change' | 'revert',\n oldFilename: string,\n newDescription: string,\n): Promise<Change> {\n\n const files = folder === 'change' ? change.changeFiles : change.revertFiles;\n\n // Find file\n const fileIndex = files.findIndex((f) => f.filename === oldFilename);\n\n if (fileIndex === -1) {\n\n throw new ChangeValidationError(change.name, `File not found: ${oldFilename}`);\n\n }\n\n const file = files[fileIndex];\n\n if (!file) {\n\n throw new ChangeValidationError(change.name, `File not found: ${oldFilename}`);\n\n }\n\n // Parse current filename\n const sequence = parseSequence(file.filename);\n const extension = getExtension(file.filename);\n\n if (sequence === null) {\n\n throw new ChangeValidationError(\n change.name,\n `Invalid filename format: ${oldFilename}`,\n );\n\n }\n\n // Generate new filename\n const slug = slugify(newDescription);\n const newFilename = `${padSequence(sequence)}_${slug}${extension}`;\n const newPath = path.join(path.dirname(file.path), newFilename);\n\n // Rename file\n const [, renameErr] = await attempt(() => rename(file.path, newPath));\n\n if (renameErr) {\n\n throw new Error(`Failed to rename file: ${file.path}`, { cause: renameErr });\n\n }\n\n // Update file object\n const updatedFile: ChangeFile = {\n ...file,\n filename: newFilename,\n path: newPath,\n };\n\n // Update change\n const updatedFiles = [...files];\n updatedFiles[fileIndex] = updatedFile;\n updatedFiles.sort((a, b) => a.filename.localeCompare(b.filename));\n\n if (folder === 'change') {\n\n return { ...change, changeFiles: updatedFiles };\n\n }\n\n return { ...change, revertFiles: updatedFiles };\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Reorder Files\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Reorder files in a change folder.\n *\n * @param change - Change to modify\n * @param folder - 'change' or 'revert'\n * @param newOrder - Array of filenames in desired order\n * @returns Updated change\n *\n * @example\n * ```typescript\n * // Reorder files\n * const updated = await reorderFiles(change, 'change', [\n * '002_create-index.sql', // Was second, now first\n * '001_create-table.sql', // Was first, now second\n * ])\n *\n * // Files are renumbered: 001_create-index.sql, 002_create-table.sql\n * ```\n */\nexport async function reorderFiles(\n change: Change,\n folder: 'change' | 'revert',\n newOrder: string[],\n): Promise<Change> {\n\n const files = folder === 'change' ? change.changeFiles : change.revertFiles;\n\n // Validate new order contains all files\n const currentFilenames = new Set(files.map((f) => f.filename));\n const newOrderSet = new Set(newOrder);\n\n if (currentFilenames.size !== newOrderSet.size) {\n\n throw new ChangeValidationError(\n change.name,\n 'New order must contain all existing files',\n );\n\n }\n\n for (const filename of newOrder) {\n\n if (!currentFilenames.has(filename)) {\n\n throw new ChangeValidationError(\n change.name,\n `Unknown file in new order: ${filename}`,\n );\n\n }\n\n }\n\n // Create file map\n const fileMap = new Map(files.map((f) => [f.filename, f]));\n\n // Rename files to new sequence\n const updatedFiles: ChangeFile[] = [];\n\n for (let i = 0; i < newOrder.length; i++) {\n\n const oldFilename = newOrder[i];\n\n if (!oldFilename) continue;\n\n const file = fileMap.get(oldFilename);\n\n if (!file) continue;\n\n const newSequence = i + 1;\n\n // Get description and extension\n const description = parseDescription(oldFilename);\n const extension = getExtension(oldFilename);\n\n // Generate new filename\n const newFilename = `${padSequence(newSequence)}_${description}${extension}`;\n const newPath = path.join(path.dirname(file.path), newFilename);\n\n // Rename if changed\n if (newFilename !== oldFilename) {\n\n // Use temp name to avoid conflicts\n const tempPath = path.join(path.dirname(file.path), `_temp_${i}${extension}`);\n\n const [, renameErr] = await attempt(() => rename(file.path, tempPath));\n\n if (renameErr) {\n\n throw new Error(`Failed to rename file: ${file.path}`, { cause: renameErr });\n\n }\n\n updatedFiles.push({\n ...file,\n filename: newFilename,\n path: newPath,\n _tempPath: tempPath, // Track temp path\n } as ChangeFile & { _tempPath: string });\n\n }\n else {\n\n updatedFiles.push(file);\n\n }\n\n }\n\n // Final rename from temp to actual\n for (const file of updatedFiles) {\n\n const tempPath = (file as ChangeFile & { _tempPath?: string })._tempPath;\n\n if (tempPath) {\n\n const [, renameErr] = await attempt(() => rename(tempPath, file.path));\n\n if (renameErr) {\n\n throw new Error(`Failed to finalize rename: ${file.path}`, { cause: renameErr });\n\n }\n\n }\n\n }\n\n // Clean up temp property\n const cleanFiles = updatedFiles.map((f) => {\n\n const { _tempPath, ...clean } = f as ChangeFile & { _tempPath?: string };\n\n return clean;\n\n });\n\n if (folder === 'change') {\n\n return { ...change, changeFiles: cleanFiles };\n\n }\n\n return { ...change, revertFiles: cleanFiles };\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Delete Change\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Delete a change directory from disk.\n *\n * @param change - Change to delete\n */\nexport async function deleteChange(change: Change): Promise<void> {\n\n const [, rmErr] = await attempt(() => rm(change.path, { recursive: true, force: true }));\n\n if (rmErr) {\n\n throw new Error(`Failed to delete change: ${change.path}`, { cause: rmErr });\n\n }\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Internal Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Format date as YYYY-MM-DD.\n */\nfunction formatDate(date: Date): string {\n\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${year}-${month}-${day}`;\n\n}\n\n/**\n * Convert text to URL-safe slug.\n */\nfunction slugify(text: string): string {\n\n return text\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n}\n\n/**\n * Pad sequence number to 3 digits.\n */\nfunction padSequence(seq: number): string {\n\n return String(seq).padStart(3, '0');\n\n}\n\n/**\n * Get max sequence number from files.\n */\nfunction getMaxSequence(files: ChangeFile[]): number {\n\n let max = 0;\n\n for (const file of files) {\n\n const seq = parseSequence(file.filename);\n\n if (seq !== null && seq > max) {\n\n max = seq;\n\n }\n\n }\n\n return max;\n\n}\n\n/**\n * Get file extension (including .sql.tmpl).\n */\nfunction getExtension(filename: string): string {\n\n if (filename.endsWith('.sql.tmpl')) {\n\n return '.sql.tmpl';\n\n }\n\n if (filename.endsWith('.sql')) {\n\n return '.sql';\n\n }\n\n if (filename.endsWith('.txt')) {\n\n return '.txt';\n\n }\n\n return '';\n\n}\n","/**\n * Change history tracking.\n *\n * Database operations for tracking change execution. Provides\n * change detection, status queries, and execution recording.\n *\n * WHY: Change execution must be tracked to enable:\n * - Idempotent execution (skip already-applied changes)\n * - Audit trail (who ran what, when)\n * - Status visibility (list command)\n * - Safe reverts (know what was applied)\n *\n * @example\n * ```typescript\n * import { ChangeHistory } from './history'\n *\n * const history = new ChangeHistory(db, 'production')\n *\n * // Check if change needs to run\n * const result = await history.needsRun('2024-01-15-add-users', 'abc123...')\n *\n * // Get status\n * const status = await history.getStatus('2024-01-15-add-users')\n * ```\n */\nimport type { Kysely } from 'kysely';\nimport { sql } from 'kysely';\n\nimport { attempt } from '@logosdx/utils';\n\nimport { observer } from '../observer.js';\nimport { NOORM_TABLES } from '../shared/index.js';\nimport type {\n NoormDatabase,\n OperationStatus,\n Direction,\n ExecutionStatus,\n FileType,\n} from '../shared/index.js';\nimport type {\n ChangeStatus,\n ChangeHistoryRecord,\n UnifiedHistoryRecord,\n FileHistoryRecord,\n NeedsRunResult,\n} from './types.js';\nimport type { ChangeType } from '../shared/index.js';\n\n// ─────────────────────────────────────────────────────────────\n// History Class\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Change history tracker.\n *\n * Handles all database operations for change execution tracking.\n *\n * @example\n * ```typescript\n * const history = new ChangeHistory(db, 'production')\n *\n * // Create operation record\n * const opId = await history.createOperation({\n * name: '2024-01-15-add-users',\n * direction: 'change',\n * executedBy: 'Alice <alice@example.com>',\n * })\n *\n * // Record file executions\n * await history.recordFileExecution(opId, {\n * filepath: '/path/to/001.sql',\n * checksum: 'abc123',\n * status: 'success',\n * durationMs: 42,\n * })\n *\n * // Finalize\n * await history.finalizeOperation(opId, 'success', 'xyz789', 1234)\n * ```\n */\nexport class ChangeHistory {\n\n readonly #db: Kysely<NoormDatabase>;\n readonly #configName: string;\n\n constructor(db: Kysely<NoormDatabase>, configName: string) {\n\n this.#db = db;\n this.#configName = configName;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Status Queries\n // ─────────────────────────────────────────────────────────\n\n /**\n * Get the current status of a change.\n *\n * Queries the most recent record with `direction: 'change'` for\n * the change. Revert records don't affect change status.\n *\n * @param name - Change name\n * @returns Status or null if never run\n */\n async getStatus(name: string): Promise<ChangeStatus | null> {\n\n const [record, err] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.change)\n .select([\n 'name',\n 'status',\n 'executed_at',\n 'executed_by',\n 'error_message',\n 'checksum',\n ])\n .where('name', '=', name)\n .where('change_type', '=', 'change')\n .where('direction', '=', 'change')\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc')\n .limit(1)\n .executeTakeFirst(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { name, operation: 'get-status' },\n });\n\n return null;\n\n }\n\n if (!record) {\n\n return null;\n\n }\n\n // Check for revert (to get revertedAt)\n const [revertRecord] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.change)\n .select(['executed_at'])\n .where('name', '=', name)\n .where('change_type', '=', 'change')\n .where('direction', '=', 'revert')\n .where('status', '=', 'success')\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc')\n .limit(1)\n .executeTakeFirst(),\n );\n\n return {\n name: record.name,\n status: record.status,\n appliedAt: record.executed_at,\n appliedBy: record.executed_by,\n revertedAt: revertRecord?.executed_at ?? null,\n errorMessage: record.error_message || null,\n };\n\n }\n\n /**\n * Get status for all changes.\n *\n * Returns the most recent change record for each unique change name.\n *\n * @returns Map of change name to status\n */\n async getAllStatuses(): Promise<Map<string, ChangeStatus>> {\n\n const statuses = new Map<string, ChangeStatus>();\n\n // Get all unique change names\n const [records, err] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.change)\n .select(['id', 'name', 'status', 'executed_at', 'executed_by', 'error_message'])\n .where('change_type', '=', 'change')\n .where('direction', '=', 'change')\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc')\n .execute(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { operation: 'get-all-statuses' },\n });\n\n return statuses;\n\n }\n\n // Group by name, keeping most recent\n for (const record of records) {\n\n if (!statuses.has(record.name)) {\n\n statuses.set(record.name, {\n name: record.name,\n status: record.status,\n appliedAt: record.executed_at,\n appliedBy: record.executed_by,\n revertedAt: null, // Will be filled in below\n errorMessage: record.error_message || null,\n });\n\n }\n\n }\n\n // Get revert info for each\n const [reverts] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.change)\n .select(['name', 'executed_at'])\n .where('change_type', '=', 'change')\n .where('direction', '=', 'revert')\n .where('status', '=', 'success')\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc')\n .execute(),\n );\n\n if (reverts) {\n\n // Track which ones we've seen\n const seenReverts = new Set<string>();\n\n for (const revert of reverts) {\n\n if (!seenReverts.has(revert.name) && statuses.has(revert.name)) {\n\n const status = statuses.get(revert.name)!;\n status.revertedAt = revert.executed_at;\n seenReverts.add(revert.name);\n\n }\n\n }\n\n }\n\n return statuses;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Change Detection\n // ─────────────────────────────────────────────────────────\n\n /**\n * Check if a change needs to run.\n *\n * @param name - Change name\n * @param checksum - Current checksum of change files\n * @param force - Force re-run regardless of status\n * @returns Whether the change needs to run and why\n */\n async needsRun(name: string, checksum: string, force: boolean): Promise<NeedsRunResult> {\n\n // Force always runs\n if (force) {\n\n return { needsRun: true, reason: 'force' };\n\n }\n\n // Get most recent change record\n const [record, err] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.change)\n .select(['status', 'checksum'])\n .where('name', '=', name)\n .where('change_type', '=', 'change')\n .where('direction', '=', 'change')\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc')\n .limit(1)\n .executeTakeFirst(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { name, operation: 'needs-run-check' },\n });\n\n // On error, assume needs to run\n return { needsRun: true, reason: 'new' };\n\n }\n\n // No previous record - new change\n if (!record) {\n\n return { needsRun: true, reason: 'new' };\n\n }\n\n // Previous execution failed - retry\n if (record.status === 'failed') {\n\n return {\n needsRun: true,\n reason: 'failed',\n previousChecksum: record.checksum,\n previousStatus: record.status,\n };\n\n }\n\n // Previous execution was reverted - can re-apply\n if (record.status === 'reverted') {\n\n return {\n needsRun: true,\n reason: 'reverted',\n previousChecksum: record.checksum,\n previousStatus: record.status,\n };\n\n }\n\n // Previous execution is stale (schema torn down) - needs re-apply\n if (record.status === 'stale') {\n\n return {\n needsRun: true,\n reason: 'stale',\n previousChecksum: record.checksum,\n previousStatus: record.status,\n };\n\n }\n\n // Checksum changed\n if (record.checksum !== checksum) {\n\n return {\n needsRun: true,\n reason: 'changed',\n previousChecksum: record.checksum,\n previousStatus: record.status,\n };\n\n }\n\n // Success and unchanged - skip\n return {\n needsRun: false,\n skipReason: 'already applied',\n previousChecksum: record.checksum,\n previousStatus: record.status,\n };\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Create Records\n // ─────────────────────────────────────────────────────────\n //\n // NOTE: canRevert has been moved to ChangeTracker.\n //\n\n /**\n * Create a new operation record.\n *\n * @returns The created operation's ID\n */\n async createOperation(data: {\n name: string;\n direction: Direction;\n executedBy: string;\n }): Promise<number> {\n\n const [result, err] = await attempt(() =>\n this.#db\n .insertInto(NOORM_TABLES.change)\n .values({\n name: data.name,\n change_type: 'change',\n direction: data.direction,\n status: 'pending',\n config_name: this.#configName,\n executed_by: data.executedBy,\n })\n .returning('id')\n .executeTakeFirstOrThrow(),\n );\n\n if (err) {\n\n throw new Error('Failed to create change operation record', { cause: err });\n\n }\n\n // Validate the returned ID\n // Note: SQLite with better-sqlite3 may return null for RETURNING clause\n // In that case, fall back to last_insert_rowid()\n let id = result?.id;\n\n if (id === null || id === undefined) {\n\n const [lastIdResult, lastIdErr] = await attempt(() =>\n sql<{ id: number }>`SELECT last_insert_rowid() as id`.execute(this.#db),\n );\n\n if (lastIdErr || !lastIdResult?.rows?.[0]?.id) {\n\n throw new Error('Failed to retrieve last insert row id');\n\n }\n\n id = lastIdResult.rows[0].id;\n\n }\n\n if (typeof id !== 'number' || !Number.isFinite(id) || id <= 0) {\n\n throw new Error(`Invalid operation ID returned: ${id}`);\n\n }\n\n return id;\n\n }\n\n /**\n * Create pending file records for all files.\n *\n * Creates records upfront so we can mark remaining as skipped on failure.\n *\n * @returns Error message if creation failed, null on success\n */\n async createFileRecords(\n operationId: number,\n files: Array<{\n filepath: string;\n fileType: FileType;\n checksum: string;\n }>,\n ): Promise<string | null> {\n\n if (files.length === 0) return null;\n\n const values = files.map((f) => ({\n change_id: operationId,\n filepath: f.filepath,\n file_type: f.fileType,\n checksum: f.checksum,\n status: 'pending' as ExecutionStatus,\n }));\n\n const [, err] = await attempt(() =>\n this.#db.insertInto(NOORM_TABLES.executions).values(values).execute(),\n );\n\n if (err) {\n\n const errMsg = err instanceof Error ? err.message : String(err);\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { operationId, operation: 'create-file-records' },\n });\n\n return `Failed to create file records: ${errMsg}`;\n\n }\n\n return null;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Update Records\n // ─────────────────────────────────────────────────────────\n\n /**\n * Update a file execution record.\n *\n * @returns Error message if update failed, null on success\n */\n async updateFileExecution(\n operationId: number,\n filepath: string,\n status: ExecutionStatus,\n durationMs: number,\n errorMessage?: string,\n skipReason?: string,\n ): Promise<string | null> {\n\n const [result, err] = await attempt(() =>\n this.#db\n .updateTable(NOORM_TABLES.executions)\n .set({\n status,\n duration_ms: Math.round(durationMs),\n error_message: errorMessage ?? '',\n skip_reason: skipReason ?? '',\n })\n .where('change_id', '=', operationId)\n .where('filepath', '=', filepath)\n .executeTakeFirst(),\n );\n\n if (err) {\n\n const errMsg = err instanceof Error ? err.message : String(err);\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { filepath, operation: 'update-file-execution' },\n });\n\n return `Failed to update file execution ${filepath}: ${errMsg}`;\n\n }\n\n // Check if any rows were updated\n const numUpdated = Number(result?.numUpdatedRows ?? 0);\n\n if (numUpdated === 0) {\n\n const errMsg = `No execution record found for ${filepath} (operationId: ${operationId})`;\n\n observer.emit('error', {\n source: 'change',\n error: new Error(errMsg),\n context: { operationId, filepath, operation: 'update-file-execution' },\n });\n\n return errMsg;\n\n }\n\n return null;\n\n }\n\n /**\n * Mark remaining files as skipped after failure.\n *\n * @returns Error message if skip failed, null on success\n */\n async skipRemainingFiles(operationId: number, reason: string): Promise<string | null> {\n\n const [, err] = await attempt(() =>\n this.#db\n .updateTable(NOORM_TABLES.executions)\n .set({\n status: 'skipped',\n skip_reason: reason,\n })\n .where('change_id', '=', operationId)\n .where('status', '=', 'pending')\n .execute(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { operationId, operation: 'skip-remaining-files' },\n });\n\n return `Failed to skip remaining files: ${err instanceof Error ? err.message : String(err)}`;\n\n }\n\n return null;\n\n }\n\n /**\n * Finalize an operation.\n *\n * @returns Error message if finalization failed, null on success\n */\n async finalizeOperation(\n operationId: number,\n status: OperationStatus,\n checksum: string,\n durationMs: number,\n errorMessage?: string,\n ): Promise<string | null> {\n\n // Truncate error message if too long (some DBs have limits)\n const truncatedError = errorMessage ? errorMessage.slice(0, 2000) : '';\n\n const [result, err] = await attempt(() =>\n this.#db\n .updateTable(NOORM_TABLES.change)\n .set({\n status,\n checksum,\n duration_ms: Math.round(durationMs),\n error_message: truncatedError,\n })\n .where('id', '=', operationId)\n .executeTakeFirst(),\n );\n\n if (err) {\n\n const errMsg = err instanceof Error ? err.message : String(err);\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { operationId, operation: 'finalize-operation' },\n });\n\n // Return error instead of throwing - let caller decide how to handle\n return `Failed to finalize operation ${operationId}: ${errMsg}`;\n\n }\n\n // Check if any rows were updated\n const numUpdated = Number(result?.numUpdatedRows ?? 0);\n\n if (numUpdated === 0) {\n\n const errMsg = `No operation record found with id ${operationId}`;\n\n observer.emit('error', {\n source: 'change',\n error: new Error(errMsg),\n context: { operationId, operation: 'finalize-operation' },\n });\n\n return errMsg;\n\n }\n\n return null;\n\n }\n\n // NOTE: markAsReverted and markAllAsStale have been moved to ChangeTracker.\n\n /**\n * Record a database reset event.\n *\n * Creates a special change entry to document when the database\n * was torn down. Provides audit trail for reset operations.\n *\n * @param executedBy - Identity of who performed the reset\n * @param reason - Optional reason for the reset\n * @returns The created record's ID\n */\n async recordReset(executedBy: string, reason?: string): Promise<number> {\n\n const [result, err] = await attempt(() =>\n this.#db\n .insertInto(NOORM_TABLES.change)\n .values({\n name: '__reset__',\n change_type: 'change',\n direction: 'change',\n status: 'success',\n config_name: this.#configName,\n executed_by: executedBy,\n error_message: reason ?? '',\n duration_ms: 0,\n checksum: '',\n })\n .returning('id')\n .executeTakeFirstOrThrow(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { operation: 'record-reset' },\n });\n\n return 0;\n\n }\n\n return result.id;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Delete Records\n // ─────────────────────────────────────────────────────────\n\n /**\n * Delete all records for a change.\n */\n async deleteRecords(name: string): Promise<void> {\n\n // First get all operation IDs for this change\n const [operations, queryErr] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.change)\n .select(['id'])\n .where('name', '=', name)\n .where('change_type', '=', 'change')\n .where('config_name', '=', this.#configName)\n .execute(),\n );\n\n if (queryErr || !operations || operations.length === 0) {\n\n return;\n\n }\n\n const operationIds = operations.map((o) => o.id);\n\n // Delete execution records\n const [, execErr] = await attempt(() =>\n this.#db\n .deleteFrom(NOORM_TABLES.executions)\n .where('change_id', 'in', operationIds)\n .execute(),\n );\n\n if (execErr) {\n\n observer.emit('error', {\n source: 'change',\n error: execErr,\n context: { name, operation: 'delete-executions' },\n });\n\n }\n\n // Delete change records\n const [, changeErr] = await attempt(() =>\n this.#db.deleteFrom(NOORM_TABLES.change).where('id', 'in', operationIds).execute(),\n );\n\n if (changeErr) {\n\n observer.emit('error', {\n source: 'change',\n error: changeErr,\n context: { name, operation: 'delete-change' },\n });\n\n }\n\n }\n\n // ─────────────────────────────────────────────────────────\n // History Queries\n // ─────────────────────────────────────────────────────────\n\n /**\n * Get execution history for a change.\n *\n * @param name - Change name (optional, all if not provided)\n * @param limit - Max records to return\n */\n async getHistory(name?: string, limit?: number): Promise<ChangeHistoryRecord[]> {\n\n let query = this.#db\n .selectFrom(NOORM_TABLES.change)\n .select([\n 'id',\n 'name',\n 'direction',\n 'status',\n 'executed_at',\n 'executed_by',\n 'duration_ms',\n 'error_message',\n 'checksum',\n ])\n .where('change_type', '=', 'change')\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc');\n\n if (name) {\n\n query = query.where('name', '=', name);\n\n }\n\n if (limit) {\n\n query = query.limit(limit);\n\n }\n\n const [records, err] = await attempt(() => query.execute());\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { name, operation: 'get-history' },\n });\n\n return [];\n\n }\n\n return records.map((r) => ({\n id: r.id,\n name: r.name,\n direction: r.direction,\n status: r.status,\n executedAt: r.executed_at,\n executedBy: r.executed_by,\n durationMs: r.duration_ms,\n errorMessage: r.error_message || null,\n checksum: r.checksum,\n }));\n\n }\n\n /**\n * Get unified execution history across all operation types.\n *\n * Unlike getHistory() which only returns changes, this returns\n * builds, runs, and changes in a unified view.\n *\n * @param changeTypes - Optional filter for specific types (default: all)\n * @param limit - Max records to return\n */\n async getUnifiedHistory(\n changeTypes?: ChangeType[],\n limit?: number,\n ): Promise<UnifiedHistoryRecord[]> {\n\n let query = this.#db\n .selectFrom(NOORM_TABLES.change)\n .select([\n 'id',\n 'name',\n 'change_type',\n 'direction',\n 'status',\n 'executed_at',\n 'executed_by',\n 'duration_ms',\n 'error_message',\n 'checksum',\n ])\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc');\n\n // Filter by change types if specified\n if (changeTypes && changeTypes.length > 0) {\n\n query = query.where('change_type', 'in', changeTypes);\n\n }\n\n if (limit) {\n\n query = query.limit(limit);\n\n }\n\n const [records, err] = await attempt(() => query.execute());\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { operation: 'get-unified-history' },\n });\n\n return [];\n\n }\n\n return records.map((r) => ({\n id: r.id,\n name: r.name,\n changeType: r.change_type,\n direction: r.direction,\n status: r.status,\n executedAt: r.executed_at,\n executedBy: r.executed_by,\n durationMs: r.duration_ms,\n errorMessage: r.error_message || null,\n checksum: r.checksum,\n }));\n\n }\n\n /**\n * Get build and run history only (excludes changes).\n *\n * Convenience method for screens that want to show only\n * build/run operations.\n *\n * @param limit - Max records to return\n */\n async getBuildRunHistory(limit?: number): Promise<UnifiedHistoryRecord[]> {\n\n return this.getUnifiedHistory(['build', 'run'], limit);\n\n }\n\n /**\n * Get file execution records for an operation.\n */\n async getFileHistory(operationId: number): Promise<FileHistoryRecord[]> {\n\n const [records, err] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.executions)\n .select([\n 'id',\n 'change_id',\n 'filepath',\n 'file_type',\n 'checksum',\n 'status',\n 'skip_reason',\n 'error_message',\n 'duration_ms',\n ])\n .where('change_id', '=', operationId)\n .orderBy('id', 'asc')\n .execute(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { operationId, operation: 'get-file-history' },\n });\n\n return [];\n\n }\n\n return records.map((r) => ({\n id: r.id,\n changeId: r.change_id,\n filepath: r.filepath,\n fileType: r.file_type as 'sql' | 'txt',\n checksum: r.checksum,\n status: r.status,\n skipReason: r.skip_reason || null,\n errorMessage: r.error_message || null,\n durationMs: r.duration_ms,\n }));\n\n }\n\n /**\n * Get all orphaned changes (in DB but not on disk).\n *\n * @param diskNames - Set of change names on disk\n */\n async getOrphaned(diskNames: Set<string>): Promise<string[]> {\n\n const statuses = await this.getAllStatuses();\n const orphaned: string[] = [];\n\n for (const [name] of statuses) {\n\n if (!diskNames.has(name)) {\n\n orphaned.push(name);\n\n }\n\n }\n\n return orphaned;\n\n }\n\n}\n","/**\n * Execution tracker.\n *\n * Manages database records for tracking SQL file executions.\n * Provides change detection by comparing checksums against\n * previous executions.\n *\n * WHY: Idempotent builds require knowing which files have changed.\n * The tracker maintains an audit trail in __noorm_change__ and\n * __noorm_executions__ tables.\n *\n * @example\n * ```typescript\n * import { Tracker } from './tracker'\n *\n * const tracker = new Tracker(db, 'dev')\n *\n * // Check if file needs to run\n * const result = await tracker.needsRun('/path/to/file.sql', 'abc123', false)\n *\n * // Create operation and record executions\n * const opId = await tracker.createOperation({ name: 'build:...', ... })\n * await tracker.recordExecution({ changeId: opId, filepath: '...', ... })\n * ```\n */\nimport type { Kysely } from 'kysely';\nimport { sql } from 'kysely';\n\nimport { attempt } from '@logosdx/utils';\n\nimport { observer } from '../observer.js';\nimport { NOORM_TABLES } from '../shared/index.js';\nimport type { NoormDatabase, ChangeType, ExecutionStatus, FileType } from '../shared/index.js';\nimport type { NeedsRunResult, CreateOperationData, RecordExecutionData, Direction } from './types.js';\n\n/**\n * Execution tracker for change detection and audit logging.\n *\n * @example\n * ```typescript\n * const tracker = new Tracker(db, 'production')\n *\n * // Start a build operation\n * const opId = await tracker.createOperation({\n * name: 'build:2024-01-15T10:30:00',\n * changeType: 'build',\n * configName: 'production',\n * executedBy: 'Alice <alice@example.com>',\n * })\n *\n * // Record each file execution\n * await tracker.recordExecution({\n * changeId: opId,\n * filepath: '/project/sql/001.sql',\n * checksum: 'abc123...',\n * status: 'success',\n * durationMs: 42,\n * })\n *\n * // Finalize the operation\n * await tracker.finalizeOperation(opId, 'success', 1234)\n * ```\n */\nexport class Tracker {\n\n readonly #db: Kysely<NoormDatabase>;\n readonly #configName: string;\n\n constructor(db: Kysely<NoormDatabase>, configName: string) {\n\n this.#db = db;\n this.#configName = configName;\n\n }\n\n /**\n * Check if a file needs to run.\n *\n * A file needs to run if:\n * - Force flag is set\n * - No previous execution exists (new file)\n * - Previous execution failed\n * - Parent change is stale (schema was torn down)\n * - Checksum differs (file changed)\n *\n * @param filepath - File path to check\n * @param checksum - Current file checksum\n * @param force - Force re-run regardless of status\n * @returns Whether file needs to run and why\n */\n async needsRun(filepath: string, checksum: string, force: boolean): Promise<NeedsRunResult> {\n\n // Force always runs\n if (force) {\n\n return { needsRun: true, reason: 'force' };\n\n }\n\n // Find most recent execution for this file and config\n // Also fetch the parent change status to check for stale\n const [record, err] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.executions)\n .innerJoin(\n NOORM_TABLES.change,\n `${NOORM_TABLES.change}.id`,\n `${NOORM_TABLES.executions}.change_id`,\n )\n .select((eb) => [\n eb.ref(`${NOORM_TABLES.executions}.checksum`).as('checksum'),\n eb.ref(`${NOORM_TABLES.executions}.status`).as('exec_status'),\n eb.ref(`${NOORM_TABLES.change}.status`).as('change_status'),\n ])\n .where(`${NOORM_TABLES.executions}.filepath`, '=', filepath)\n .where(`${NOORM_TABLES.change}.config_name`, '=', this.#configName)\n .orderBy(`${NOORM_TABLES.executions}.id`, 'desc')\n .limit(1)\n .executeTakeFirst(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'runner',\n error: err,\n context: { filepath, operation: 'needs-run-check' },\n });\n\n // On error, assume file needs to run\n return { needsRun: true, reason: 'new' };\n\n }\n\n // No previous record - new file\n if (!record) {\n\n return { needsRun: true, reason: 'new' };\n\n }\n\n // Previous execution failed - retry\n if (record.exec_status === 'failed') {\n\n return {\n needsRun: true,\n reason: 'failed',\n previousChecksum: record.checksum,\n };\n\n }\n\n // Previous execution is pending or skipped - needs to run\n // This handles records created upfront for batch visibility\n if (record.exec_status === 'pending' || record.exec_status === 'skipped') {\n\n return { needsRun: true, reason: 'new' };\n\n }\n\n // Parent change is stale (schema was torn down) - needs re-run\n if (record.change_status === 'stale') {\n\n return {\n needsRun: true,\n reason: 'stale',\n previousChecksum: record.checksum,\n };\n\n }\n\n // Checksum changed\n if (record.checksum !== checksum) {\n\n return {\n needsRun: true,\n reason: 'changed',\n previousChecksum: record.checksum,\n };\n\n }\n\n // Unchanged - skip\n return {\n needsRun: false,\n skipReason: 'unchanged',\n previousChecksum: record.checksum,\n };\n\n }\n\n /**\n * Create a new operation record.\n *\n * Operations are parent records in __noorm_change__ that\n * group individual file executions.\n *\n * @param data - Operation data\n * @returns The created operation's ID\n */\n async createOperation(data: CreateOperationData): Promise<number> {\n\n // Direction defaults to 'commit' (forward execution)\n const direction: Direction = data.direction ?? 'commit';\n\n // Map direction to database value\n // 'commit' is stored as 'change' for historical compatibility\n const dbDirection = direction === 'commit' ? 'change' : 'revert';\n\n const [result, err] = await attempt(() =>\n this.#db\n .insertInto(NOORM_TABLES.change)\n .values({\n name: data.name,\n change_type: data.changeType as ChangeType,\n direction: dbDirection,\n status: 'pending',\n config_name: data.configName,\n executed_by: data.executedBy,\n })\n .returning('id')\n .executeTakeFirstOrThrow(),\n );\n\n if (err) {\n\n throw new Error('Failed to create operation record', { cause: err });\n\n }\n\n // Validate the returned ID\n // Note: SQLite with better-sqlite3 may return null for RETURNING clause\n // In that case, fall back to last_insert_rowid()\n let id = result?.id;\n\n if (id === null || id === undefined) {\n\n const [lastIdResult, lastIdErr] = await attempt(() =>\n sql<{ id: number }>`SELECT last_insert_rowid() as id`.execute(this.#db),\n );\n\n if (lastIdErr || !lastIdResult?.rows?.[0]?.id) {\n\n throw new Error('Failed to retrieve last insert row id');\n\n }\n\n id = lastIdResult.rows[0].id;\n\n }\n\n if (typeof id !== 'number' || !Number.isFinite(id) || id <= 0) {\n\n throw new Error(`Invalid operation ID returned: ${id}`);\n\n }\n\n return id;\n\n }\n\n /**\n * Record a file execution.\n *\n * Creates a child record in __noorm_executions__ linked\n * to the parent operation.\n *\n * @param data - Execution data\n */\n async recordExecution(data: RecordExecutionData): Promise<void> {\n\n const [, err] = await attempt(() =>\n this.#db\n .insertInto(NOORM_TABLES.executions)\n .values({\n change_id: data.changeId,\n filepath: data.filepath,\n file_type: 'sql',\n checksum: data.checksum,\n status: data.status as ExecutionStatus,\n skip_reason: data.skipReason ?? '',\n error_message: data.errorMessage ?? '',\n duration_ms: Math.round(data.durationMs ?? 0),\n })\n .execute(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'runner',\n error: err,\n context: { filepath: data.filepath, operation: 'record-execution' },\n });\n\n }\n\n }\n\n /**\n * Finalize an operation.\n *\n * Updates the parent record with final status and duration.\n *\n * @param operationId - Operation ID to update\n * @param status - Final status\n * @param durationMs - Total duration\n * @param checksum - Combined checksum of all files\n * @param errorMessage - Error message if failed\n * @returns Error message if finalization failed, null on success\n */\n async finalizeOperation(\n operationId: number,\n status: 'success' | 'failed',\n durationMs: number,\n checksum?: string,\n errorMessage?: string,\n ): Promise<string | null> {\n\n // Truncate error message if too long (some DBs have limits)\n const truncatedError = errorMessage ? errorMessage.slice(0, 2000) : '';\n\n const [result, err] = await attempt(() =>\n this.#db\n .updateTable(NOORM_TABLES.change)\n .set({\n status,\n duration_ms: Math.round(durationMs),\n checksum: checksum ?? '',\n error_message: truncatedError,\n })\n .where('id', '=', operationId)\n .executeTakeFirst(),\n );\n\n if (err) {\n\n const errMsg = err instanceof Error ? err.message : String(err);\n\n observer.emit('error', {\n source: 'runner',\n error: err,\n context: { operationId, operation: 'finalize-operation' },\n });\n\n return `Failed to finalize operation ${operationId}: ${errMsg}`;\n\n }\n\n // Check if any rows were updated\n const numUpdated = Number(result?.numUpdatedRows ?? 0);\n\n if (numUpdated === 0) {\n\n const errMsg = `No operation record found with id ${operationId}`;\n\n observer.emit('error', {\n source: 'runner',\n error: new Error(errMsg),\n context: { operationId, operation: 'finalize-operation' },\n });\n\n return errMsg;\n\n }\n\n return null;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Batch File Operations (Shared by Runner and Changes)\n // ─────────────────────────────────────────────────────────\n\n /**\n * Create pending file records for all files upfront.\n *\n * Creates records so the batch is fully visible. On failure,\n * remaining files can be marked as skipped.\n *\n * @param operationId - Parent operation ID\n * @param files - Files to create records for\n * @returns Error message if creation failed, null on success\n */\n async createFileRecords(\n operationId: number,\n files: Array<{\n filepath: string;\n fileType: FileType;\n checksum: string;\n }>,\n ): Promise<string | null> {\n\n if (files.length === 0) return null;\n\n const values = files.map((f) => ({\n change_id: operationId,\n filepath: f.filepath,\n file_type: f.fileType,\n checksum: f.checksum,\n status: 'pending' as ExecutionStatus,\n }));\n\n const [, err] = await attempt(() =>\n this.#db.insertInto(NOORM_TABLES.executions).values(values).execute(),\n );\n\n if (err) {\n\n const errMsg = err instanceof Error ? err.message : String(err);\n\n observer.emit('error', {\n source: 'runner',\n error: err,\n context: { operationId, operation: 'create-file-records' },\n });\n\n return `Failed to create file records: ${errMsg}`;\n\n }\n\n return null;\n\n }\n\n /**\n * Update a file execution record.\n *\n * Updates an existing pending record with execution results.\n *\n * @param operationId - Parent operation ID\n * @param filepath - File path to update\n * @param status - Execution status\n * @param durationMs - Execution time\n * @param errorMessage - Error message if failed\n * @param skipReason - Skip reason if skipped\n * @returns Error message if update failed, null on success\n */\n async updateFileExecution(\n operationId: number,\n filepath: string,\n status: ExecutionStatus,\n durationMs: number,\n errorMessage?: string,\n skipReason?: string,\n ): Promise<string | null> {\n\n const [result, err] = await attempt(() =>\n this.#db\n .updateTable(NOORM_TABLES.executions)\n .set({\n status,\n duration_ms: Math.round(durationMs),\n error_message: errorMessage ?? '',\n skip_reason: skipReason ?? '',\n })\n .where('change_id', '=', operationId)\n .where('filepath', '=', filepath)\n .executeTakeFirst(),\n );\n\n if (err) {\n\n const errMsg = err instanceof Error ? err.message : String(err);\n\n observer.emit('error', {\n source: 'runner',\n error: err,\n context: { filepath, operation: 'update-file-execution' },\n });\n\n return `Failed to update file execution ${filepath}: ${errMsg}`;\n\n }\n\n // Check if any rows were updated\n const numUpdated = Number(result?.numUpdatedRows ?? 0);\n\n if (numUpdated === 0) {\n\n const errMsg = `No execution record found for ${filepath} (operationId: ${operationId})`;\n\n observer.emit('error', {\n source: 'runner',\n error: new Error(errMsg),\n context: { operationId, filepath, operation: 'update-file-execution' },\n });\n\n return errMsg;\n\n }\n\n return null;\n\n }\n\n /**\n * Mark remaining pending files as skipped.\n *\n * Called when execution stops early (failure or abort).\n * Updates all pending records for this operation to skipped.\n *\n * @param operationId - Parent operation ID\n * @param reason - Why files were skipped\n * @returns Error message if skip failed, null on success\n */\n async skipRemainingFiles(operationId: number, reason: string): Promise<string | null> {\n\n const [, err] = await attempt(() =>\n this.#db\n .updateTable(NOORM_TABLES.executions)\n .set({\n status: 'skipped',\n skip_reason: reason,\n })\n .where('change_id', '=', operationId)\n .where('status', '=', 'pending')\n .execute(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'runner',\n error: err,\n context: { operationId, operation: 'skip-remaining-files' },\n });\n\n return `Failed to skip remaining files: ${err instanceof Error ? err.message : String(err)}`;\n\n }\n\n return null;\n\n }\n\n /**\n * Check if a change needs to run by name.\n *\n * Similar to needsRun but checks by change name instead of filepath.\n * Used for change sets where we track by change name, not individual files.\n *\n * @param name - Change name\n * @param checksum - Current checksum of change files\n * @param force - Force re-run regardless of status\n * @returns Whether the change needs to run and why\n */\n async needsRunByName(name: string, checksum: string, force: boolean): Promise<NeedsRunResult> {\n\n // Force always runs\n if (force) {\n\n return { needsRun: true, reason: 'force' };\n\n }\n\n // Get most recent change record for this name\n // Note: Database stores 'change' for forward direction (legacy naming)\n const [record, err] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.change)\n .select(['status', 'checksum'])\n .where('name', '=', name)\n .where('direction', '=', 'change') // 'change' = forward/commit in DB\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc')\n .limit(1)\n .executeTakeFirst(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'runner',\n error: err,\n context: { name, operation: 'needs-run-by-name' },\n });\n\n // On error, assume needs to run\n return { needsRun: true, reason: 'new' };\n\n }\n\n // No previous record - new change\n if (!record) {\n\n return { needsRun: true, reason: 'new' };\n\n }\n\n // Previous execution failed - retry\n if (record.status === 'failed') {\n\n return {\n needsRun: true,\n reason: 'failed',\n previousChecksum: record.checksum,\n };\n\n }\n\n // Previous execution was reverted - can re-apply\n if (record.status === 'reverted') {\n\n return {\n needsRun: true,\n reason: 'stale', // Use 'stale' since 'reverted' isn't in RunReason\n previousChecksum: record.checksum,\n };\n\n }\n\n // Previous execution is stale (schema torn down) - needs re-apply\n if (record.status === 'stale') {\n\n return {\n needsRun: true,\n reason: 'stale',\n previousChecksum: record.checksum,\n };\n\n }\n\n // Checksum changed\n if (record.checksum !== checksum) {\n\n return {\n needsRun: true,\n reason: 'changed',\n previousChecksum: record.checksum,\n };\n\n }\n\n // Success and unchanged - skip\n return {\n needsRun: false,\n skipReason: 'already-run',\n previousChecksum: record.checksum,\n };\n\n }\n\n}\n","/**\n * Change-specific tracker.\n *\n * Extends the base Tracker with change-specific operations like\n * revert handling and stale marking.\n *\n * WHY: Changes have special operations that don't apply to builds/runs:\n * - Revert support (check if can revert, mark as reverted)\n * - Stale marking (after teardown, all applied changes become stale)\n *\n * @example\n * ```typescript\n * import { ChangeTracker } from './tracker'\n *\n * const tracker = new ChangeTracker(db, 'production')\n *\n * // Check if change can be reverted\n * const result = await tracker.canRevert('2024-01-15-add-users', false)\n *\n * // Mark original change as reverted\n * await tracker.markAsReverted('2024-01-15-add-users')\n *\n * // After teardown, mark all as stale\n * await tracker.markAllAsStale()\n * ```\n */\nimport { attempt } from '@logosdx/utils';\n\nimport { Tracker } from '../runner/tracker.js';\nimport { observer } from '../observer.js';\nimport { NOORM_TABLES } from '../shared/index.js';\nimport type { NoormDatabase, OperationStatus } from '../shared/index.js';\nimport type { Kysely } from 'kysely';\n\n// ─────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Result of checking if a change can be reverted.\n */\nexport interface CanRevertResult {\n /** Whether revert is allowed */\n canRevert: boolean;\n\n /** Reason why revert is not allowed (if canRevert is false) */\n reason?: string;\n\n /** Current status of the change */\n status?: OperationStatus;\n}\n\n// ─────────────────────────────────────────────────────────────\n// ChangeTracker Class\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Change-specific tracker.\n *\n * Extends Tracker with operations specific to change management:\n * - Revert checking and marking\n * - Stale marking after teardown\n *\n * @example\n * ```typescript\n * const tracker = new ChangeTracker(db, 'dev')\n *\n * // Use inherited methods from Tracker\n * const opId = await tracker.createOperation({\n * name: 'my-change',\n * changeType: 'change',\n * direction: 'commit',\n * configName: 'dev',\n * executedBy: 'user@example.com',\n * })\n *\n * // Use change-specific methods\n * const canRevert = await tracker.canRevert('my-change', false)\n * ```\n */\nexport class ChangeTracker extends Tracker {\n\n // Store db and configName for change-specific queries\n // (Tracker uses private fields, so we need our own references)\n readonly #db: Kysely<NoormDatabase>;\n readonly #configName: string;\n\n constructor(db: Kysely<NoormDatabase>, configName: string) {\n\n super(db, configName);\n this.#db = db;\n this.#configName = configName;\n\n }\n\n /**\n * Check if a change can be reverted.\n *\n * @param name - Change name\n * @param force - Force revert regardless of status\n * @returns Whether revert is allowed and current status\n */\n async canRevert(name: string, force: boolean): Promise<CanRevertResult> {\n\n // Get most recent change record\n const [record, err] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.change)\n .select(['status'])\n .where('name', '=', name)\n .where('change_type', '=', 'change')\n .where('direction', '=', 'change') // 'change' = forward/commit in DB\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc')\n .limit(1)\n .executeTakeFirst(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { name, operation: 'can-revert' },\n });\n\n return { canRevert: false, reason: 'database error' };\n\n }\n\n if (!record) {\n\n return { canRevert: false, reason: 'not applied' };\n\n }\n\n if (force) {\n\n return { canRevert: true, status: record.status };\n\n }\n\n switch (record.status) {\n\n case 'pending':\n return { canRevert: false, reason: 'not applied yet', status: record.status };\n\n case 'success':\n return { canRevert: true, status: record.status };\n\n case 'failed':\n return { canRevert: true, status: record.status };\n\n case 'reverted':\n return { canRevert: false, reason: 'already reverted', status: record.status };\n\n case 'stale':\n return { canRevert: false, reason: 'schema was torn down', status: record.status };\n\n default:\n return { canRevert: false, reason: 'unknown status' };\n\n }\n\n }\n\n /**\n * Mark the original change record as reverted.\n *\n * Called after successful revert.\n *\n * @param name - Change name to mark as reverted\n */\n async markAsReverted(name: string): Promise<void> {\n\n // Find the most recent 'change' record\n const [record] = await attempt(() =>\n this.#db\n .selectFrom(NOORM_TABLES.change)\n .select(['id'])\n .where('name', '=', name)\n .where('change_type', '=', 'change')\n .where('direction', '=', 'change')\n .where('config_name', '=', this.#configName)\n .orderBy('id', 'desc')\n .limit(1)\n .executeTakeFirst(),\n );\n\n if (record) {\n\n await attempt(() =>\n this.#db\n .updateTable(NOORM_TABLES.change)\n .set({ status: 'reverted' })\n .where('id', '=', record.id)\n .execute(),\n );\n\n }\n\n }\n\n /**\n * Mark all operation records as stale.\n *\n * Called during teardown to indicate schema objects no longer exist.\n * Marks changes, builds, and runs - all types that created schema objects.\n * Marks 'success', 'failed', and 'pending' records - anything that might have\n * created schema objects needs to be re-run after teardown.\n *\n * @returns Number of records marked as stale\n */\n async markAllAsStale(): Promise<number> {\n\n const [result, err] = await attempt(() =>\n this.#db\n .updateTable(NOORM_TABLES.change)\n .set({ status: 'stale' })\n .where('direction', '=', 'change') // Only forward operations\n .where('status', 'in', ['success', 'failed', 'pending'])\n .where('config_name', '=', this.#configName)\n .execute(),\n );\n\n if (err) {\n\n observer.emit('error', {\n source: 'change',\n error: err,\n context: { operation: 'mark-all-stale' },\n });\n\n return 0;\n\n }\n\n return result.reduce((acc, r) => acc + Number(r.numUpdatedRows ?? 0), 0);\n\n }\n\n}\n","/**\n * File checksum utilities.\n *\n * Computes SHA-256 hashes for change detection. Files are re-executed\n * only when their checksum changes, enabling idempotent builds.\n *\n * WHY SHA-256: Cryptographically strong, fast enough for our use case,\n * and produces fixed-length output suitable for database storage.\n *\n * @example\n * ```typescript\n * import { computeChecksum, computeChecksumFromContent } from './checksum'\n *\n * const hash = await computeChecksum('/path/to/file.sql')\n * const hash2 = computeChecksumFromContent('SELECT 1;')\n * ```\n */\nimport { createHash } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\n\nimport { attempt } from '@logosdx/utils';\n\n/**\n * Compute SHA-256 checksum of a file.\n *\n * @param filepath - Absolute path to the file\n * @returns SHA-256 hash as hex string\n * @throws Error if file cannot be read\n *\n * @example\n * ```typescript\n * const hash = await computeChecksum('/project/sql/001_users.sql')\n * // => 'a3f2b8c9d4e5...'\n * ```\n */\nexport async function computeChecksum(filepath: string): Promise<string> {\n\n const [content, err] = await attempt(() => readFile(filepath, 'utf-8'));\n\n if (err) {\n\n throw new Error(`Failed to read file for checksum: ${filepath}`, { cause: err });\n\n }\n\n return computeChecksumFromContent(content);\n\n}\n\n/**\n * Compute SHA-256 checksum from string content.\n *\n * Useful for computing checksums of rendered templates or\n * for testing without file I/O.\n *\n * @param content - String content to hash\n * @returns SHA-256 hash as hex string\n *\n * @example\n * ```typescript\n * const hash = computeChecksumFromContent('CREATE TABLE users (...);')\n * // => 'b4c7d8e9f0a1...'\n * ```\n */\nexport function computeChecksumFromContent(content: string): string {\n\n return createHash('sha256').update(content, 'utf-8').digest('hex');\n\n}\n\n/**\n * Compute combined checksum for multiple files.\n *\n * Creates a deterministic checksum by sorting file checksums\n * alphabetically and hashing the concatenated result.\n *\n * WHY: Build operations need a single checksum representing\n * the entire set of files. Sorting ensures the same files\n * always produce the same combined hash regardless of order.\n *\n * @param checksums - Array of individual file checksums\n * @returns Combined SHA-256 hash\n *\n * @example\n * ```typescript\n * const combined = computeCombinedChecksum([\n * 'abc123...',\n * 'def456...',\n * ])\n * ```\n */\nexport function computeCombinedChecksum(checksums: string[]): string {\n\n const sorted = [...checksums].sort();\n const combined = sorted.join('');\n\n return createHash('sha256').update(combined, 'utf-8').digest('hex');\n\n}\n","/**\n * Lock manager types.\n *\n * Defines the shape of locks and options for acquiring them.\n * Used to prevent concurrent operations on the same database.\n *\n * WHY: Concurrent DDL operations can corrupt database state.\n * Locks ensure only one process modifies the schema at a time.\n */\n\n/**\n * Lock state returned after acquisition.\n *\n * @example\n * ```typescript\n * const lock = await lockManager.acquire('dev', 'alice@example.com')\n * console.log(lock.lockedBy) // 'alice@example.com'\n * console.log(lock.expiresAt) // Date object\n * ```\n */\nexport interface Lock {\n /** Identity string of holder */\n lockedBy: string;\n\n /** When acquired */\n lockedAt: Date;\n\n /** Auto-expiry time */\n expiresAt: Date;\n\n /** Optional reason for acquiring */\n reason?: string;\n}\n\n/**\n * Options for acquiring a lock.\n *\n * @example\n * ```typescript\n * // Wait up to 30s for lock, polling every 500ms\n * const options: LockOptions = {\n * timeout: 60_000, // Lock expires after 60s\n * wait: true, // Block until available\n * waitTimeout: 30_000, // Max wait time\n * pollInterval: 500, // Check every 500ms\n * reason: 'Running migrations',\n * }\n * ```\n */\nexport interface LockOptions {\n /**\n * Database dialect for date formatting.\n *\n * SQLite stores dates as ISO strings, other dialects can use Date objects.\n * @default 'postgres'\n */\n dialect?: 'postgres' | 'mysql' | 'sqlite' | 'mssql';\n\n /**\n * Lock duration in milliseconds.\n *\n * After this time, the lock expires and can be claimed by others.\n * @default 300_000 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Block until lock is available?\n *\n * If true, will poll until the lock is acquired or waitTimeout is reached.\n * @default false\n */\n wait?: boolean;\n\n /**\n * Max time to wait for lock in milliseconds.\n *\n * Only used if wait is true.\n * @default 30_000 (30 seconds)\n */\n waitTimeout?: number;\n\n /**\n * How often to poll when waiting, in milliseconds.\n *\n * Only used if wait is true.\n * @default 1_000 (1 second)\n */\n pollInterval?: number;\n\n /**\n * Optional reason for acquiring the lock.\n *\n * Shown to users who are blocked by this lock.\n */\n reason?: string;\n}\n\n/**\n * Result of a lock status check.\n */\nexport interface LockStatus {\n /** Whether the lock is currently held */\n isLocked: boolean;\n\n /** Lock details if held, null if not */\n lock: Lock | null;\n}\n\n/**\n * Default lock options.\n */\nexport const DEFAULT_LOCK_OPTIONS: Required<Omit<LockOptions, 'reason'>> = {\n dialect: 'postgres',\n timeout: 5 * 60 * 1000, // 5 minutes\n wait: false,\n waitTimeout: 30 * 1000, // 30 seconds\n pollInterval: 1000, // 1 second\n};\n","/**\n * Lock-related errors.\n *\n * WHY: Specific error types allow callers to handle lock failures\n * differently from other errors (e.g., prompt user to wait vs retry).\n */\n\n/**\n * Error when lock cannot be acquired.\n *\n * Thrown when another process holds the lock and wait=false,\n * or when waitTimeout is exceeded.\n *\n * @example\n * ```typescript\n * const [lock, err] = await attempt(() => lockManager.acquire(config, identity))\n * if (err instanceof LockAcquireError) {\n * console.log(`Blocked by ${err.holder} since ${err.heldSince}`)\n * }\n * ```\n */\nexport class LockAcquireError extends Error {\n\n override readonly name = 'LockAcquireError' as const;\n\n constructor(\n public readonly configName: string,\n public readonly holder: string,\n public readonly heldSince: Date,\n public readonly expiresAt: Date,\n public readonly reason?: string,\n ) {\n\n const since = heldSince.toISOString();\n const expires = expiresAt.toISOString();\n const reasonSuffix = reason ? ` (${reason})` : '';\n\n super(\n `Lock for '${configName}' held by ${holder} since ${since}, expires ${expires}${reasonSuffix}`,\n );\n\n }\n\n}\n\n/**\n * Error when lock expires during operation.\n *\n * Thrown when validating lock before a critical operation\n * and discovering it has expired.\n *\n * @example\n * ```typescript\n * // Before committing transaction\n * const [, err] = await attempt(() => lockManager.validate(configName, identity))\n * if (err instanceof LockExpiredError) {\n * await transaction.rollback()\n * throw new Error('Lock expired, operation aborted')\n * }\n * ```\n */\nexport class LockExpiredError extends Error {\n\n override readonly name = 'LockExpiredError' as const;\n\n constructor(\n public readonly configName: string,\n public readonly identity: string,\n public readonly expiredAt: Date,\n ) {\n\n super(`Lock for '${configName}' expired at ${expiredAt.toISOString()}`);\n\n }\n\n}\n\n/**\n * Error when trying to release a non-existent lock.\n *\n * Thrown when release() is called but no lock exists,\n * or the lock is held by a different identity.\n *\n * @example\n * ```typescript\n * const [, err] = await attempt(() => lockManager.release(configName, identity))\n * if (err instanceof LockNotFoundError) {\n * // Lock was already released or expired\n * }\n * ```\n */\nexport class LockNotFoundError extends Error {\n\n override readonly name = 'LockNotFoundError' as const;\n\n constructor(\n public readonly configName: string,\n public readonly identity: string,\n ) {\n\n super(`No lock found for '${configName}' held by ${identity}`);\n\n }\n\n}\n\n/**\n * Error when trying to release a lock held by someone else.\n *\n * @example\n * ```typescript\n * const [, err] = await attempt(() => lockManager.release(configName, identity))\n * if (err instanceof LockOwnershipError) {\n * console.log(`Lock held by ${err.actualHolder}, not ${err.requestedBy}`)\n * }\n * ```\n */\nexport class LockOwnershipError extends Error {\n\n override readonly name = 'LockOwnershipError' as const;\n\n constructor(\n public readonly configName: string,\n public readonly requestedBy: string,\n public readonly actualHolder: string,\n ) {\n\n super(\n `Cannot release lock for '${configName}': held by ${actualHolder}, not ${requestedBy}`,\n );\n\n }\n\n}\n","/**\n * Lock manager for preventing concurrent database operations.\n *\n * Uses table-based locking via `__noorm_lock__` to prevent race conditions\n * when multiple processes try to modify the same database.\n *\n * @example\n * ```typescript\n * const manager = getLockManager()\n *\n * // Acquire lock before running migrations\n * await manager.withLock(db, 'dev', 'alice@example.com', async () => {\n * await runMigrations()\n * })\n *\n * // Or manual acquire/release\n * const lock = await manager.acquire(db, 'dev', 'alice@example.com')\n * try {\n * await runMigrations()\n * }\n * finally {\n * await manager.release(db, 'dev', 'alice@example.com')\n * }\n * ```\n */\nimport { attempt } from '@logosdx/utils';\nimport type { Kysely } from 'kysely';\n\nimport { observer } from '../observer.js';\nimport { NOORM_TABLES, type NoormDatabase } from '../shared/index.js';\nimport type { Dialect } from '../connection/types.js';\nimport type { Lock, LockOptions, LockStatus } from './types.js';\nimport { DEFAULT_LOCK_OPTIONS } from './types.js';\nimport {\n LockAcquireError,\n LockExpiredError,\n LockNotFoundError,\n LockOwnershipError,\n} from './errors.js';\n\n// ─────────────────────────────────────────────────────────────\n// Dialect-aware date helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Format a Date for database storage based on dialect.\n *\n * SQLite stores dates as TEXT (ISO strings), while other dialects\n * can bind Date objects directly.\n */\nfunction formatDateForDialect(date: Date, dialect: Dialect): Date | string {\n\n if (dialect === 'sqlite') {\n\n return date.toISOString();\n\n }\n\n return date;\n\n}\n\n/**\n * Manages database locks for concurrent operation protection.\n */\nclass LockManager {\n\n /**\n * Acquire a lock for a config.\n *\n * If the lock is held by another identity and wait=false, throws LockAcquireError.\n * If wait=true, polls until lock is available or waitTimeout is exceeded.\n *\n * @param db - Kysely database instance\n * @param configName - Config/database scope for the lock\n * @param identity - Identity string of the requester\n * @param options - Lock options\n * @returns Lock state on success\n * @throws LockAcquireError if lock cannot be acquired\n */\n async acquire(\n db: Kysely<NoormDatabase>,\n configName: string,\n identity: string,\n options: LockOptions = {},\n ): Promise<Lock> {\n\n // Declaration\n const opts = { ...DEFAULT_LOCK_OPTIONS, ...options };\n const startTime = Date.now();\n\n // Emit acquiring event\n observer.emit('lock:acquiring', { configName, identity });\n\n // Business Logic\n while (true) {\n\n // Clean up expired locks first\n await this.cleanupExpired(db, configName, opts.dialect);\n\n // Try to get existing lock\n const existing = await this.getLock(db, configName);\n\n if (!existing) {\n\n // No lock exists, create one\n const lock = await this.createLock(db, configName, identity, opts);\n observer.emit('lock:acquired', {\n configName,\n identity,\n expiresAt: lock.expiresAt,\n });\n\n return lock;\n\n }\n\n // Lock exists and is not expired (cleanup already ran)\n // Check if it's ours\n if (existing.lockedBy === identity) {\n\n // We already hold the lock - extend it\n const lock = await this.extendLock(db, configName, identity, opts);\n observer.emit('lock:acquired', {\n configName,\n identity,\n expiresAt: lock.expiresAt,\n });\n\n return lock;\n\n }\n\n // Lock held by someone else\n observer.emit('lock:blocked', {\n configName,\n holder: existing.lockedBy,\n heldSince: existing.lockedAt,\n });\n\n if (!opts.wait) {\n\n throw new LockAcquireError(\n configName,\n existing.lockedBy,\n existing.lockedAt,\n existing.expiresAt,\n existing.reason,\n );\n\n }\n\n // Check wait timeout\n const elapsed = Date.now() - startTime;\n if (elapsed >= opts.waitTimeout) {\n\n throw new LockAcquireError(\n configName,\n existing.lockedBy,\n existing.lockedAt,\n existing.expiresAt,\n existing.reason,\n );\n\n }\n\n // Wait and retry\n await sleep(opts.pollInterval);\n\n }\n\n }\n\n /**\n * Release a lock.\n *\n * @param db - Kysely database instance\n * @param configName - Config/database scope\n * @param identity - Identity of the lock holder\n * @throws LockNotFoundError if no lock exists\n * @throws LockOwnershipError if lock is held by someone else\n */\n async release(db: Kysely<NoormDatabase>, configName: string, identity: string): Promise<void> {\n\n // Check existing lock\n const existing = await this.getLock(db, configName);\n\n if (!existing) {\n\n throw new LockNotFoundError(configName, identity);\n\n }\n\n if (existing.lockedBy !== identity) {\n\n throw new LockOwnershipError(configName, identity, existing.lockedBy);\n\n }\n\n // Delete the lock\n await db\n .deleteFrom(NOORM_TABLES.lock)\n .where('config_name', '=', configName)\n .where('locked_by', '=', identity)\n .execute();\n\n observer.emit('lock:released', { configName, identity });\n\n }\n\n /**\n * Force release a lock regardless of owner.\n *\n * Use with caution - this bypasses ownership checks.\n * Intended for admin/CLI force-release commands.\n *\n * @param db - Kysely database instance\n * @param configName - Config/database scope\n * @returns true if a lock was released, false if none existed\n */\n async forceRelease(db: Kysely<NoormDatabase>, configName: string): Promise<boolean> {\n\n const existing = await this.getLock(db, configName);\n if (!existing) {\n\n return false;\n\n }\n\n await db.deleteFrom(NOORM_TABLES.lock).where('config_name', '=', configName).execute();\n\n observer.emit('lock:released', {\n configName,\n identity: existing.lockedBy,\n });\n\n return true;\n\n }\n\n /**\n * Execute an operation while holding a lock.\n *\n * Acquires the lock, runs the operation, and releases the lock.\n * Lock is released even if the operation throws.\n *\n * @param db - Kysely database instance\n * @param configName - Config/database scope\n * @param identity - Identity string\n * @param operation - Async function to execute\n * @param options - Lock options\n * @returns Result of the operation\n */\n async withLock<T>(\n db: Kysely<NoormDatabase>,\n configName: string,\n identity: string,\n operation: () => Promise<T>,\n options: LockOptions = {},\n ): Promise<T> {\n\n await this.acquire(db, configName, identity, options);\n\n try {\n\n return await operation();\n\n }\n finally {\n\n const [, err] = await attempt(() => this.release(db, configName, identity));\n\n if (err) {\n\n // Log but don't throw - the operation result matters more\n observer.emit('error', {\n source: 'lock',\n error: err,\n context: { configName, identity },\n });\n\n }\n\n }\n\n }\n\n /**\n * Validate that a lock is still held by the given identity.\n *\n * Use this before critical operations to ensure the lock hasn't expired.\n *\n * @param db - Kysely database instance\n * @param configName - Config/database scope\n * @param identity - Expected lock holder\n * @throws LockExpiredError if lock has expired\n * @throws LockOwnershipError if lock is held by someone else\n * @throws LockNotFoundError if no lock exists\n */\n async validate(\n db: Kysely<NoormDatabase>,\n configName: string,\n identity: string,\n dialect: Dialect = 'postgres',\n ): Promise<void> {\n\n const existing = await this.getLock(db, configName);\n\n if (!existing) {\n\n throw new LockNotFoundError(configName, identity);\n\n }\n\n if (existing.lockedBy !== identity) {\n\n throw new LockOwnershipError(configName, identity, existing.lockedBy);\n\n }\n\n if (existing.expiresAt < new Date()) {\n\n // Clean it up\n await this.cleanupExpired(db, configName, dialect);\n\n throw new LockExpiredError(configName, identity, existing.expiresAt);\n\n }\n\n }\n\n /**\n * Extend a lock's expiration time.\n *\n * @param db - Kysely database instance\n * @param configName - Config/database scope\n * @param identity - Lock holder identity\n * @param options - Lock options (uses timeout for extension)\n * @returns Updated lock state\n */\n async extend(\n db: Kysely<NoormDatabase>,\n configName: string,\n identity: string,\n options: LockOptions = {},\n ): Promise<Lock> {\n\n // Validate first\n await this.validate(db, configName, identity);\n\n return this.extendLock(db, configName, identity, options);\n\n }\n\n /**\n * Get the current lock status for a config.\n *\n * @param db - Kysely database instance\n * @param configName - Config/database scope\n * @param dialect - Database dialect for date formatting\n * @returns Lock status with isLocked flag and lock details\n */\n async status(\n db: Kysely<NoormDatabase>,\n configName: string,\n dialect: Dialect = 'postgres',\n ): Promise<LockStatus> {\n\n // Clean up expired first\n await this.cleanupExpired(db, configName, dialect);\n\n const lock = await this.getLock(db, configName);\n\n return {\n isLocked: lock !== null,\n lock,\n };\n\n }\n\n // ─────────────────────────────────────────────────────────────\n // Private helpers\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get lock from database, or null if none exists.\n */\n private async getLock(db: Kysely<NoormDatabase>, configName: string): Promise<Lock | null> {\n\n const row = await db\n .selectFrom(NOORM_TABLES.lock)\n .selectAll()\n .where('config_name', '=', configName)\n .executeTakeFirst();\n\n if (!row) {\n\n return null;\n\n }\n\n return {\n lockedBy: row.locked_by,\n lockedAt: new Date(row.locked_at),\n expiresAt: new Date(row.expires_at),\n reason: row.reason || undefined,\n };\n\n }\n\n /**\n * Create a new lock in the database.\n */\n private async createLock(\n db: Kysely<NoormDatabase>,\n configName: string,\n identity: string,\n opts: Required<Omit<LockOptions, 'reason'>> & { reason?: string },\n ): Promise<Lock> {\n\n const now = new Date();\n const expiresAt = new Date(now.getTime() + opts.timeout);\n\n await db\n .insertInto(NOORM_TABLES.lock)\n .values({\n config_name: configName,\n locked_by: identity,\n locked_at: formatDateForDialect(now, opts.dialect) as Date,\n expires_at: formatDateForDialect(expiresAt, opts.dialect) as Date,\n reason: opts.reason ?? '',\n })\n .execute();\n\n return {\n lockedBy: identity,\n lockedAt: now,\n expiresAt,\n reason: opts.reason,\n };\n\n }\n\n /**\n * Extend an existing lock.\n */\n private async extendLock(\n db: Kysely<NoormDatabase>,\n configName: string,\n identity: string,\n opts: Partial<LockOptions>,\n ): Promise<Lock> {\n\n const dialect = opts.dialect ?? DEFAULT_LOCK_OPTIONS.dialect;\n const timeout = opts.timeout ?? DEFAULT_LOCK_OPTIONS.timeout;\n const now = new Date();\n const expiresAt = new Date(now.getTime() + timeout);\n\n const updateValues: Record<string, Date | string | undefined> = {\n expires_at: formatDateForDialect(expiresAt, dialect),\n };\n\n if (opts.reason !== undefined) {\n\n updateValues['reason'] = opts.reason;\n\n }\n\n await db\n .updateTable(NOORM_TABLES.lock)\n .set(updateValues as Record<string, string>)\n .where('config_name', '=', configName)\n .where('locked_by', '=', identity)\n .execute();\n\n // Fetch the updated lock\n const lock = await this.getLock(db, configName);\n\n return lock!;\n\n }\n\n /**\n * Clean up expired locks.\n */\n private async cleanupExpired(\n db: Kysely<NoormDatabase>,\n configName: string,\n dialect: Dialect = 'postgres',\n ): Promise<void> {\n\n const now = new Date();\n const nowForDb = formatDateForDialect(now, dialect);\n\n // Get expired lock info for event\n const expired = await db\n .selectFrom(NOORM_TABLES.lock)\n .select(['locked_by'])\n .where('config_name', '=', configName)\n .where('expires_at', '<', nowForDb as Date)\n .executeTakeFirst();\n\n if (expired) {\n\n await db\n .deleteFrom(NOORM_TABLES.lock)\n .where('config_name', '=', configName)\n .where('expires_at', '<', nowForDb as Date)\n .execute();\n\n observer.emit('lock:expired', {\n configName,\n previousHolder: expired.locked_by,\n });\n\n }\n\n }\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Module singleton\n// ─────────────────────────────────────────────────────────────\n\nlet instance: LockManager | null = null;\n\n/**\n * Get the global LockManager instance.\n *\n * @example\n * ```typescript\n * const lockManager = getLockManager()\n * await lockManager.withLock(db, 'dev', 'alice', async () => {\n * await runMigrations()\n * })\n * ```\n */\nexport function getLockManager(): LockManager {\n\n if (!instance) {\n\n instance = new LockManager();\n\n }\n\n return instance;\n\n}\n\n/**\n * Reset the global LockManager instance.\n *\n * Primarily for testing.\n */\nexport function resetLockManager(): void {\n\n instance = null;\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Utility\n// ─────────────────────────────────────────────────────────────\n\nfunction sleep(ms: number): Promise<void> {\n\n return new Promise((resolve) => setTimeout(resolve, ms));\n\n}\n\n// Export class for typing\nexport { LockManager };\n","/**\n * Change executor.\n *\n * Orchestrates change execution by coordinating the parser, history,\n * and runner modules. Handles the full lifecycle from validation to\n * completion.\n *\n * WHY: Change execution is complex - it needs to parse files, check\n * status, acquire locks, execute SQL, and track results. The executor\n * centralizes this logic.\n *\n * @example\n * ```typescript\n * import { executeChange, revertChange } from './executor'\n *\n * // Execute a change\n * const result = await executeChange(context, change, options)\n *\n * // Revert a change\n * const revertResult = await revertChange(context, change, options)\n * ```\n */\nimport path from 'node:path';\nimport { readFile, writeFile as fsWriteFile, mkdir } from 'node:fs/promises';\nimport { sql } from 'kysely';\n\nimport { attempt, attemptSync } from '@logosdx/utils';\n\nimport { observer } from '../observer.js';\nimport { formatIdentity } from '../identity/resolver.js';\nimport { processFile, isTemplate } from '../template/index.js';\nimport { computeChecksum, computeCombinedChecksum } from '../runner/checksum.js';\nimport { getLockManager } from '../lock/index.js';\nimport { ChangeHistory } from './history.js';\nimport { ChangeTracker } from './tracker.js';\nimport { resolveManifest, validateChange, hasRevertFiles } from './parser.js';\nimport type {\n Change,\n ChangeFile,\n ChangeContext,\n ChangeOptions,\n ChangeResult,\n ChangeFileResult,\n} from './types.js';\nimport { ChangeNotAppliedError, ChangeValidationError } from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Constants\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_OPTIONS: Required<Omit<ChangeOptions, 'output'>> & { output: string | null } = {\n force: false,\n dryRun: false,\n preview: false,\n output: null,\n};\n\n/** Default SQL template - files with only this content are considered empty */\nconst SQL_TEMPLATE = '-- TODO: Add SQL statements here';\n\n// ─────────────────────────────────────────────────────────────\n// Execute Change (Change Direction)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execute a change (apply changes).\n *\n * @param context - Execution context\n * @param change - Change to execute\n * @param options - Execution options\n * @returns Execution result\n *\n * @example\n * ```typescript\n * const result = await executeChange(context, change, {\n * force: false,\n * dryRun: false,\n * })\n *\n * if (result.status === 'success') {\n * console.log('Change applied successfully')\n * }\n * ```\n */\nexport async function executeChange(\n context: ChangeContext,\n change: Change,\n options: ChangeOptions = {},\n): Promise<ChangeResult> {\n\n const start = performance.now();\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n // Validate change structure\n const [, validateErr] = attemptSync(() => {\n\n validateChange(change);\n\n });\n\n if (validateErr) {\n\n observer.emit('error', {\n source: 'change',\n error: validateErr,\n context: { name: change.name, operation: 'validate' },\n });\n\n return createFailedResult(change.name, 'change', validateErr.message, start);\n\n }\n\n // Get files to execute\n const files = change.changeFiles;\n\n if (files.length === 0) {\n\n throw new ChangeValidationError(change.name, 'No files in change/ folder');\n\n }\n\n // Validate files have actual content (not empty or template-only)\n const [contentValid, contentErr] = await attempt(() => validateFilesHaveContent(files));\n\n if (contentErr || !contentValid) {\n\n throw new ChangeValidationError(\n change.name,\n 'Files are empty or contain only template placeholders. Edit the SQL files before running.',\n );\n\n }\n\n // Compute checksum\n const [checksums, checksumErr] = await attempt(() =>\n computeFileChecksums(files, context.sqlDir),\n );\n\n if (checksumErr) {\n\n return createFailedResult(change.name, 'change', checksumErr.message, start);\n\n }\n\n const changeChecksum = computeCombinedChecksum(checksums);\n\n // Create history tracker\n const history = new ChangeHistory(context.db, context.configName);\n\n // Check if needs to run (unless dry run or preview)\n if (!opts.dryRun && !opts.preview) {\n\n const needsRunResult = await history.needsRun(\n change.name,\n changeChecksum,\n opts.force,\n );\n\n if (!needsRunResult.needsRun) {\n\n observer.emit('change:skip', {\n name: change.name,\n reason: needsRunResult.skipReason ?? 'already applied',\n });\n\n return {\n name: change.name,\n direction: 'change',\n status: 'success',\n files: [],\n durationMs: performance.now() - start,\n };\n\n }\n\n }\n\n // Handle dry run\n if (opts.dryRun) {\n\n return executeDryRun(context, change, files, 'change', start);\n\n }\n\n // Handle preview\n if (opts.preview) {\n\n return executePreview(context, change, files, 'change', opts.output, start);\n\n }\n\n // Acquire lock\n const lockManager = getLockManager();\n const identity = formatIdentity(context.identity);\n\n const [, lockErr] = await attempt(() =>\n lockManager.acquire(context.db, context.configName, identity, {\n reason: `Change: ${change.name}`,\n dialect: context.dialect,\n }),\n );\n\n if (lockErr) {\n\n // Lock error is thrown, not returned\n throw lockErr;\n\n }\n\n // Execute files (lock will be released after, regardless of outcome)\n const [result, execErr] = await attempt(() =>\n executeFiles(\n context,\n change,\n files,\n 'change',\n changeChecksum,\n history,\n start,\n ),\n );\n\n // Always release lock\n await attempt(() => lockManager.release(context.db, context.configName, identity));\n\n if (execErr) {\n\n throw execErr;\n\n }\n\n return result;\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Revert Change\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Revert a change (apply revert files).\n *\n * @param context - Execution context\n * @param change - Change to revert\n * @param options - Execution options\n * @returns Execution result\n */\nexport async function revertChange(\n context: ChangeContext,\n change: Change,\n options: ChangeOptions = {},\n): Promise<ChangeResult> {\n\n const start = performance.now();\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n // Check for revert files\n if (!hasRevertFiles(change)) {\n\n throw new ChangeValidationError(\n change.name,\n 'No revert files (revert/ folder is empty or missing)',\n );\n\n }\n\n const files = change.revertFiles;\n\n // Compute checksum\n const [checksums, checksumErr] = await attempt(() =>\n computeFileChecksums(files, context.sqlDir),\n );\n\n if (checksumErr) {\n\n return createFailedResult(change.name, 'revert', checksumErr.message, start);\n\n }\n\n const revertChecksum = computeCombinedChecksum(checksums);\n\n // Create trackers\n const history = new ChangeHistory(context.db, context.configName);\n const tracker = new ChangeTracker(context.db, context.configName);\n\n // Check if can revert (unless dry run or preview)\n if (!opts.dryRun && !opts.preview) {\n\n const canRevertResult = await tracker.canRevert(change.name, opts.force);\n\n if (!canRevertResult.canRevert) {\n\n if (canRevertResult.reason === 'not applied') {\n\n throw new ChangeNotAppliedError(change.name);\n\n }\n\n observer.emit('change:skip', {\n name: change.name,\n reason: canRevertResult.reason ?? 'cannot revert',\n });\n\n return {\n name: change.name,\n direction: 'revert',\n status: 'success',\n files: [],\n durationMs: performance.now() - start,\n };\n\n }\n\n }\n\n // Handle dry run\n if (opts.dryRun) {\n\n return executeDryRun(context, change, files, 'revert', start);\n\n }\n\n // Handle preview\n if (opts.preview) {\n\n return executePreview(context, change, files, 'revert', opts.output, start);\n\n }\n\n // Acquire lock\n const lockManager = getLockManager();\n const identity = formatIdentity(context.identity);\n\n const [, lockErr] = await attempt(() =>\n lockManager.acquire(context.db, context.configName, identity, {\n reason: `Revert: ${change.name}`,\n dialect: context.dialect,\n }),\n );\n\n if (lockErr) {\n\n throw lockErr;\n\n }\n\n // Execute files (lock will be released after, regardless of outcome)\n const [result, execErr] = await attempt(() =>\n executeFiles(\n context,\n change,\n files,\n 'revert',\n revertChecksum,\n history,\n start,\n ),\n );\n\n // Always release lock\n await attempt(() => lockManager.release(context.db, context.configName, identity));\n\n if (execErr) {\n\n throw execErr;\n\n }\n\n // If successful, mark original as reverted\n if (result.status === 'success') {\n\n await tracker.markAsReverted(change.name);\n\n }\n\n return result;\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Internal: Execute Files\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execute files with tracking.\n */\nasync function executeFiles(\n context: ChangeContext,\n change: Change,\n files: ChangeFile[],\n direction: 'change' | 'revert',\n checksum: string,\n history: ChangeHistory,\n startTime: number,\n): Promise<ChangeResult> {\n\n // Expand .txt manifests to actual file list\n const expandedFiles = await expandFiles(files, context.sqlDir);\n\n // Create operation record\n const [operationId, createErr] = await attempt(() =>\n history.createOperation({\n name: change.name,\n direction,\n executedBy: formatIdentity(context.identity),\n }),\n );\n\n if (createErr) {\n\n observer.emit('error', {\n source: 'change',\n error: createErr,\n context: { name: change.name, operation: 'create-operation' },\n });\n\n return createFailedResult(change.name, direction, createErr.message, startTime);\n\n }\n\n // Compute checksums for all files\n const fileChecksums = new Map<string, string>();\n\n for (const file of expandedFiles) {\n\n const [cs] = await attempt(() => computeChecksum(file.path));\n fileChecksums.set(file.path, cs ?? '');\n\n }\n\n // Create pending file records\n const createRecordsErr = await history.createFileRecords(\n operationId,\n expandedFiles.map((f) => ({\n filepath: f.path,\n fileType: f.type,\n checksum: fileChecksums.get(f.path) ?? '',\n })),\n );\n\n if (createRecordsErr) {\n\n // File records couldn't be created - finalize as failed and return\n await history.finalizeOperation(operationId, 'failed', checksum, 0, createRecordsErr);\n\n return {\n name: change.name,\n direction,\n status: 'failed',\n files: [],\n durationMs: performance.now() - startTime,\n error: createRecordsErr,\n operationId,\n };\n\n }\n\n // Emit start event\n observer.emit('change:start', {\n name: change.name,\n direction,\n files: expandedFiles.map((f) => f.path),\n });\n\n // Execute each file\n const results: ChangeFileResult[] = [];\n let failed = false;\n let failedFile: string | undefined;\n let failureError: string | undefined;\n\n // Execute loop wrapped in attempt to catch unexpected errors\n const [, unexpectedErr] = await attempt(async () => {\n\n for (let i = 0; i < expandedFiles.length; i++) {\n\n const file = expandedFiles[i];\n\n if (!file) continue;\n\n observer.emit('change:file', {\n change: change.name,\n filepath: file.path,\n index: i,\n total: expandedFiles.length,\n });\n\n const fileStart = performance.now();\n\n // Load and render file\n const [sqlContent, loadErr] = await attempt(() => loadAndRenderFile(context, file.path));\n\n if (loadErr) {\n\n const durationMs = performance.now() - fileStart;\n\n // Capture error info FIRST\n failed = true;\n failedFile = file.path;\n failureError = loadErr.message;\n\n results.push({\n filepath: file.path,\n checksum: fileChecksums.get(file.path) ?? '',\n status: 'failed',\n error: loadErr.message,\n durationMs,\n });\n\n // Update DB record\n const updateErr = await history.updateFileExecution(\n operationId,\n file.path,\n 'failed',\n durationMs,\n loadErr.message,\n );\n\n if (updateErr) {\n\n // Log but don't fail - we already have the error captured\n observer.emit('error', {\n source: 'change',\n error: new Error(updateErr),\n context: { filepath: file.path, operation: 'update-failed-record' },\n });\n\n }\n\n break;\n\n }\n\n // Execute SQL\n const [, execErr] = await attempt(() => sql.raw(sqlContent).execute(context.db));\n\n const durationMs = performance.now() - fileStart;\n\n if (execErr) {\n\n // Capture error info FIRST\n failed = true;\n failedFile = file.path;\n failureError = execErr.message;\n\n results.push({\n filepath: file.path,\n checksum: fileChecksums.get(file.path) ?? '',\n status: 'failed',\n error: execErr.message,\n durationMs,\n });\n\n // Update DB record\n const updateErr = await history.updateFileExecution(\n operationId,\n file.path,\n 'failed',\n durationMs,\n execErr.message,\n );\n\n if (updateErr) {\n\n // Log but don't fail - we already have the error captured\n observer.emit('error', {\n source: 'change',\n error: new Error(updateErr),\n context: { filepath: file.path, operation: 'update-failed-record' },\n });\n\n }\n\n break;\n\n }\n\n // Success\n results.push({\n filepath: file.path,\n checksum: fileChecksums.get(file.path) ?? '',\n status: 'success',\n durationMs,\n });\n\n // Update DB record\n const updateErr = await history.updateFileExecution(\n operationId,\n file.path,\n 'success',\n durationMs,\n );\n\n if (updateErr) {\n\n // Log but continue - the file was executed successfully\n observer.emit('error', {\n source: 'change',\n error: new Error(updateErr),\n context: { filepath: file.path, operation: 'update-success-record' },\n });\n\n }\n\n }\n\n });\n\n // Handle unexpected errors from the execution loop\n if (unexpectedErr) {\n\n if (!failed) {\n\n failed = true;\n failureError = unexpectedErr.message;\n\n }\n\n observer.emit('error', {\n source: 'change',\n error: unexpectedErr,\n context: { name: change.name, operation: 'execute-files' },\n });\n\n }\n\n // Mark remaining pending files as skipped if there was a failure\n // This handles both normal failures and unexpected exceptions\n if (failed) {\n\n const skipReason = failedFile\n ? `${path.basename(failedFile)} failed: ${failureError ?? 'unknown error'}`\n : 'change failed';\n\n const skipError = await history.skipRemainingFiles(operationId, skipReason);\n\n if (skipError) {\n\n // Log skip failure but continue - the change already failed\n observer.emit('error', {\n source: 'change',\n error: new Error(skipError),\n context: { operationId, operation: 'skip-remaining-files' },\n });\n\n }\n\n }\n\n // Finalize operation\n const totalDurationMs = performance.now() - startTime;\n const executionStatus = failed ? 'failed' : 'success';\n\n // Build detailed error message for the change record\n const errorMessage = failedFile\n ? `${path.basename(failedFile)}: ${failureError ?? 'unknown error'}`\n : failureError;\n\n const finalizeError = await history.finalizeOperation(\n operationId,\n executionStatus,\n checksum,\n totalDurationMs,\n failed ? errorMessage : undefined,\n );\n\n // Final status accounts for BOTH execution AND finalization\n // If finalization failed, the change is effectively failed regardless of execution\n const finalStatus = finalizeError ? 'failed' : executionStatus;\n const combinedError = finalizeError\n ? `${errorMessage ?? 'Execution succeeded but finalization failed'}. Additionally: ${finalizeError}`\n : errorMessage;\n\n // Emit complete event\n observer.emit('change:complete', {\n name: change.name,\n direction,\n status: finalStatus,\n durationMs: totalDurationMs,\n });\n\n return {\n name: change.name,\n direction,\n status: finalStatus,\n files: results,\n durationMs: totalDurationMs,\n error: finalStatus === 'failed' ? combinedError : undefined,\n operationId,\n };\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Internal: Preview\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execute preview mode.\n */\nasync function executePreview(\n context: ChangeContext,\n change: Change,\n files: ChangeFile[],\n direction: 'change' | 'revert',\n output: string | null,\n startTime: number,\n): Promise<ChangeResult> {\n\n const expandedFiles = await expandFiles(files, context.sqlDir);\n const results: ChangeFileResult[] = [];\n const rendered: string[] = [];\n\n for (const file of expandedFiles) {\n\n const fileStart = performance.now();\n\n // Compute checksum\n const [checksum] = await attempt(() => computeChecksum(file.path));\n\n // Load and render file\n const [sqlContent, loadErr] = await attempt(() => loadAndRenderFile(context, file.path));\n\n if (loadErr) {\n\n results.push({\n filepath: file.path,\n checksum: checksum ?? '',\n status: 'failed',\n error: loadErr.message,\n durationMs: performance.now() - fileStart,\n });\n\n continue;\n\n }\n\n rendered.push(formatPreviewHeader(file.path) + sqlContent);\n\n results.push({\n filepath: file.path,\n checksum: checksum ?? '',\n status: 'success',\n durationMs: performance.now() - fileStart,\n renderedSql: sqlContent,\n });\n\n }\n\n // Write to output file if specified\n if (output) {\n\n const { writeFile } = await import('node:fs/promises');\n\n const combinedSql = rendered.join('\\n\\n');\n await writeFile(output, combinedSql, 'utf-8');\n\n }\n\n return {\n name: change.name,\n direction,\n status: results.every((r) => r.status === 'success') ? 'success' : 'failed',\n files: results,\n durationMs: performance.now() - startTime,\n };\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Internal Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Expand .txt manifest files to actual SQL paths.\n */\nasync function expandFiles(files: ChangeFile[], sqlDir: string): Promise<ChangeFile[]> {\n\n const expanded: ChangeFile[] = [];\n\n for (const file of files) {\n\n if (file.type === 'txt') {\n\n // .txt files reference other SQL files\n if (file.resolvedPaths) {\n\n for (const resolvedPath of file.resolvedPaths) {\n\n expanded.push({\n filename: path.basename(resolvedPath),\n path: resolvedPath,\n type: 'sql',\n });\n\n }\n\n }\n else {\n\n // Resolve now if not already resolved\n const resolved = await resolveManifest(file.path, sqlDir);\n\n for (const resolvedPath of resolved) {\n\n expanded.push({\n filename: path.basename(resolvedPath),\n path: resolvedPath,\n type: 'sql',\n });\n\n }\n\n }\n\n }\n else {\n\n expanded.push(file);\n\n }\n\n }\n\n return expanded;\n\n}\n\n/**\n * Compute checksums for all files, including expanded manifests.\n */\nasync function computeFileChecksums(files: ChangeFile[], sqlDir: string): Promise<string[]> {\n\n const checksums: string[] = [];\n\n for (const file of files) {\n\n // Compute checksum of the file itself\n const fileChecksum = await computeChecksum(file.path);\n checksums.push(fileChecksum);\n\n // For .txt files, also include checksums of referenced files\n if (file.type === 'txt') {\n\n const resolved = file.resolvedPaths ?? (await resolveManifest(file.path, sqlDir));\n\n for (const resolvedPath of resolved) {\n\n const refChecksum = await computeChecksum(resolvedPath);\n checksums.push(refChecksum);\n\n }\n\n }\n\n }\n\n return checksums;\n\n}\n\n/**\n * Format preview header for a file.\n */\nfunction formatPreviewHeader(filepath: string): string {\n\n return `-- ============================================================\n-- File: ${filepath}\n-- ============================================================\n\n`;\n\n}\n\n/**\n * Validate that at least one file has actual content (not empty or template-only).\n * Returns true if valid, false if all files are empty/template.\n */\nasync function validateFilesHaveContent(files: ChangeFile[]): Promise<boolean> {\n\n for (const file of files) {\n\n // .txt manifest files are considered valid (they reference other files)\n if (file.type === 'txt') {\n\n return true;\n\n }\n\n const [content, err] = await attempt(() => readFile(file.path, 'utf-8'));\n\n if (err) {\n\n continue; // Skip files we can't read\n\n }\n\n const trimmed = content?.trim() ?? '';\n\n // Check if file has actual content (not empty, not just the template)\n if (trimmed && trimmed !== SQL_TEMPLATE) {\n\n return true;\n\n }\n\n }\n\n return false;\n\n}\n\n/**\n * Create a failed result.\n */\nfunction createFailedResult(\n name: string,\n direction: 'change' | 'revert',\n error: string,\n startTime: number,\n): ChangeResult {\n\n return {\n name,\n direction,\n status: 'failed',\n files: [],\n durationMs: performance.now() - startTime,\n error,\n };\n\n}\n\n/**\n * Execute dry run mode.\n *\n * Writes rendered SQL to tmp/ without executing or tracking.\n */\nasync function executeDryRun(\n context: ChangeContext,\n change: Change,\n files: ChangeFile[],\n direction: 'change' | 'revert',\n startTime: number,\n): Promise<ChangeResult> {\n\n const expandedFiles = await expandFiles(files, context.sqlDir);\n const results: ChangeFileResult[] = [];\n\n for (const file of expandedFiles) {\n\n const fileStart = performance.now();\n\n // Compute checksum\n const [checksum] = await attempt(() => computeChecksum(file.path));\n\n // Load and render file\n const [sqlContent, loadErr] = await attempt(() => loadAndRenderFile(context, file.path));\n\n if (loadErr) {\n\n observer.emit('file:dry-run', {\n filepath: file.path,\n status: 'failed',\n error: loadErr.message,\n });\n\n results.push({\n filepath: file.path,\n checksum: checksum ?? '',\n status: 'failed',\n error: loadErr.message,\n durationMs: performance.now() - fileStart,\n });\n\n continue;\n\n }\n\n // Write to tmp/\n const [, writeErr] = await attempt(() =>\n writeDryRunOutput(context.projectRoot, file.path, sqlContent),\n );\n\n const durationMs = performance.now() - fileStart;\n\n if (writeErr) {\n\n observer.emit('error', {\n source: 'change',\n error: writeErr,\n context: { filepath: file.path, operation: 'dry-run-write' },\n });\n\n }\n\n const outputPath = getDryRunOutputPath(context.projectRoot, file.path);\n\n observer.emit('file:dry-run', {\n filepath: file.path,\n status: 'success',\n outputPath,\n });\n\n results.push({\n filepath: file.path,\n checksum: checksum ?? '',\n status: 'success',\n durationMs,\n renderedSql: sqlContent,\n });\n\n }\n\n return {\n name: change.name,\n direction,\n status: results.every((r) => r.status === 'success') ? 'success' : 'failed',\n files: results,\n durationMs: performance.now() - startTime,\n };\n\n}\n\n/**\n * Get the output path for a dry run file.\n *\n * Mirrors the source path structure under tmp/.\n */\nfunction getDryRunOutputPath(projectRoot: string, filepath: string): string {\n\n const relativePath = path.relative(projectRoot, filepath);\n\n const outputRelativePath = relativePath.endsWith('.tmpl')\n ? relativePath.slice(0, -5)\n : relativePath;\n\n return path.join(projectRoot, 'tmp', outputRelativePath);\n\n}\n\n/**\n * Write rendered SQL to tmp/ directory for dry run.\n */\nasync function writeDryRunOutput(\n projectRoot: string,\n filepath: string,\n content: string,\n): Promise<void> {\n\n const outputPath = getDryRunOutputPath(projectRoot, filepath);\n\n // Ensure directory exists\n const outputDir = path.dirname(outputPath);\n await mkdir(outputDir, { recursive: true });\n\n // Write file\n await fsWriteFile(outputPath, content, 'utf-8');\n\n}\n\n/**\n * Load and optionally render a SQL file.\n */\nasync function loadAndRenderFile(context: ChangeContext, filepath: string): Promise<string> {\n\n if (isTemplate(filepath)) {\n\n const result = await processFile(filepath, {\n projectRoot: context.projectRoot,\n config: undefined, // Change context doesn't have config\n secrets: undefined,\n globalSecrets: undefined,\n });\n\n return result.sql;\n\n }\n\n const [content, err] = await attempt(() => readFile(filepath, 'utf-8'));\n\n if (err) {\n\n throw new Error(`Failed to read file: ${filepath}`, { cause: err });\n\n }\n\n return content;\n\n}\n","/**\n * Change manager.\n *\n * High-level operations that combine parser, history, and executor\n * to provide the public API for change management.\n *\n * WHY: CLI commands need a simple interface to changes. The manager\n * provides this by coordinating the lower-level modules.\n *\n * @example\n * ```typescript\n * import { ChangeManager } from './manager'\n *\n * const manager = new ChangeManager(context)\n *\n * // List all changes\n * const list = await manager.list()\n *\n * // Run a specific change\n * const result = await manager.run('2024-01-15-add-users')\n *\n * // Run next pending\n * const batchResult = await manager.next(2)\n * ```\n */\nimport path from 'node:path';\n\nimport { attempt } from '@logosdx/utils';\n\nimport { parseChange, discoverChanges } from './parser.js';\nimport { deleteChange as deleteFromDisk } from './scaffold.js';\nimport { ChangeHistory } from './history.js';\nimport { executeChange, revertChange } from './executor.js';\nimport type {\n Change,\n ChangeContext,\n ChangeOptions,\n BatchChangeOptions,\n ChangeResult,\n BatchChangeResult,\n ChangeListItem,\n ChangeHistoryRecord,\n FileHistoryRecord,\n} from './types.js';\nimport { ChangeNotFoundError, ChangeOrphanedError } from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Default Options\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_BATCH: Required<Omit<BatchChangeOptions, 'output'>> & { output: string | null } = {\n force: false,\n dryRun: false,\n preview: false,\n output: null,\n abortOnError: true,\n};\n\n// ─────────────────────────────────────────────────────────────\n// Manager Class\n// ─────────────────────────────────────────────────────────────\n\n/**\n * High-level change manager.\n *\n * Provides operations for listing, running, reverting, and\n * managing changes.\n *\n * @example\n * ```typescript\n * const manager = new ChangeManager(context)\n *\n * // List all changes with status\n * const list = await manager.list()\n *\n * for (const cs of list) {\n * console.log(cs.name, cs.status, cs.orphaned ? '(orphaned)' : '')\n * }\n * ```\n */\nexport class ChangeManager {\n\n readonly #context: ChangeContext;\n readonly #history: ChangeHistory;\n\n constructor(context: ChangeContext) {\n\n this.#context = context;\n this.#history = new ChangeHistory(context.db, context.configName);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // List\n // ─────────────────────────────────────────────────────────\n\n /**\n * List all changes with status.\n *\n * Merges changes from disk with status from database.\n * Includes orphaned changes (in DB but not on disk).\n *\n * @returns Array of changes with merged status\n */\n async list(): Promise<ChangeListItem[]> {\n\n // Discover changes from disk\n const diskChanges = await discoverChanges(\n this.#context.changesDir,\n this.#context.sqlDir,\n );\n\n // Get all statuses from DB\n const statuses = await this.#history.getAllStatuses();\n\n // Create set of disk names for orphan detection\n const diskNames = new Set(diskChanges.map((cs) => cs.name));\n\n // Get orphaned changes\n const orphanedNames = await this.#history.getOrphaned(diskNames);\n\n // Merge disk + DB\n const result: ChangeListItem[] = [];\n\n // Add disk changes with their status\n for (const cs of diskChanges) {\n\n const status = statuses.get(cs.name);\n\n result.push({\n ...cs,\n name: cs.name,\n status: status?.status ?? 'pending',\n appliedAt: status?.appliedAt ?? null,\n appliedBy: status?.appliedBy ?? null,\n revertedAt: status?.revertedAt ?? null,\n errorMessage: status?.errorMessage ?? null,\n isNew: !status,\n orphaned: false,\n });\n\n }\n\n // Add orphaned changes\n for (const name of orphanedNames) {\n\n const status = statuses.get(name)!;\n\n result.push({\n name,\n status: status.status,\n appliedAt: status.appliedAt,\n appliedBy: status.appliedBy,\n revertedAt: status.revertedAt,\n errorMessage: status.errorMessage,\n isNew: false,\n orphaned: true,\n // Disk fields are not available for orphaned changes\n path: undefined,\n date: undefined,\n description: undefined,\n changeFiles: undefined,\n revertFiles: undefined,\n hasChangelog: undefined,\n });\n\n }\n\n // Sort by name\n return result.sort((a, b) => a.name.localeCompare(b.name));\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Run Single Change\n // ─────────────────────────────────────────────────────────\n\n /**\n * Run a specific change by name.\n *\n * @param name - Change name\n * @param options - Execution options\n * @returns Execution result\n */\n async run(name: string, options: ChangeOptions = {}): Promise<ChangeResult> {\n\n const change = await this.#loadChange(name);\n\n return executeChange(this.#context, change, options);\n\n }\n\n /**\n * Run a change object directly.\n */\n async runChange(\n change: Change,\n options: ChangeOptions = {},\n ): Promise<ChangeResult> {\n\n return executeChange(this.#context, change, options);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Revert Single Change\n // ─────────────────────────────────────────────────────────\n\n /**\n * Revert a specific change by name.\n *\n * @param name - Change name\n * @param options - Execution options\n * @returns Execution result\n */\n async revert(name: string, options: ChangeOptions = {}): Promise<ChangeResult> {\n\n const change = await this.#loadChange(name);\n\n return revertChange(this.#context, change, options);\n\n }\n\n /**\n * Revert a change object directly.\n */\n async revertChange(\n change: Change,\n options: ChangeOptions = {},\n ): Promise<ChangeResult> {\n\n return revertChange(this.#context, change, options);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Batch Operations\n // ─────────────────────────────────────────────────────────\n\n /**\n * Run next N pending changes.\n *\n * @param count - Number of changes to run (default: 1)\n * @param options - Execution options\n * @returns Batch result\n */\n async next(\n count: number = 1,\n options: BatchChangeOptions = {},\n ): Promise<BatchChangeResult> {\n\n const opts = { ...DEFAULT_BATCH, ...options };\n const start = performance.now();\n\n // Get pending changes\n const list = await this.list();\n const pending = list\n .filter((cs) => !cs.orphaned && (cs.status === 'pending' || cs.status === 'reverted'))\n .slice(0, count);\n\n if (pending.length === 0) {\n\n return {\n status: 'success',\n changes: [],\n executed: 0,\n skipped: 0,\n failed: 0,\n durationMs: performance.now() - start,\n };\n\n }\n\n // Execute each\n const results: ChangeResult[] = [];\n let failed = 0;\n let executed = 0;\n\n for (const item of pending) {\n\n // Load full change from disk\n const [change, loadErr] = await attempt(() => this.#loadChange(item.name));\n\n if (loadErr) {\n\n results.push({\n name: item.name,\n direction: 'change',\n status: 'failed',\n files: [],\n durationMs: 0,\n error: loadErr.message,\n });\n\n failed++;\n\n if (opts.abortOnError) break;\n\n continue;\n\n }\n\n const result = await executeChange(this.#context, change, opts);\n results.push(result);\n\n if (result.status === 'success') {\n\n executed++;\n\n }\n else {\n\n failed++;\n\n if (opts.abortOnError) break;\n\n }\n\n }\n\n return {\n status: failed > 0 ? (executed > 0 ? 'partial' : 'failed') : 'success',\n changes: results,\n executed,\n skipped: pending.length - executed - failed,\n failed,\n durationMs: performance.now() - start,\n };\n\n }\n\n /**\n * Fast-forward: run all pending changes.\n *\n * @param options - Execution options\n * @returns Batch result\n */\n async ff(options: BatchChangeOptions = {}): Promise<BatchChangeResult> {\n\n // Get count of pending\n const list = await this.list();\n const pendingCount = list.filter(\n (cs) => !cs.orphaned && (cs.status === 'pending' || cs.status === 'reverted'),\n ).length;\n\n return this.next(pendingCount, options);\n\n }\n\n /**\n * Rewind: revert changes in reverse order.\n *\n * @param target - Number of changes to revert, or name to revert to\n * @param options - Execution options\n * @returns Batch result\n */\n async rewind(\n target: number | string,\n options: BatchChangeOptions = {},\n ): Promise<BatchChangeResult> {\n\n const opts = { ...DEFAULT_BATCH, ...options };\n const start = performance.now();\n\n // Get applied changes sorted by appliedAt (most recent first)\n const list = await this.list();\n const applied = list\n .filter((cs) => !cs.orphaned && cs.status === 'success' && cs.appliedAt)\n .sort((a, b) => {\n\n const aTime = a.appliedAt?.getTime() ?? 0;\n const bTime = b.appliedAt?.getTime() ?? 0;\n\n return bTime - aTime; // Most recent first\n\n });\n\n // Determine which to revert\n let toRevert: typeof applied;\n\n if (typeof target === 'number') {\n\n toRevert = applied.slice(0, target);\n\n }\n else {\n\n // Revert until (and including) the named change\n const targetIndex = applied.findIndex((cs) => cs.name === target);\n\n if (targetIndex === -1) {\n\n return {\n status: 'failed',\n changes: [],\n executed: 0,\n skipped: 0,\n failed: 1,\n durationMs: performance.now() - start,\n };\n\n }\n\n toRevert = applied.slice(0, targetIndex + 1);\n\n }\n\n if (toRevert.length === 0) {\n\n return {\n status: 'success',\n changes: [],\n executed: 0,\n skipped: 0,\n failed: 0,\n durationMs: performance.now() - start,\n };\n\n }\n\n // Revert each\n const results: ChangeResult[] = [];\n let failed = 0;\n let executed = 0;\n let skipped = 0;\n\n for (const item of toRevert) {\n\n // Check if already reverted\n if (item.status === 'reverted') {\n\n results.push({\n name: item.name,\n direction: 'revert',\n status: 'success',\n files: [],\n durationMs: 0,\n });\n\n skipped++;\n continue;\n\n }\n\n // Load full change from disk\n const [change, loadErr] = await attempt(() => this.#loadChange(item.name));\n\n if (loadErr) {\n\n results.push({\n name: item.name,\n direction: 'revert',\n status: 'failed',\n files: [],\n durationMs: 0,\n error: loadErr.message,\n });\n\n failed++;\n\n if (opts.abortOnError) break;\n\n continue;\n\n }\n\n const result = await revertChange(this.#context, change, opts);\n results.push(result);\n\n if (result.status === 'success') {\n\n executed++;\n\n }\n else {\n\n failed++;\n\n if (opts.abortOnError) break;\n\n }\n\n }\n\n return {\n status: failed > 0 ? (executed > 0 ? 'partial' : 'failed') : 'success',\n changes: results,\n executed,\n skipped,\n failed,\n durationMs: performance.now() - start,\n };\n\n }\n\n // ─────────────────────────────────────────────────────────\n // History\n // ─────────────────────────────────────────────────────────\n\n /**\n * Get execution history.\n *\n * @param name - Optional change name (all if not provided)\n * @param limit - Max records to return\n * @returns Array of history records\n */\n async getHistory(name?: string, limit?: number): Promise<ChangeHistoryRecord[]> {\n\n return this.#history.getHistory(name, limit);\n\n }\n\n /**\n * Get file execution history for an operation.\n */\n async getFileHistory(operationId: number): Promise<FileHistoryRecord[]> {\n\n return this.#history.getFileHistory(operationId);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Remove\n // ─────────────────────────────────────────────────────────\n\n /**\n * Remove a change from disk, database, or both.\n *\n * @param name - Change name\n * @param options - What to remove\n */\n async remove(name: string, options: { disk?: boolean; db?: boolean }): Promise<void> {\n\n if (options.disk) {\n\n const changePath = path.join(this.#context.changesDir, name);\n\n const [change, loadErr] = await attempt(() =>\n parseChange(changePath, this.#context.sqlDir),\n );\n\n if (!loadErr && change) {\n\n await deleteFromDisk(change);\n\n }\n\n }\n\n if (options.db) {\n\n await this.#history.deleteRecords(name);\n\n }\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Get Single Change\n // ─────────────────────────────────────────────────────────\n\n /**\n * Get a specific change by name.\n */\n async get(name: string): Promise<ChangeListItem | null> {\n\n const list = await this.list();\n\n return list.find((cs) => cs.name === name) ?? null;\n\n }\n\n /**\n * Load a change from disk.\n */\n async load(name: string): Promise<Change> {\n\n return this.#loadChange(name);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Internal\n // ─────────────────────────────────────────────────────────\n\n /**\n * Load a change from disk by name.\n */\n async #loadChange(name: string): Promise<Change> {\n\n const changePath = path.join(this.#context.changesDir, name);\n\n const [change, err] = await attempt(() =>\n parseChange(changePath, this.#context.sqlDir),\n );\n\n if (err) {\n\n // Check if it exists in DB (orphaned)\n const status = await this.#history.getStatus(name);\n\n if (status) {\n\n throw new ChangeOrphanedError(name);\n\n }\n\n throw new ChangeNotFoundError(name);\n\n }\n\n return change;\n\n }\n\n}\n","/**\n * Teardown Operations\n *\n * High-level API for database reset and teardown operations.\n * Uses the explore module for schema introspection and\n * dialect-specific SQL generation for execution.\n */\nimport { attempt } from '@logosdx/utils';\nimport { sql } from 'kysely';\nimport { readFile } from 'fs/promises';\nimport { join } from 'path';\n\nimport type { Kysely } from 'kysely';\nimport type { Dialect } from '../connection/types.js';\nimport type {\n TruncateOptions,\n TruncateResult,\n TeardownOptions,\n TeardownResult,\n TeardownPreview,\n} from './types.js';\nimport { NOORM_TABLES, type NoormDatabase } from '../shared/tables.js';\nimport { fetchList } from '../explore/operations.js';\nimport { getTeardownOperations } from './dialects/index.js';\nimport { observer } from '../observer.js';\nimport { ChangeHistory, ChangeTracker } from '../change/index.js';\n\n/**\n * Names of all noorm internal tables as strings.\n */\nconst NOORM_TABLE_NAMES = new Set<string>(Object.values(NOORM_TABLES));\n\n/**\n * Check if a table name is a noorm internal table.\n * Exported for testing purposes.\n */\nexport function isNoormTable(name: string | undefined | null): boolean {\n\n if (!name) return false;\n\n return name.startsWith('__noorm_') || NOORM_TABLE_NAMES.has(name);\n\n}\n\n/**\n * Truncate data from tables.\n *\n * Disables FK checks, truncates specified tables, then re-enables FK checks.\n *\n * @param db - Kysely database instance\n * @param dialect - Database dialect\n * @param options - Truncate options\n * @returns Result with truncated/preserved tables and SQL statements\n *\n * @example\n * ```typescript\n * // Truncate all tables except preserved ones\n * const result = await truncateData(db, 'postgres', {\n * preserve: ['AppSettings', 'UserRoles'],\n * })\n * console.log(`Truncated: ${result.truncated.join(', ')}`)\n *\n * // Dry run to preview\n * const preview = await truncateData(db, 'postgres', {\n * preserve: ['AppSettings'],\n * dryRun: true,\n * })\n * console.log('SQL:', preview.statements)\n * ```\n */\nexport async function truncateData(\n db: Kysely<unknown>,\n dialect: Dialect,\n options: TruncateOptions = {},\n): Promise<TruncateResult> {\n\n const startTime = performance.now();\n const ops = getTeardownOperations(dialect);\n const statements: string[] = [];\n const truncated: string[] = [];\n const preserved: string[] = [];\n\n observer.emit('teardown:start', { type: 'truncate' });\n\n // Fetch all tables (including noorm tables so we can preserve them)\n const [tables, err] = await attempt(() => fetchList(db, dialect, 'tables', { includeNoormTables: true }));\n\n if (err) {\n\n observer.emit('teardown:error', { error: err, object: null });\n throw err;\n\n }\n\n // Determine which tables to truncate\n const preserveSet = new Set(options.preserve ?? []);\n\n for (const table of tables) {\n\n const tableName = table.name;\n\n // Always preserve noorm tables\n if (isNoormTable(tableName)) {\n\n preserved.push(tableName);\n continue;\n\n }\n\n // Check if table should be preserved\n if (preserveSet.has(tableName)) {\n\n preserved.push(tableName);\n continue;\n\n }\n\n // If 'only' is specified, check if table is in the list\n if (options.only && !options.only.includes(tableName)) {\n\n preserved.push(tableName);\n continue;\n\n }\n\n truncated.push(tableName);\n\n }\n\n // Build SQL statements\n statements.push(ops.disableForeignKeyChecks());\n\n for (const tableName of truncated) {\n\n statements.push(ops.truncateTable(tableName, undefined, options.restartIdentity ?? true));\n\n }\n\n statements.push(ops.enableForeignKeyChecks());\n\n // Execute unless dry run\n if (!options.dryRun) {\n\n for (const stmt of statements) {\n\n // Skip comments\n if (stmt.startsWith('--')) continue;\n\n // Handle multi-statement strings (e.g., SQLite truncate returns two statements)\n const subStatements = stmt.includes('; ')\n ? stmt.split('; ').map(s => s.trim()).filter(s => s.length > 0)\n : [stmt];\n\n for (const subStmt of subStatements) {\n\n observer.emit('teardown:progress', {\n category: 'tables',\n object: subStmt.includes('DELETE') || subStmt.includes('TRUNCATE') ? subStmt : null,\n action: 'truncating',\n });\n\n const [, execErr] = await attempt(() => sql.raw(subStmt).execute(db));\n\n if (execErr) {\n\n observer.emit('teardown:error', { error: execErr, object: subStmt });\n throw execErr;\n\n }\n\n }\n\n }\n\n }\n\n const durationMs = Math.round(performance.now() - startTime);\n\n const result: TruncateResult = {\n truncated,\n preserved,\n statements,\n durationMs,\n };\n\n observer.emit('teardown:complete', { result });\n\n return result;\n\n}\n\n/**\n * Drop all user-created database objects.\n *\n * Preserves noorm internal tables (__noorm_*) and optionally other objects.\n * Order: FK constraints → Tables → Views → Functions → Types\n *\n * @param db - Kysely database instance\n * @param dialect - Database dialect\n * @param options - Teardown options\n * @returns Result with dropped/preserved objects and SQL statements\n *\n * @example\n * ```typescript\n * // Preview what would be dropped\n * const preview = await teardownSchema(db, 'postgres', { dryRun: true })\n * console.log('Tables to drop:', preview.dropped.tables)\n *\n * // Execute teardown\n * const result = await teardownSchema(db, 'postgres', {\n * keepTypes: true, // Keep enum types\n * postScript: 'sql/teardown/cleanup.sql',\n * })\n * ```\n */\nexport async function teardownSchema(\n db: Kysely<unknown>,\n dialect: Dialect,\n options: TeardownOptions = {},\n): Promise<TeardownResult> {\n\n const startTime = performance.now();\n const ops = getTeardownOperations(dialect);\n const statements: string[] = [];\n const preserved: string[] = [];\n const dropped: TeardownResult['dropped'] = {\n tables: [],\n views: [],\n functions: [],\n procedures: [],\n types: [],\n foreignKeys: [],\n };\n\n observer.emit('teardown:start', { type: 'schema' });\n\n const preserveSet = new Set(options.preserveTables ?? []);\n\n // Fetch all objects in parallel (include noorm tables so we can preserve them)\n const [\n [tables, tablesErr],\n [views, viewsErr],\n [functions, functionsErr],\n [procedures, proceduresErr],\n [types, typesErr],\n [foreignKeys, fksErr],\n ] = await Promise.all([\n attempt(() => fetchList(db, dialect, 'tables', { includeNoormTables: true })),\n attempt(() => fetchList(db, dialect, 'views')),\n attempt(() => fetchList(db, dialect, 'functions')),\n attempt(() => fetchList(db, dialect, 'procedures')),\n attempt(() => fetchList(db, dialect, 'types')),\n attempt(() => fetchList(db, dialect, 'foreignKeys')),\n ]);\n\n if (tablesErr) throw tablesErr;\n if (viewsErr) throw viewsErr;\n if (functionsErr) throw functionsErr;\n if (proceduresErr) throw proceduresErr;\n if (typesErr) throw typesErr;\n if (fksErr) throw fksErr;\n\n // 1. Drop FK constraints first (must happen before tables)\n for (const fk of foreignKeys) {\n\n const tableName = fk.tableName;\n\n // Skip noorm tables\n if (isNoormTable(tableName)) continue;\n\n // Skip preserved tables\n if (preserveSet.has(tableName)) continue;\n\n dropped.foreignKeys.push(fk.name);\n statements.push(ops.dropForeignKey(fk.name, tableName, fk.schema));\n\n }\n\n // 2. Drop views (unless keepViews)\n if (!options.keepViews) {\n\n for (const view of views) {\n\n dropped.views.push(view.name);\n statements.push(ops.dropView(view.name, view.schema));\n\n }\n\n }\n\n // 3. Drop tables\n for (const table of tables) {\n\n const tableName = table.name;\n\n // Always preserve noorm tables\n if (isNoormTable(tableName)) {\n\n preserved.push(tableName);\n continue;\n\n }\n\n // Skip preserved tables\n if (preserveSet.has(tableName)) {\n\n preserved.push(tableName);\n continue;\n\n }\n\n dropped.tables.push(tableName);\n statements.push(ops.dropTable(tableName, table.schema));\n\n }\n\n // 4. Drop functions (unless keepFunctions)\n if (!options.keepFunctions) {\n\n for (const fn of functions) {\n\n dropped.functions.push(fn.name);\n statements.push(ops.dropFunction(fn.name, fn.schema));\n\n }\n\n }\n\n // 5. Drop procedures (unless keepProcedures)\n if (!options.keepProcedures) {\n\n for (const proc of procedures) {\n\n dropped.procedures.push(proc.name);\n statements.push(ops.dropProcedure(proc.name, proc.schema));\n\n }\n\n }\n\n // 6. Drop types (unless keepTypes)\n if (!options.keepTypes) {\n\n for (const type of types) {\n\n dropped.types.push(type.name);\n statements.push(ops.dropType(type.name, type.schema));\n\n }\n\n }\n\n // Execute unless dry run\n if (!options.dryRun) {\n\n for (const stmt of statements) {\n\n // Skip comments\n if (stmt.startsWith('--')) continue;\n\n observer.emit('teardown:progress', {\n category: 'tables',\n object: stmt,\n action: 'dropping',\n });\n\n const [, execErr] = await attempt(() => sql.raw(stmt).execute(db));\n\n if (execErr) {\n\n observer.emit('teardown:error', { error: execErr, object: stmt });\n throw execErr;\n\n }\n\n }\n\n }\n\n const durationMs = Math.round(performance.now() - startTime);\n\n const result: TeardownResult = {\n dropped,\n preserved,\n statements,\n durationMs,\n };\n\n // Execute post-script if provided\n if (options.postScript && !options.dryRun) {\n\n const postScriptResult = await executePostScript(db, options.postScript);\n result.postScriptResult = postScriptResult;\n\n }\n\n // Mark changes as stale and record reset if config provided\n if (options.configName && options.executedBy && !options.dryRun) {\n\n const tracker = new ChangeTracker(\n db as Kysely<NoormDatabase>,\n options.configName,\n );\n\n const history = new ChangeHistory(\n db as Kysely<NoormDatabase>,\n options.configName,\n );\n\n // Mark all successful changes as stale\n result.staleCount = await tracker.markAllAsStale();\n\n // Record the reset event\n const parts = [\n `${dropped.tables.length} tables`,\n `${dropped.views.length} views`,\n `${dropped.functions.length} functions`,\n `${dropped.procedures.length} procedures`,\n ];\n result.resetRecordId = await history.recordReset(\n options.executedBy,\n `Schema teardown: dropped ${parts.join(', ')}`,\n );\n\n }\n\n observer.emit('teardown:complete', { result });\n\n return result;\n\n}\n\n/**\n * Preview what would be affected by a teardown operation.\n *\n * @param db - Kysely database instance\n * @param dialect - Database dialect\n * @param options - Teardown options\n * @returns Preview of what would be dropped/preserved\n */\nexport async function previewTeardown(\n db: Kysely<unknown>,\n dialect: Dialect,\n options: TeardownOptions = {},\n): Promise<TeardownPreview> {\n\n // Just run with dryRun: true and convert the result\n const result = await teardownSchema(db, dialect, { ...options, dryRun: true });\n\n return {\n toDrop: result.dropped,\n toPreserve: result.preserved,\n statements: result.statements,\n };\n\n}\n\n/**\n * Execute a post-teardown SQL script.\n */\nasync function executePostScript(\n db: Kysely<unknown>,\n scriptPath: string,\n): Promise<{ executed: boolean; error?: string }> {\n\n const fullPath = join(process.cwd(), scriptPath);\n\n const [content, readErr] = await attempt(() => readFile(fullPath, 'utf-8'));\n\n if (readErr) {\n\n return { executed: false, error: `Failed to read script: ${readErr.message}` };\n\n }\n\n // Split by semicolons and execute each statement\n const stmts = content\n .split(';')\n .map(s => s.trim())\n .filter(s => s.length > 0 && !s.startsWith('--'));\n\n for (const stmt of stmts) {\n\n const [, execErr] = await attempt(() => sql.raw(stmt).execute(db));\n\n if (execErr) {\n\n return { executed: false, error: `Script failed: ${execErr.message}` };\n\n }\n\n }\n\n return { executed: true };\n\n}\n","/**\n * SQL file runner.\n *\n * Executes SQL files against a database connection with:\n * - Checksum-based change detection (skip unchanged files)\n * - Template rendering for .sql.tmpl files\n * - Execution tracking in __noorm_change__ / __noorm_executions__\n * - Preview mode for inspecting rendered SQL\n *\n * WHY: Build systems need idempotent execution. Running unchanged\n * files wastes time and can cause issues with non-idempotent DDL.\n * The runner tracks what has run and skips unchanged files.\n *\n * @example\n * ```typescript\n * import { runBuild, runFile, runDir } from './runner'\n *\n * // Execute all files in schema directory\n * const result = await runBuild(context, '/project/sql', options)\n *\n * // Execute a single file\n * const fileResult = await runFile(context, '/project/sql/001.sql', options)\n *\n * // Execute all files in a directory\n * const dirResult = await runDir(context, '/project/sql/migrations', options)\n * ```\n */\nimport path from 'node:path';\nimport { readFile, readdir, writeFile as fsWriteFile, mkdir } from 'node:fs/promises';\nimport { sql } from 'kysely';\n\nimport { attempt, attemptSync } from '@logosdx/utils';\n\nimport { observer } from '../observer.js';\nimport { formatIdentity } from '../identity/resolver.js';\nimport { processFile, isTemplate } from '../template/index.js';\nimport { computeChecksum, computeChecksumFromContent, computeCombinedChecksum } from './checksum.js';\nimport { Tracker } from './tracker.js';\nimport type {\n RunOptions,\n RunContext,\n FileResult,\n BatchResult,\n BatchStatus,\n FileInput,\n ExecuteFilesOptions,\n ChangeType,\n FilesStatusResult,\n FileStatusResult,\n FileStatusCategory,\n} from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Constants\n// ─────────────────────────────────────────────────────────────\n\nconst SQL_EXTENSIONS = ['.sql', '.sql.tmpl'];\n\nconst FILE_HEADER_TEMPLATE = `-- ============================================================\n-- File: %FILE%\n-- ============================================================\n\n`;\n\n// ─────────────────────────────────────────────────────────────\n// Build Mode\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execute all SQL files in a schema directory.\n *\n * Files are discovered recursively, sorted alphabetically, and\n * executed in order. Use numeric prefixes (001_, 002_) to control\n * execution order.\n *\n * @param context - Run context (db, identity, config)\n * @param sqlPath - Path to SQL files directory\n * @param options - Run options\n * @param preFilteredFiles - Optional pre-filtered file list to skip discovery\n * @returns Batch result with all file results\n *\n * @example\n * ```typescript\n * const result = await runBuild(context, '/project/sql')\n *\n * console.log(`Ran ${result.filesRun} files in ${result.durationMs}ms`)\n * ```\n */\nexport async function runBuild(\n context: RunContext,\n sqlPath: string,\n options: RunOptions = {},\n preFilteredFiles?: string[],\n): Promise<BatchResult> {\n\n const start = performance.now();\n const opts = { ...DEFAULT_RUN_OPTIONS_INTERNAL, ...options };\n\n // Use pre-filtered files or discover from directory\n let files: string[];\n\n if (preFilteredFiles) {\n\n files = preFilteredFiles;\n\n }\n else {\n\n const [discovered, discoverErr] = await attempt(() => discoverFiles(sqlPath));\n\n if (discoverErr) {\n\n observer.emit('error', {\n source: 'runner',\n error: discoverErr,\n context: { sqlPath, operation: 'discover-files' },\n });\n\n return createFailedBatchResult(discoverErr.message, performance.now() - start);\n\n }\n\n files = discovered;\n\n }\n\n observer.emit('build:start', {\n sqlPath,\n fileCount: files.length,\n });\n\n // Execute files\n const result = await executeFilesInternal(context, files, opts, 'build');\n\n observer.emit('build:complete', {\n status: result.status,\n filesRun: result.filesRun,\n filesSkipped: result.filesSkipped,\n filesFailed: result.filesFailed,\n durationMs: result.durationMs,\n });\n\n return result;\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// File Mode\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execute a single SQL file.\n *\n * @param context - Run context\n * @param filepath - Path to SQL file\n * @param options - Run options\n * @returns File result\n *\n * @example\n * ```typescript\n * const result = await runFile(context, '/project/sql/001_users.sql')\n *\n * if (result.status === 'success') {\n * console.log('File executed successfully')\n * }\n * ```\n */\nexport async function runFile(\n context: RunContext,\n filepath: string,\n options: RunOptions = {},\n): Promise<FileResult> {\n\n const opts = { ...DEFAULT_RUN_OPTIONS_INTERNAL, ...options };\n\n observer.emit('run:file', {\n filepath,\n configName: context.configName,\n });\n\n // For single file, we still create an operation record for tracking\n const tracker = new Tracker(context.db, context.configName);\n const operationName = `run:${new Date().toISOString()}`;\n\n const [operationId, createErr] = await attempt(() =>\n tracker.createOperation({\n name: operationName,\n changeType: 'run',\n configName: context.configName,\n executedBy: formatIdentity(context.identity),\n }),\n );\n\n if (createErr) {\n\n observer.emit('error', {\n source: 'runner',\n error: createErr,\n context: { filepath, operation: 'create-operation' },\n });\n\n return {\n filepath,\n checksum: '',\n status: 'failed',\n error: createErr.message,\n };\n\n }\n\n const result = await executeSingleFile(context, filepath, opts, tracker, operationId!);\n\n // Finalize operation\n await tracker.finalizeOperation(\n operationId!,\n result.status === 'failed' ? 'failed' : 'success',\n Math.round(result.durationMs ?? 0),\n result.checksum,\n result.error,\n );\n\n return result;\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Dir Mode\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execute all SQL files in a directory.\n *\n * Similar to build mode but for a specific directory.\n *\n * @param context - Run context\n * @param dirpath - Path to directory\n * @param options - Run options\n * @returns Batch result\n *\n * @example\n * ```typescript\n * const result = await runDir(context, '/project/sql/migrations')\n * ```\n */\nexport async function runDir(\n context: RunContext,\n dirpath: string,\n options: RunOptions = {},\n): Promise<BatchResult> {\n\n const start = performance.now();\n const opts = { ...DEFAULT_RUN_OPTIONS_INTERNAL, ...options };\n\n // Discover files\n const [files, discoverErr] = await attempt(() => discoverFiles(dirpath));\n\n if (discoverErr) {\n\n observer.emit('error', {\n source: 'runner',\n error: discoverErr,\n context: { dirpath, operation: 'discover-files' },\n });\n\n return createFailedBatchResult(discoverErr.message, performance.now() - start);\n\n }\n\n observer.emit('run:dir', {\n dirpath,\n fileCount: files.length,\n configName: context.configName,\n });\n\n // Execute files\n return executeFilesInternal(context, files, opts, 'run');\n\n}\n\n/**\n * Run specific SQL files.\n *\n * Executes the given list of files in order.\n *\n * @param context - Run context\n * @param files - Array of file paths to execute\n * @param options - Run options\n * @returns Batch result\n */\nexport async function runFiles(\n context: RunContext,\n files: string[],\n options: RunOptions = {},\n): Promise<BatchResult> {\n\n const opts = { ...DEFAULT_RUN_OPTIONS_INTERNAL, ...options };\n\n observer.emit('run:files', {\n fileCount: files.length,\n configName: context.configName,\n });\n\n // Execute files\n return executeFilesInternal(context, files, opts, 'run');\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Preview Mode\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Preview rendered SQL without executing.\n *\n * Useful for debugging templates and verifying SQL before execution.\n *\n * @param context - Run context\n * @param filepaths - Files to preview\n * @param output - Optional output file path\n * @returns Array of file results with rendered SQL\n */\nexport async function preview(\n context: RunContext,\n filepaths: string[],\n output?: string | null,\n): Promise<FileResult[]> {\n\n const results: FileResult[] = [];\n const rendered: string[] = [];\n\n for (const filepath of filepaths) {\n\n const [sqlContent, err] = await attempt(() => loadAndRenderFile(context, filepath));\n\n if (err) {\n\n results.push({\n filepath,\n checksum: '',\n status: 'failed',\n error: err.message,\n });\n continue;\n\n }\n\n const checksum = await computeChecksum(filepath);\n\n results.push({\n filepath,\n checksum,\n status: 'success',\n renderedSql: sqlContent,\n });\n\n rendered.push(FILE_HEADER_TEMPLATE.replace('%FILE%', filepath) + sqlContent);\n\n }\n\n // Output results\n const combinedSql = rendered.join('\\n\\n');\n\n if (output) {\n\n const [, writeErr] = await attempt(() => fsWriteFile(output, combinedSql, 'utf-8'));\n\n if (writeErr) {\n\n observer.emit('error', {\n source: 'runner',\n error: writeErr,\n context: { output, operation: 'write-preview' },\n });\n\n }\n\n }\n else {\n // In a real CLI, this would go to stdout\n // For the core module, we just return the results\n }\n\n return results;\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// File Status Check (Pre-execution)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Check status of files before execution.\n *\n * Determines which files are new, previously run, changed, or failed\n * without actually executing them. Useful for showing confirmation\n * dialogs before re-running files.\n *\n * @param context - Run context (db, configName required)\n * @param files - File paths to check\n * @returns Categorized file statuses\n *\n * @example\n * ```typescript\n * const status = await checkFilesStatus(context, ['/sql/seed.sql'])\n *\n * if (status.previouslyRunFiles.length > 0) {\n * // Show confirmation dialog\n * console.log(`${status.previouslyRunFiles.length} file(s) were previously run`)\n * }\n * ```\n */\nexport async function checkFilesStatus(\n context: RunContext,\n files: string[],\n): Promise<FilesStatusResult> {\n\n const tracker = new Tracker(context.db, context.configName);\n const results: FileStatusResult[] = [];\n\n for (const filepath of files) {\n\n // Load and render file to compute checksum\n // Templates need rendering before checksum computation\n const [sqlContent, loadErr] = await attempt(() => loadAndRenderFile(context, filepath));\n\n if (loadErr) {\n\n // Can't check status if we can't read the file\n results.push({\n filepath,\n checksum: '',\n category: 'new',\n wouldSkip: false,\n });\n continue;\n\n }\n\n // Compute checksum from rendered content\n const [checksum, checksumErr] = attemptSync(() => computeChecksumFromContent(sqlContent));\n\n if (checksumErr) {\n\n results.push({\n filepath,\n checksum: '',\n category: 'new',\n wouldSkip: false,\n });\n continue;\n\n }\n\n // Check if file needs to run (without force flag)\n const needsRunResult = await tracker.needsRun(filepath, checksum, false);\n\n let category: FileStatusCategory;\n\n if (!needsRunResult.needsRun) {\n\n // File would be skipped - it was previously run with same content\n category = 'previously-run';\n\n }\n else if (needsRunResult.reason === 'new') {\n\n category = 'new';\n\n }\n else if (needsRunResult.reason === 'changed') {\n\n category = 'changed';\n\n }\n else if (needsRunResult.reason === 'failed') {\n\n category = 'failed';\n\n }\n else {\n\n // stale, force, etc. - treat as new\n category = 'new';\n\n }\n\n results.push({\n filepath,\n checksum,\n category,\n wouldSkip: !needsRunResult.needsRun,\n });\n\n }\n\n // Categorize results\n const newFiles = results.filter((r) => r.category === 'new').map((r) => r.filepath);\n const previouslyRunFiles = results.filter((r) => r.category === 'previously-run').map((r) => r.filepath);\n const changedFiles = results.filter((r) => r.category === 'changed').map((r) => r.filepath);\n const failedFiles = results.filter((r) => r.category === 'failed').map((r) => r.filepath);\n const wouldSkipCount = results.filter((r) => r.wouldSkip).length;\n\n return {\n files: results,\n newFiles,\n previouslyRunFiles,\n changedFiles,\n failedFiles,\n wouldSkipCount,\n };\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Internal Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Internal default options (avoids import cycle with types).\n */\nconst DEFAULT_RUN_OPTIONS_INTERNAL = {\n force: false,\n concurrency: 1,\n abortOnError: true,\n dryRun: false,\n preview: false,\n output: null as string | null,\n};\n\n/**\n * Execute multiple files with tracking.\n *\n * This is the unified execution function used by both runner and change modules.\n * It creates pending records upfront for full batch visibility, then executes\n * files sequentially, updating records as it goes.\n *\n * @param context - Run context\n * @param files - Files to execute (gathered externally)\n * @param runOptions - Execution options (force, dryRun, etc.)\n * @param execOptions - Operation metadata (changeType, operationName, etc.)\n * @returns Batch result with all file results\n */\nexport async function executeFiles(\n context: RunContext,\n files: FileInput[],\n runOptions: RunOptions,\n execOptions: ExecuteFilesOptions,\n): Promise<BatchResult> {\n\n const start = performance.now();\n const opts = { ...DEFAULT_RUN_OPTIONS_INTERNAL, ...runOptions };\n\n // Convert FileInput[] to string[] for preview/dryRun modes\n const filepaths = files.map((f) => f.path);\n\n // Handle preview mode\n if (opts.preview) {\n\n const results = await preview(context, filepaths, opts.output);\n const durationMs = performance.now() - start;\n\n return {\n status: results.every((r) => r.status !== 'failed') ? 'success' : 'failed',\n files: results,\n filesRun: 0,\n filesSkipped: 0,\n filesFailed: results.filter((r) => r.status === 'failed').length,\n durationMs,\n };\n\n }\n\n // Handle dry run mode - no tracking, just render and write to tmp/\n if (opts.dryRun) {\n\n const results = await executeDryRun(context, filepaths);\n const durationMs = performance.now() - start;\n\n return {\n status: results.every((r) => r.status !== 'failed') ? 'success' : 'failed',\n files: results,\n filesRun: results.filter((r) => r.status === 'success').length,\n filesSkipped: 0,\n filesFailed: results.filter((r) => r.status === 'failed').length,\n durationMs,\n };\n\n }\n\n // Use provided tracker or create new one\n const tracker = (execOptions.tracker as Tracker) ?? new Tracker(context.db, context.configName);\n\n // Create operation record\n const [operationId, createErr] = await attempt(() =>\n tracker.createOperation({\n name: execOptions.operationName,\n changeType: execOptions.changeType,\n direction: execOptions.direction,\n configName: context.configName,\n executedBy: formatIdentity(context.identity),\n }),\n );\n\n if (createErr) {\n\n observer.emit('error', {\n source: 'runner:create-operation',\n error: createErr,\n context: { operationName: execOptions.operationName },\n });\n\n return createFailedBatchResult(createErr.message, performance.now() - start);\n\n }\n\n // Compute checksums for files that don't have them\n const fileRecords: Array<{ filepath: string; fileType: 'sql' | 'txt'; checksum: string }> = [];\n\n for (const file of files) {\n\n let checksum = file.checksum;\n\n if (!checksum) {\n\n const [computed, err] = await attempt(() => computeChecksum(file.path));\n checksum = err ? '' : computed;\n\n }\n\n fileRecords.push({\n filepath: file.path,\n fileType: file.type,\n checksum,\n });\n\n }\n\n // Create ALL file records upfront (pending status)\n // This gives full visibility into the batch before execution starts\n const createRecordsErr = await tracker.createFileRecords(operationId!, fileRecords);\n\n if (createRecordsErr) {\n\n observer.emit('error', {\n source: 'runner:create-file-records',\n error: new Error(createRecordsErr),\n context: { operationId: operationId! },\n });\n\n await tracker.finalizeOperation(operationId!, 'failed', 0, '', createRecordsErr);\n\n return createFailedBatchResult(createRecordsErr, performance.now() - start);\n\n }\n\n // Execute files sequentially (concurrency is typically 1 for DDL safety)\n const results: FileResult[] = [];\n let failed = false;\n\n for (let i = 0; i < files.length; i++) {\n\n const file = files[i]!;\n const fileRecord = fileRecords[i]!;\n\n const result = await executeSingleFileWithUpdate(\n context,\n file.path,\n fileRecord.checksum,\n opts,\n tracker,\n operationId!,\n execOptions.changeType,\n );\n\n results.push(result);\n\n // Abort on error if configured\n if (result.status === 'failed' && opts.abortOnError) {\n\n failed = true;\n\n // Mark remaining files as skipped\n const skipErr = await tracker.skipRemainingFiles(\n operationId!,\n `Skipped due to failure in ${file.path}`,\n );\n\n if (skipErr) {\n\n observer.emit('error', {\n source: 'runner:skip-remaining',\n error: new Error(skipErr),\n context: { operationId: operationId! },\n });\n\n }\n\n break;\n\n }\n\n }\n\n // Compute stats\n const filesRun = results.filter((r) => r.status === 'success').length;\n const filesSkipped = results.filter((r) => r.status === 'skipped').length;\n const filesFailed = results.filter((r) => r.status === 'failed').length;\n const durationMs = performance.now() - start;\n\n // Determine overall status\n let status: BatchStatus = 'success';\n\n if (filesFailed > 0 || failed) {\n\n status = filesRun > 0 ? 'partial' : 'failed';\n\n }\n\n // Compute combined checksum (or use provided)\n const combinedChecksum =\n execOptions.checksum ?? computeCombinedChecksum(fileRecords.map((f) => f.checksum));\n\n // Finalize operation (partial failures count as failed)\n // Compute final status AFTER all operations\n const finalStatus = status === 'success' ? 'success' : 'failed';\n\n const finalizeErr = await tracker.finalizeOperation(\n operationId!,\n finalStatus,\n Math.round(durationMs),\n combinedChecksum,\n failed ? results.find((r) => r.status === 'failed')?.error : undefined,\n );\n\n if (finalizeErr) {\n\n observer.emit('error', {\n source: 'runner:finalize',\n error: new Error(finalizeErr),\n context: { operationId: operationId! },\n });\n\n }\n\n return {\n status,\n files: results,\n filesRun,\n filesSkipped,\n filesFailed,\n durationMs,\n changeId: operationId,\n };\n\n}\n\n/**\n * Internal wrapper for legacy callers.\n *\n * Converts string[] to FileInput[] and creates ExecuteFilesOptions.\n */\nasync function executeFilesInternal(\n context: RunContext,\n files: string[],\n options: Required<Omit<RunOptions, 'output'>> & { output: string | null },\n changeType: 'build' | 'run',\n): Promise<BatchResult> {\n\n // Convert string[] to FileInput[]\n const fileInputs: FileInput[] = files.map((f) => ({\n path: f,\n type: 'sql' as const,\n }));\n\n // Create ExecuteFilesOptions\n const execOptions: ExecuteFilesOptions = {\n changeType,\n direction: 'commit',\n operationName: `${changeType}:${new Date().toISOString()}`,\n };\n\n return executeFiles(context, fileInputs, options, execOptions);\n\n}\n\n/**\n * Execute a single file with upfront record update.\n *\n * This version uses updateFileExecution (records created upfront)\n * instead of recordExecution (insert on execution).\n *\n * @param context - Run context\n * @param filepath - File to execute\n * @param checksum - Pre-computed checksum\n * @param options - Run options\n * @param tracker - Tracker instance\n * @param operationId - Parent operation ID\n * @param changeType - Type of operation (affects needsRun behavior)\n */\nasync function executeSingleFileWithUpdate(\n context: RunContext,\n filepath: string,\n checksum: string,\n options: Required<Omit<RunOptions, 'output'>> & { output: string | null },\n tracker: Tracker,\n operationId: number,\n changeType: ChangeType,\n): Promise<FileResult> {\n\n const start = performance.now();\n\n // Load and render file\n const [sqlContent, loadErr] = await attempt(() => loadAndRenderFile(context, filepath));\n\n if (loadErr) {\n\n const durationMs = performance.now() - start;\n const result: FileResult = {\n filepath,\n checksum: checksum || '',\n status: 'failed',\n error: loadErr.message,\n durationMs,\n };\n\n await tracker.updateFileExecution(\n operationId,\n filepath,\n 'failed',\n Math.round(durationMs),\n loadErr.message,\n );\n\n observer.emit('file:after', {\n filepath,\n status: 'failed',\n durationMs,\n error: loadErr.message,\n });\n\n return result;\n\n }\n\n // Recompute checksum from rendered content for templates\n const [renderedChecksum, checksumErr] = attemptSync(() => computeChecksumFromContent(sqlContent));\n const finalChecksum = checksumErr ? checksum : renderedChecksum;\n\n observer.emit('file:before', {\n filepath,\n checksum: finalChecksum,\n configName: context.configName,\n });\n\n // For 'build' and 'run', check if individual file needs to run\n // For 'change', the change-level check was already done by the caller\n if (changeType !== 'change') {\n\n const needsRunResult = await tracker.needsRun(filepath, finalChecksum, options.force);\n\n if (!needsRunResult.needsRun) {\n\n const result: FileResult = {\n filepath,\n checksum: finalChecksum,\n status: 'skipped',\n skipReason: needsRunResult.skipReason,\n };\n\n await tracker.updateFileExecution(\n operationId,\n filepath,\n 'skipped',\n 0,\n undefined,\n needsRunResult.skipReason,\n );\n\n observer.emit('file:skip', {\n filepath,\n reason: needsRunResult.skipReason!,\n });\n\n return result;\n\n }\n\n }\n\n // Execute SQL\n const [, execErr] = await attempt(() => sql.raw(sqlContent).execute(context.db));\n\n const durationMs = performance.now() - start;\n\n if (execErr) {\n\n const result: FileResult = {\n filepath,\n checksum: finalChecksum,\n status: 'failed',\n error: execErr.message,\n durationMs,\n };\n\n await tracker.updateFileExecution(\n operationId,\n filepath,\n 'failed',\n Math.round(durationMs),\n execErr.message,\n );\n\n observer.emit('file:after', {\n filepath,\n status: 'failed',\n durationMs,\n error: execErr.message,\n });\n\n return result;\n\n }\n\n // Success\n const result: FileResult = {\n filepath,\n checksum: finalChecksum,\n status: 'success',\n durationMs,\n };\n\n await tracker.updateFileExecution(\n operationId,\n filepath,\n 'success',\n Math.round(durationMs),\n );\n\n observer.emit('file:after', {\n filepath,\n status: 'success',\n durationMs,\n });\n\n return result;\n\n}\n\n/**\n * Execute a single file (legacy version for runFile).\n *\n * Uses recordExecution (insert) instead of updateFileExecution.\n */\nasync function executeSingleFile(\n context: RunContext,\n filepath: string,\n options: Required<Omit<RunOptions, 'output'>> & { output: string | null },\n tracker: Tracker,\n operationId: number,\n): Promise<FileResult> {\n\n const start = performance.now();\n\n // Load and render file\n // Needed before checksum to support templates\n const [sqlContent, loadErr] = await attempt(() => loadAndRenderFile(context, filepath));\n\n if (loadErr) {\n\n const durationMs = performance.now() - start;\n const result: FileResult = {\n filepath,\n checksum: '',\n status: 'failed',\n error: loadErr.message,\n durationMs,\n };\n\n await tracker.recordExecution({\n changeId: operationId,\n filepath,\n checksum: '',\n status: 'failed',\n errorMessage: loadErr.message,\n durationMs: Math.round(durationMs),\n });\n\n observer.emit('file:after', {\n filepath,\n status: 'failed',\n durationMs,\n error: loadErr.message,\n });\n\n return result;\n\n }\n\n // Compute checksum\n const [checksum, checksumErr] = attemptSync(() => computeChecksumFromContent(sqlContent));\n\n if (checksumErr) {\n\n const result: FileResult = {\n filepath,\n checksum: '',\n status: 'failed',\n error: checksumErr.message,\n durationMs: performance.now() - start,\n };\n\n await tracker.recordExecution({\n changeId: operationId,\n filepath,\n checksum: '',\n status: 'failed',\n errorMessage: checksumErr.message,\n durationMs: Math.round(result.durationMs ?? 0),\n });\n\n observer.emit('file:after', {\n filepath,\n status: 'failed',\n durationMs: result.durationMs ?? 0,\n error: checksumErr.message,\n });\n\n return result;\n\n }\n\n observer.emit('file:before', {\n filepath,\n checksum,\n configName: context.configName,\n });\n\n // Check if file needs to run\n const needsRunResult = await tracker.needsRun(filepath, checksum, options.force);\n\n if (!needsRunResult.needsRun) {\n\n const result: FileResult = {\n filepath,\n checksum,\n status: 'skipped',\n skipReason: needsRunResult.skipReason,\n };\n\n await tracker.recordExecution({\n changeId: operationId,\n filepath,\n checksum,\n status: 'skipped',\n skipReason: needsRunResult.skipReason,\n });\n\n observer.emit('file:skip', {\n filepath,\n reason: needsRunResult.skipReason!,\n });\n\n return result;\n\n }\n\n // Execute SQL\n const [, execErr] = await attempt(() => sql.raw(sqlContent).execute(context.db));\n\n const durationMs = performance.now() - start;\n\n if (execErr) {\n\n const result: FileResult = {\n filepath,\n checksum,\n status: 'failed',\n error: execErr.message,\n durationMs,\n };\n\n await tracker.recordExecution({\n changeId: operationId,\n filepath,\n checksum,\n status: 'failed',\n errorMessage: execErr.message,\n durationMs: Math.round(durationMs),\n });\n\n observer.emit('file:after', {\n filepath,\n status: 'failed',\n durationMs,\n error: execErr.message,\n });\n\n return result;\n\n }\n\n // Success\n const result: FileResult = {\n filepath,\n checksum,\n status: 'success',\n durationMs,\n };\n\n await tracker.recordExecution({\n changeId: operationId,\n filepath,\n checksum,\n status: 'success',\n durationMs: Math.round(durationMs),\n });\n\n observer.emit('file:after', {\n filepath,\n status: 'success',\n durationMs,\n });\n\n return result;\n\n}\n\n/**\n * Load and optionally render a SQL file.\n */\nasync function loadAndRenderFile(context: RunContext, filepath: string): Promise<string> {\n\n if (isTemplate(filepath)) {\n\n const result = await processFile(filepath, {\n projectRoot: context.projectRoot,\n config: context.config,\n secrets: context.secrets,\n globalSecrets: context.globalSecrets,\n });\n\n return result.sql;\n\n }\n\n const [content, err] = await attempt(() => readFile(filepath, 'utf-8'));\n\n if (err) {\n\n throw new Error(`Failed to read file: ${filepath}`, { cause: err });\n\n }\n\n return content;\n\n}\n\n/**\n * Execute dry run for multiple files.\n *\n * Renders templates and writes to tmp/ without tracking or executing.\n */\nasync function executeDryRun(context: RunContext, files: string[]): Promise<FileResult[]> {\n\n const results: FileResult[] = [];\n\n for (const filepath of files) {\n\n const start = performance.now();\n\n // Compute checksum\n const [checksum, checksumErr] = await attempt(() => computeChecksum(filepath));\n\n if (checksumErr) {\n\n observer.emit('file:dry-run', {\n filepath,\n status: 'failed',\n error: checksumErr.message,\n });\n\n results.push({\n filepath,\n checksum: '',\n status: 'failed',\n error: checksumErr.message,\n durationMs: performance.now() - start,\n });\n continue;\n\n }\n\n // Load and render file\n const [sqlContent, loadErr] = await attempt(() => loadAndRenderFile(context, filepath));\n\n if (loadErr) {\n\n observer.emit('file:dry-run', {\n filepath,\n status: 'failed',\n error: loadErr.message,\n });\n\n results.push({\n filepath,\n checksum,\n status: 'failed',\n error: loadErr.message,\n durationMs: performance.now() - start,\n });\n continue;\n\n }\n\n // Write to tmp/\n const [, writeErr] = await attempt(() =>\n writeDryRunOutput(context.projectRoot, filepath, sqlContent),\n );\n\n const durationMs = performance.now() - start;\n\n if (writeErr) {\n\n observer.emit('error', {\n source: 'runner',\n error: writeErr,\n context: { filepath, operation: 'dry-run-write' },\n });\n\n }\n\n const outputPath = getDryRunOutputPath(context.projectRoot, filepath);\n\n observer.emit('file:dry-run', {\n filepath,\n status: 'success',\n outputPath,\n });\n\n results.push({\n filepath,\n checksum,\n status: 'success',\n durationMs,\n renderedSql: sqlContent,\n });\n\n }\n\n return results;\n\n}\n\n/**\n * Get the output path for a dry run file.\n *\n * Mirrors the source path structure under tmp/, stripping .tmpl extension.\n * Example: sql/views/my_view.sql.tmpl → tmp/sql/views/my_view.sql\n */\nfunction getDryRunOutputPath(projectRoot: string, filepath: string): string {\n\n const relativePath = path.relative(projectRoot, filepath);\n\n const outputRelativePath = relativePath.endsWith('.tmpl')\n ? relativePath.slice(0, -5)\n : relativePath;\n\n return path.join(projectRoot, 'tmp', outputRelativePath);\n\n}\n\n/**\n * Write rendered SQL to tmp/ directory for dry run.\n */\nasync function writeDryRunOutput(\n projectRoot: string,\n filepath: string,\n content: string,\n): Promise<void> {\n\n const outputPath = getDryRunOutputPath(projectRoot, filepath);\n\n // Ensure directory exists\n const outputDir = path.dirname(outputPath);\n await mkdir(outputDir, { recursive: true });\n\n // Write file\n await fsWriteFile(outputPath, content, 'utf-8');\n\n}\n\n/**\n * Discover SQL files in a directory recursively.\n *\n * Finds all `.sql` and `.sql.tmpl` files, sorted alphabetically\n * for deterministic execution order.\n *\n * @param dirpath - Directory to scan\n * @returns Sorted array of absolute file paths\n *\n * @example\n * ```typescript\n * const files = await discoverFiles('/project/sql')\n * // ['/project/sql/tables/users.sql', '/project/sql/views/active_users.sql']\n * ```\n */\nexport async function discoverFiles(dirpath: string): Promise<string[]> {\n\n const files: string[] = [];\n\n async function scan(dir: string): Promise<void> {\n\n const [entries, err] = await attempt(() => readdir(dir, { withFileTypes: true }));\n\n if (err) {\n\n throw new Error(`Failed to read directory: ${dir}`, { cause: err });\n\n }\n\n for (const entry of entries) {\n\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n\n await scan(fullPath);\n\n }\n else if (entry.isFile() && isSqlFile(entry.name)) {\n\n files.push(fullPath);\n\n }\n\n }\n\n }\n\n await scan(dirpath);\n\n // Sort alphabetically for deterministic order\n return files.sort();\n\n}\n\n/**\n * Check if a filename is a SQL file.\n */\nfunction isSqlFile(filename: string): boolean {\n\n return SQL_EXTENSIONS.some((ext) => filename.endsWith(ext));\n\n}\n\n/**\n * Create a failed batch result.\n */\nfunction createFailedBatchResult(error: string, durationMs: number): BatchResult {\n\n return {\n status: 'failed',\n files: [],\n filesRun: 0,\n filesSkipped: 0,\n filesFailed: 0,\n durationMs,\n };\n\n}\n","/**\n * Dual connection infrastructure.\n *\n * Generic infrastructure for cross-database operations.\n * Provides a safe way to work with two database connections simultaneously,\n * with proper lifecycle management and cleanup.\n *\n * Used by:\n * - vault cp (copy secrets between configs)\n * - Future: db transfer, db backup/restore, etc.\n */\nimport type { Kysely } from 'kysely';\n\nimport { attempt } from '@logosdx/utils';\n\nimport type { ConnectionResult, Dialect } from '../connection/types.js';\nimport type { Config } from '../config/types.js';\nimport type { NoormDatabase } from '../shared/tables.js';\nimport { createConnection } from '../connection/factory.js';\nimport { observer } from '../observer.js';\nimport { ensureSchemaVersion } from '../version/schema/index.js';\n\n/**\n * Connection info for dual connection context.\n */\nexport interface DualConnectionEntry {\n config: Config;\n db: Kysely<NoormDatabase>;\n dialect: Dialect;\n}\n\n/**\n * Context passed to dual connection operations.\n */\nexport interface DualConnectionContext {\n source: DualConnectionEntry;\n destination: DualConnectionEntry;\n}\n\n/**\n * Options for dual connection operations.\n */\nexport interface DualConnectionOptions {\n /** Source config object */\n sourceConfig: Config;\n\n /** Destination config object */\n destConfig: Config;\n\n /** Bootstrap noorm tables on destination if needed (default: true) */\n ensureSchema?: boolean;\n}\n\n/**\n * Execute an operation with two database connections.\n *\n * Handles connection lifecycle for both databases, ensuring proper\n * cleanup even on failure. This is foundational infrastructure for\n * all cross-database operations.\n *\n * @param options - Source and destination config objects\n * @param fn - Function to execute with both connections\n * @returns Tuple of [result, error]\n *\n * @example\n * ```typescript\n * const [result, err] = await withDualConnection(\n * { sourceConfig, destConfig, cliVersion: '1.0.0' },\n * async (ctx) => {\n * // Copy data from source to destination\n * const rows = await ctx.source.db.selectFrom('table').execute();\n * for (const row of rows) {\n * await ctx.destination.db.insertInto('table').values(row).execute();\n * }\n * return { copiedCount: rows.length };\n * },\n * );\n *\n * if (err) {\n * console.error('Copy failed:', err.message);\n * }\n * ```\n */\nexport async function withDualConnection<T>(\n options: DualConnectionOptions,\n fn: (ctx: DualConnectionContext) => Promise<T>,\n): Promise<[T | null, Error | null]> {\n\n const { sourceConfig, destConfig, ensureSchema = true } = options;\n\n let sourceConn: ConnectionResult | null = null;\n let destConn: ConnectionResult | null = null;\n\n observer.emit('db:dual:connecting', {\n source: sourceConfig.name,\n destination: destConfig.name,\n });\n\n const [result, err] = await attempt(async () => {\n\n // Connect to source database\n sourceConn = await createConnection(sourceConfig.connection, sourceConfig.name);\n\n // Connect to destination database\n destConn = await createConnection(destConfig.connection, destConfig.name);\n\n observer.emit('db:dual:connected', {\n source: sourceConfig.name,\n destination: destConfig.name,\n });\n\n // Optionally bootstrap noorm schema on destination\n if (ensureSchema) {\n\n await ensureSchemaVersion(\n destConn.db as Kysely<NoormDatabase>,\n destConn.dialect,\n );\n\n }\n\n // Execute the operation\n return fn({\n source: {\n config: sourceConfig,\n db: sourceConn.db as Kysely<NoormDatabase>,\n dialect: sourceConn.dialect,\n },\n destination: {\n config: destConfig,\n db: destConn.db as Kysely<NoormDatabase>,\n dialect: destConn.dialect,\n },\n });\n\n });\n\n // ALWAYS cleanup - even if one fails, try to close the other\n const cleanupErrors: Error[] = [];\n\n observer.emit('db:dual:disconnecting', {\n source: sourceConfig.name,\n destination: destConfig.name,\n });\n\n if (sourceConn) {\n\n const [, closeErr] = await attempt(() => sourceConn!.destroy());\n if (closeErr) cleanupErrors.push(closeErr);\n\n }\n\n if (destConn) {\n\n const [, closeErr] = await attempt(() => destConn!.destroy());\n if (closeErr) cleanupErrors.push(closeErr);\n\n }\n\n observer.emit('db:dual:disconnected', {\n source: sourceConfig.name,\n destination: destConfig.name,\n });\n\n // If main operation succeeded but cleanup failed, log but don't fail\n if (!err && cleanupErrors.length > 0) {\n\n observer.emit('db:dual:cleanup-warning', { errors: cleanupErrors.map((e) => e.message) });\n\n }\n\n return [result, err];\n\n}\n","/**\n * Same-server detection for transfer optimization.\n *\n * Determines if source and destination databases are on the same server,\n * enabling direct INSERT...SELECT transfers without data marshalling.\n */\nimport type { ConnectionConfig, Dialect } from '../connection/types.js';\n\n/**\n * Default ports by dialect.\n */\nconst DEFAULT_PORTS: Record<Dialect, number> = {\n postgres: 5432,\n mysql: 3306,\n mssql: 1433,\n sqlite: 0, // Not applicable\n};\n\n/**\n * Normalize a hostname for comparison.\n *\n * Handles common aliases like localhost, 127.0.0.1, etc.\n */\nfunction normalizeHost(host: string | undefined): string {\n\n const h = (host ?? 'localhost').toLowerCase();\n\n // Normalize localhost variants\n if (h === '127.0.0.1' || h === '::1' || h === 'localhost.localdomain') {\n\n return 'localhost';\n\n }\n\n return h;\n\n}\n\n/**\n * Check if two connection configs point to the same database instance.\n *\n * Same-server optimization (direct INSERT...SELECT) requires:\n * - Same dialect\n * - Same host (after normalization)\n * - Same port\n * - Same database (required for PostgreSQL, optional for MySQL/MSSQL)\n *\n * Note: PostgreSQL cannot do cross-database queries without extensions,\n * so different databases on the same host are NOT considered \"same server\".\n * MySQL and MSSQL can query across databases on the same server.\n *\n * SQLite is never considered \"same server\" since there's no server.\n *\n * @param source - Source connection config\n * @param dest - Destination connection config\n * @returns true if direct INSERT...SELECT is possible\n *\n * @example\n * ```typescript\n * const sameServer = isSameServer(sourceConfig, destConfig);\n * if (sameServer) {\n * // Use direct INSERT...SELECT\n * } else {\n * // Use batch transfer with data marshalling\n * }\n * ```\n */\nexport function isSameServer(\n source: ConnectionConfig,\n dest: ConnectionConfig,\n): boolean {\n\n // Different dialects = different servers\n if (source.dialect !== dest.dialect) {\n\n return false;\n\n }\n\n // SQLite has no server concept\n if (source.dialect === 'sqlite') {\n\n return false;\n\n }\n\n const srcHost = normalizeHost(source.host);\n const dstHost = normalizeHost(dest.host);\n\n const srcPort = source.port ?? DEFAULT_PORTS[source.dialect];\n const dstPort = dest.port ?? DEFAULT_PORTS[dest.dialect];\n\n // Must be same host and port\n if (srcHost !== dstHost || srcPort !== dstPort) {\n\n return false;\n\n }\n\n // PostgreSQL cannot do cross-database queries without extensions\n // So different databases = not same server for optimization purposes\n if (source.dialect === 'postgres') {\n\n return source.database === dest.database;\n\n }\n\n // MySQL and MSSQL support cross-database queries on same server\n return true;\n\n}\n\n/**\n * Get the default port for a dialect.\n *\n * @param dialect - Database dialect\n * @returns Default port number\n */\nexport function getDefaultPort(dialect: Dialect): number {\n\n return DEFAULT_PORTS[dialect];\n\n}\n","/**\n * PostgreSQL transfer operations.\n *\n * Uses session_replication_role for FK bypass, OVERRIDING SYSTEM VALUE\n * for identity columns, and ON CONFLICT for upsert handling.\n */\nimport { sql } from 'kysely';\n\nimport type { Kysely } from 'kysely';\nimport type { NoormDatabase } from '../../shared/tables.js';\nimport type { TransferDialectOperations } from './types.js';\nimport type { ConflictStrategy } from '../types.js';\n\n/**\n * Quote an identifier for PostgreSQL.\n */\nfunction quoteIdent(name: string): string {\n\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n\n}\n\n/**\n * PostgreSQL-specific transfer operations.\n */\nexport const postgresTransferOperations: TransferDialectOperations = {\n\n getDisableFKSql(): string {\n\n // Disables all trigger-based constraint checking (including FKs)\n return 'SET session_replication_role = replica';\n\n },\n\n getEnableFKSql(): string {\n\n return 'SET session_replication_role = DEFAULT';\n\n },\n\n getEnableIdentityInsertSql(_table: string): string | null {\n\n // PostgreSQL doesn't need explicit identity insert mode\n // We use OVERRIDING SYSTEM VALUE in the INSERT statement\n return null;\n\n },\n\n getDisableIdentityInsertSql(_table: string): string | null {\n\n return null;\n\n },\n\n getResetSequenceSql(table: string, column: string, schema?: string): string | null {\n\n const fullTable = schema ? `${quoteIdent(schema)}.${quoteIdent(table)}` : quoteIdent(table);\n\n // setval to MAX + 1 (or 1 if table is empty)\n return `\n SELECT setval(\n pg_get_serial_sequence('${schema ? schema + '.' : ''}${table}', '${column}'),\n COALESCE((SELECT MAX(${quoteIdent(column)}) FROM ${fullTable}), 0) + 1,\n false\n )\n `.trim();\n\n },\n\n buildConflictInsert(\n table: string,\n columns: string[],\n primaryKey: string[],\n strategy: ConflictStrategy,\n ): string {\n\n const quotedCols = columns.map(quoteIdent).join(', ');\n const placeholders = columns.map((_, i) => `$${i + 1}`).join(', ');\n const pkCols = primaryKey.map(quoteIdent).join(', ');\n\n // Base INSERT with OVERRIDING SYSTEM VALUE for identity columns\n let insertSql = `INSERT INTO ${quoteIdent(table)} (${quotedCols}) OVERRIDING SYSTEM VALUE VALUES (${placeholders})`;\n\n switch (strategy) {\n\n case 'fail':\n // No conflict clause - will error on duplicate\n break;\n\n case 'skip':\n insertSql += ` ON CONFLICT (${pkCols}) DO NOTHING`;\n break;\n\n case 'update': {\n\n // Update all non-PK columns\n const updateCols = columns.filter((c) => !primaryKey.includes(c));\n\n if (updateCols.length > 0) {\n\n const setClauses = updateCols\n .map((c) => `${quoteIdent(c)} = EXCLUDED.${quoteIdent(c)}`)\n .join(', ');\n insertSql += ` ON CONFLICT (${pkCols}) DO UPDATE SET ${setClauses}`;\n\n }\n else {\n\n // All columns are PK, nothing to update\n insertSql += ` ON CONFLICT (${pkCols}) DO NOTHING`;\n\n }\n\n break;\n\n }\n\n case 'replace':\n // PostgreSQL doesn't have REPLACE, use upsert with all columns\n {\n\n const setClauses = columns\n .map((c) => `${quoteIdent(c)} = EXCLUDED.${quoteIdent(c)}`)\n .join(', ');\n insertSql += ` ON CONFLICT (${pkCols}) DO UPDATE SET ${setClauses}`;\n\n }\n break;\n\n }\n\n return insertSql;\n\n },\n\n buildDirectTransfer(\n srcDb: string,\n srcTable: string,\n dstTable: string,\n columns: string[],\n srcSchema = 'public',\n dstSchema = 'public',\n ): string {\n\n const quotedCols = columns.map(quoteIdent).join(', ');\n\n // PostgreSQL uses dblink or postgres_fdw for cross-database\n // For same-server, we use the database name in the connection\n // This assumes we're connected to the destination and source is accessible\n // In practice, Kysely doesn't support cross-database queries directly\n // So we use a simpler approach: assume same database, different schemas not applicable\n const srcFull = `${quoteIdent(srcSchema)}.${quoteIdent(srcTable)}`;\n const dstFull = `${quoteIdent(dstSchema)}.${quoteIdent(dstTable)}`;\n\n return `INSERT INTO ${dstFull} (${quotedCols}) OVERRIDING SYSTEM VALUE SELECT ${quotedCols} FROM ${srcFull}`;\n\n },\n\n async executeDisableFK(db: Kysely<NoormDatabase>): Promise<void> {\n\n await sql.raw(this.getDisableFKSql()).execute(db);\n\n },\n\n async executeEnableFK(db: Kysely<NoormDatabase>): Promise<void> {\n\n await sql.raw(this.getEnableFKSql()).execute(db);\n\n },\n\n};\n","/**\n * MySQL transfer operations.\n *\n * Uses FOREIGN_KEY_CHECKS for FK bypass, explicit IDs work automatically,\n * and INSERT IGNORE / ON DUPLICATE KEY for conflict handling.\n */\nimport { sql } from 'kysely';\n\nimport type { Kysely } from 'kysely';\nimport type { NoormDatabase } from '../../shared/tables.js';\nimport type { TransferDialectOperations } from './types.js';\nimport type { ConflictStrategy } from '../types.js';\n\n/**\n * Quote an identifier for MySQL using backticks.\n */\nfunction quoteIdent(name: string): string {\n\n return `\\`${name.replace(/`/g, '``')}\\``;\n\n}\n\n/**\n * MySQL-specific transfer operations.\n */\nexport const mysqlTransferOperations: TransferDialectOperations = {\n\n getDisableFKSql(): string {\n\n return 'SET FOREIGN_KEY_CHECKS = 0';\n\n },\n\n getEnableFKSql(): string {\n\n return 'SET FOREIGN_KEY_CHECKS = 1';\n\n },\n\n getEnableIdentityInsertSql(_table: string): string | null {\n\n // MySQL allows inserting explicit IDs without special mode\n return null;\n\n },\n\n getDisableIdentityInsertSql(_table: string): string | null {\n\n return null;\n\n },\n\n getResetSequenceSql(table: string, _column: string, _schema?: string): string | null {\n\n // Reset AUTO_INCREMENT to 1, MySQL will adjust to MAX+1 automatically\n // on next insert if table has data\n return `ALTER TABLE ${quoteIdent(table)} AUTO_INCREMENT = 1`;\n\n },\n\n buildConflictInsert(\n table: string,\n columns: string[],\n primaryKey: string[],\n strategy: ConflictStrategy,\n ): string {\n\n const quotedCols = columns.map(quoteIdent).join(', ');\n const placeholders = columns.map(() => '?').join(', ');\n\n switch (strategy) {\n\n case 'fail':\n // Standard INSERT - will error on duplicate\n return `INSERT INTO ${quoteIdent(table)} (${quotedCols}) VALUES (${placeholders})`;\n\n case 'skip':\n // INSERT IGNORE skips rows that would cause duplicate key\n return `INSERT IGNORE INTO ${quoteIdent(table)} (${quotedCols}) VALUES (${placeholders})`;\n\n case 'update': {\n\n // ON DUPLICATE KEY UPDATE for non-PK columns\n const updateCols = columns.filter((c) => !primaryKey.includes(c));\n\n if (updateCols.length > 0) {\n\n const setClauses = updateCols\n .map((c) => `${quoteIdent(c)} = VALUES(${quoteIdent(c)})`)\n .join(', ');\n\n return `INSERT INTO ${quoteIdent(table)} (${quotedCols}) VALUES (${placeholders}) ON DUPLICATE KEY UPDATE ${setClauses}`;\n\n }\n\n // All columns are PK, use INSERT IGNORE\n return `INSERT IGNORE INTO ${quoteIdent(table)} (${quotedCols}) VALUES (${placeholders})`;\n\n }\n\n case 'replace':\n // REPLACE deletes existing row and inserts new one\n return `REPLACE INTO ${quoteIdent(table)} (${quotedCols}) VALUES (${placeholders})`;\n\n }\n\n },\n\n buildDirectTransfer(\n srcDb: string,\n srcTable: string,\n dstTable: string,\n columns: string[],\n _srcSchema?: string,\n _dstSchema?: string,\n ): string {\n\n const quotedCols = columns.map(quoteIdent).join(', ');\n\n // MySQL uses database.table notation for cross-database\n const srcFull = `${quoteIdent(srcDb)}.${quoteIdent(srcTable)}`;\n const dstFull = quoteIdent(dstTable);\n\n return `INSERT INTO ${dstFull} (${quotedCols}) SELECT ${quotedCols} FROM ${srcFull}`;\n\n },\n\n async executeDisableFK(db: Kysely<NoormDatabase>): Promise<void> {\n\n await sql.raw(this.getDisableFKSql()).execute(db);\n\n },\n\n async executeEnableFK(db: Kysely<NoormDatabase>): Promise<void> {\n\n await sql.raw(this.getEnableFKSql()).execute(db);\n\n },\n\n};\n","/**\n * MSSQL transfer operations.\n *\n * Uses NOCHECK CONSTRAINT for FK bypass, SET IDENTITY_INSERT for\n * identity columns, and MERGE for conflict handling.\n */\nimport { sql } from 'kysely';\n\nimport type { Kysely } from 'kysely';\nimport type { NoormDatabase } from '../../shared/tables.js';\nimport type { TransferDialectOperations } from './types.js';\nimport type { ConflictStrategy } from '../types.js';\n\n/**\n * Quote an identifier for MSSQL using brackets.\n */\nfunction quoteIdent(name: string): string {\n\n return `[${name.replace(/\\]/g, ']]')}]`;\n\n}\n\n/**\n * MSSQL-specific transfer operations.\n */\nexport const mssqlTransferOperations: TransferDialectOperations = {\n\n getDisableFKSql(): string {\n\n // MSSQL needs per-table disable, this is a placeholder\n // Actual disable happens in executeDisableFK\n return '-- FK disable per-table';\n\n },\n\n getEnableFKSql(): string {\n\n // Placeholder - actual enable happens in executeEnableFK\n return '-- FK enable per-table';\n\n },\n\n getEnableIdentityInsertSql(table: string): string | null {\n\n return `SET IDENTITY_INSERT ${quoteIdent(table)} ON`;\n\n },\n\n getDisableIdentityInsertSql(table: string): string | null {\n\n return `SET IDENTITY_INSERT ${quoteIdent(table)} OFF`;\n\n },\n\n getResetSequenceSql(table: string, _column: string, _schema?: string): string | null {\n\n // DBCC CHECKIDENT reseeds the identity to MAX+1\n return `DBCC CHECKIDENT ('${table}', RESEED)`;\n\n },\n\n buildConflictInsert(\n table: string,\n columns: string[],\n primaryKey: string[],\n strategy: ConflictStrategy,\n ): string {\n\n const quotedCols = columns.map(quoteIdent).join(', ');\n\n // MSSQL uses @p1, @p2, etc. for parameters (Kysely handles this)\n // For raw SQL, we use positional markers that Kysely will translate\n const placeholders = columns.map((_, i) => `@p${i}`).join(', ');\n\n switch (strategy) {\n\n case 'fail':\n // Standard INSERT - will error on duplicate\n return `INSERT INTO ${quoteIdent(table)} (${quotedCols}) VALUES (${placeholders})`;\n\n case 'skip':\n case 'update':\n case 'replace': {\n\n // MSSQL uses MERGE for all conflict scenarios\n const pkConditions = primaryKey\n .map((pk) => `target.${quoteIdent(pk)} = source.${quoteIdent(pk)}`)\n .join(' AND ');\n\n // Source is a VALUES clause wrapped as a derived table\n const sourceValues = columns.map((c, i) => `@p${i} AS ${quoteIdent(c)}`).join(', ');\n\n let mergeSql = `\n MERGE INTO ${quoteIdent(table)} AS target\n USING (SELECT ${sourceValues}) AS source\n ON (${pkConditions})\n `.trim();\n\n if (strategy === 'skip') {\n\n // Only insert when not matched\n mergeSql += `\n WHEN NOT MATCHED THEN\n INSERT (${quotedCols})\n VALUES (${columns.map((c) => `source.${quoteIdent(c)}`).join(', ')})\n `;\n\n }\n else if (strategy === 'update') {\n\n // Update when matched, insert when not\n const updateCols = columns.filter((c) => !primaryKey.includes(c));\n\n if (updateCols.length > 0) {\n\n const setClauses = updateCols\n .map((c) => `target.${quoteIdent(c)} = source.${quoteIdent(c)}`)\n .join(', ');\n\n mergeSql += `\n WHEN MATCHED THEN\n UPDATE SET ${setClauses}\n `;\n\n }\n\n mergeSql += `\n WHEN NOT MATCHED THEN\n INSERT (${quotedCols})\n VALUES (${columns.map((c) => `source.${quoteIdent(c)}`).join(', ')})\n `;\n\n }\n else {\n\n // replace: update all columns when matched\n const setClauses = columns\n .map((c) => `target.${quoteIdent(c)} = source.${quoteIdent(c)}`)\n .join(', ');\n\n mergeSql += `\n WHEN MATCHED THEN\n UPDATE SET ${setClauses}\n WHEN NOT MATCHED THEN\n INSERT (${quotedCols})\n VALUES (${columns.map((c) => `source.${quoteIdent(c)}`).join(', ')})\n `;\n\n }\n\n mergeSql += ';';\n\n return mergeSql.trim();\n\n }\n\n }\n\n },\n\n buildDirectTransfer(\n srcDb: string,\n srcTable: string,\n dstTable: string,\n columns: string[],\n srcSchema = 'dbo',\n dstSchema = 'dbo',\n ): string {\n\n const quotedCols = columns.map(quoteIdent).join(', ');\n\n // MSSQL uses four-part naming: [server].[database].[schema].[table]\n // For same-server, we can use [database].[schema].[table]\n const srcFull = `${quoteIdent(srcDb)}.${quoteIdent(srcSchema)}.${quoteIdent(srcTable)}`;\n const dstFull = `${quoteIdent(dstSchema)}.${quoteIdent(dstTable)}`;\n\n return `INSERT INTO ${dstFull} (${quotedCols}) SELECT ${quotedCols} FROM ${srcFull}`;\n\n },\n\n async executeDisableFK(db: Kysely<NoormDatabase>, tables: string[]): Promise<void> {\n\n // MSSQL requires per-table constraint disable\n for (const table of tables) {\n\n await sql.raw(`ALTER TABLE ${quoteIdent(table)} NOCHECK CONSTRAINT ALL`).execute(db);\n\n }\n\n },\n\n async executeEnableFK(db: Kysely<NoormDatabase>, tables: string[]): Promise<void> {\n\n // Re-enable with CHECK CHECK to validate existing data\n for (const table of tables) {\n\n await sql.raw(`ALTER TABLE ${quoteIdent(table)} WITH CHECK CHECK CONSTRAINT ALL`).execute(db);\n\n }\n\n },\n\n};\n","/**\n * Dialect factory for transfer operations.\n *\n * Returns the appropriate transfer operations implementation\n * based on the database dialect.\n */\nimport type { Dialect } from '../../connection/types.js';\nimport type { TransferDialectOperations } from './types.js';\n\nimport { postgresTransferOperations } from './postgres.js';\nimport { mysqlTransferOperations } from './mysql.js';\nimport { mssqlTransferOperations } from './mssql.js';\n\n/**\n * Dialect-to-operations mapping.\n *\n * Note: SQLite is not supported for data transfer operations.\n */\nconst dialectOperations: Partial<Record<Dialect, TransferDialectOperations>> = {\n postgres: postgresTransferOperations,\n mysql: mysqlTransferOperations,\n mssql: mssqlTransferOperations,\n};\n\n/**\n * Dialects that support data transfer.\n */\nexport const TRANSFER_SUPPORTED_DIALECTS: Dialect[] = ['postgres', 'mysql', 'mssql'];\n\n/**\n * Check if a dialect supports data transfer.\n *\n * @param dialect - Database dialect\n * @returns true if dialect is supported\n */\nexport function isTransferSupported(dialect: Dialect): boolean {\n\n return TRANSFER_SUPPORTED_DIALECTS.includes(dialect);\n\n}\n\n/**\n * Get transfer operations for a specific dialect.\n *\n * @param dialect - The database dialect\n * @returns Dialect-specific transfer operations or null if not supported\n *\n * @example\n * ```typescript\n * const ops = getTransferOperations('postgres');\n * if (ops) {\n * const disableSql = ops.getDisableFKSql();\n * }\n * ```\n */\nexport function getTransferOperations(dialect: Dialect): TransferDialectOperations | null {\n\n return dialectOperations[dialect] ?? null;\n\n}\n\nexport type { TransferDialectOperations };\nexport { postgresTransferOperations, mysqlTransferOperations, mssqlTransferOperations };\n","/**\n * PostgreSQL type mappings for the .dt universal type system.\n *\n * Maps PostgreSQL-specific data types to universal types and back.\n * PostgreSQL has the most stable type system of the three supported dialects.\n *\n * @example\n * ```typescript\n * import { POSTGRES_TO_UNIVERSAL, UNIVERSAL_TO_POSTGRES } from './postgres.js';\n * ```\n */\nimport type { UniversalType } from '../types.js';\n\n/**\n * Pattern entry for source type → universal type mapping.\n *\n * Patterns are tested in order; first match wins.\n */\nexport interface TypePattern {\n\n /** Regex to match against the source database type (case-insensitive). */\n pattern: RegExp;\n\n /** Universal type this pattern maps to. */\n universalType: UniversalType;\n\n /** Whether this is a native type (vs. workaround). */\n native: boolean;\n\n}\n\n/**\n * PostgreSQL source type → universal type mappings.\n *\n * Tested in order; first match wins. More specific patterns must come first.\n */\nexport const POSTGRES_TO_UNIVERSAL: TypePattern[] = [\n // Boolean\n { pattern: /^boolean$/i, universalType: 'bool', native: true },\n { pattern: /^bool$/i, universalType: 'bool', native: true },\n\n // Integer types\n { pattern: /^smallint$/i, universalType: 'int', native: true },\n { pattern: /^int2$/i, universalType: 'int', native: true },\n { pattern: /^integer$/i, universalType: 'int', native: true },\n { pattern: /^int$/i, universalType: 'int', native: true },\n { pattern: /^int4$/i, universalType: 'int', native: true },\n { pattern: /^serial$/i, universalType: 'int', native: true },\n { pattern: /^smallserial$/i, universalType: 'int', native: true },\n\n // Bigint\n { pattern: /^bigint$/i, universalType: 'bigint', native: true },\n { pattern: /^int8$/i, universalType: 'bigint', native: true },\n { pattern: /^bigserial$/i, universalType: 'bigint', native: true },\n\n // Float\n { pattern: /^real$/i, universalType: 'float', native: true },\n { pattern: /^float4$/i, universalType: 'float', native: true },\n { pattern: /^double precision$/i, universalType: 'float', native: true },\n { pattern: /^float8$/i, universalType: 'float', native: true },\n\n // Decimal\n { pattern: /^numeric/i, universalType: 'decimal', native: true },\n { pattern: /^decimal/i, universalType: 'decimal', native: true },\n\n // UUID\n { pattern: /^uuid$/i, universalType: 'uuid', native: true },\n\n // Date/time\n { pattern: /^timestamptz/i, universalType: 'timestamp', native: true },\n { pattern: /^timestamp/i, universalType: 'timestamp', native: true },\n { pattern: /^date$/i, universalType: 'date', native: true },\n { pattern: /^time/i, universalType: 'string', native: true },\n\n // JSON\n { pattern: /^jsonb$/i, universalType: 'json', native: true },\n { pattern: /^json$/i, universalType: 'json', native: true },\n\n // Binary\n { pattern: /^bytea$/i, universalType: 'binary', native: true },\n\n // Vector (pgvector extension)\n { pattern: /^vector/i, universalType: 'vector', native: true },\n\n // Array types (e.g., integer[], text[], etc.)\n { pattern: /\\[\\]$/i, universalType: 'array', native: true },\n { pattern: /^ARRAY$/i, universalType: 'array', native: true },\n\n // String types (catch-all for text-like types)\n { pattern: /^text$/i, universalType: 'string', native: true },\n { pattern: /^varchar/i, universalType: 'string', native: true },\n { pattern: /^character varying/i, universalType: 'string', native: true },\n { pattern: /^char/i, universalType: 'string', native: true },\n { pattern: /^character\\b/i, universalType: 'string', native: true },\n { pattern: /^citext$/i, universalType: 'string', native: true },\n { pattern: /^name$/i, universalType: 'string', native: true },\n\n // Everything else → custom\n { pattern: /.*/, universalType: 'custom', native: false },\n];\n\n/**\n * Universal type → PostgreSQL target type mappings.\n *\n * No version gating needed for PostgreSQL (stable type system).\n */\nexport const UNIVERSAL_TO_POSTGRES: Record<UniversalType, string> = {\n string: 'text',\n int: 'integer',\n bigint: 'bigint',\n float: 'double precision',\n decimal: 'numeric',\n bool: 'boolean',\n timestamp: 'timestamptz',\n date: 'date',\n uuid: 'uuid',\n json: 'jsonb',\n binary: 'bytea',\n vector: 'vector',\n array: 'text[]',\n custom: 'text',\n};\n","/**\n * MySQL type mappings for the .dt universal type system.\n *\n * Version-aware: MySQL 9.0+ introduced native VECTOR(N).\n * Earlier versions use JSON as a workaround for vectors.\n *\n * @example\n * ```typescript\n * import { MYSQL_TO_UNIVERSAL, getUniversalToMysql } from './mysql.js';\n * ```\n */\nimport type { TypePattern } from './postgres.js';\nimport type { UniversalType, DatabaseVersion } from '../types.js';\n\n/**\n * MySQL source type → universal type mappings.\n *\n * Tested in order; first match wins. More specific patterns must come first.\n */\nexport const MYSQL_TO_UNIVERSAL: TypePattern[] = [\n // Boolean (must come before generic TINYINT)\n { pattern: /^tinyint\\(1\\)$/i, universalType: 'bool', native: true },\n { pattern: /^boolean$/i, universalType: 'bool', native: true },\n { pattern: /^bool$/i, universalType: 'bool', native: true },\n\n // Integer types\n { pattern: /^tinyint/i, universalType: 'int', native: true },\n { pattern: /^smallint/i, universalType: 'int', native: true },\n { pattern: /^mediumint/i, universalType: 'int', native: true },\n { pattern: /^int\\b/i, universalType: 'int', native: true },\n { pattern: /^integer/i, universalType: 'int', native: true },\n { pattern: /^year$/i, universalType: 'int', native: true },\n\n // Bigint\n { pattern: /^bigint/i, universalType: 'bigint', native: true },\n\n // Float\n { pattern: /^float/i, universalType: 'float', native: true },\n { pattern: /^double/i, universalType: 'float', native: true },\n\n // Decimal\n { pattern: /^decimal/i, universalType: 'decimal', native: true },\n { pattern: /^numeric/i, universalType: 'decimal', native: true },\n\n // Date/time\n { pattern: /^datetime/i, universalType: 'timestamp', native: true },\n { pattern: /^timestamp/i, universalType: 'timestamp', native: true },\n { pattern: /^date$/i, universalType: 'date', native: true },\n { pattern: /^time/i, universalType: 'string', native: true },\n\n // JSON\n { pattern: /^json$/i, universalType: 'json', native: true },\n\n // Vector (MySQL 9.0+)\n { pattern: /^vector/i, universalType: 'vector', native: true },\n\n // Binary types\n { pattern: /^bit/i, universalType: 'binary', native: true },\n { pattern: /^binary/i, universalType: 'binary', native: true },\n { pattern: /^varbinary/i, universalType: 'binary', native: true },\n { pattern: /^tinyblob$/i, universalType: 'binary', native: true },\n { pattern: /^blob$/i, universalType: 'binary', native: true },\n { pattern: /^mediumblob$/i, universalType: 'binary', native: true },\n { pattern: /^longblob$/i, universalType: 'binary', native: true },\n\n // Enum/Set → custom\n { pattern: /^enum/i, universalType: 'custom', native: true },\n { pattern: /^set/i, universalType: 'custom', native: true },\n\n // String types\n { pattern: /^char/i, universalType: 'string', native: true },\n { pattern: /^varchar/i, universalType: 'string', native: true },\n { pattern: /^tinytext$/i, universalType: 'string', native: true },\n { pattern: /^text$/i, universalType: 'string', native: true },\n { pattern: /^mediumtext$/i, universalType: 'string', native: true },\n { pattern: /^longtext$/i, universalType: 'string', native: true },\n\n // Everything else → custom\n { pattern: /.*/, universalType: 'custom', native: false },\n];\n\n/**\n * Get MySQL target type for a universal type, version-aware.\n *\n * MySQL 9.0+ supports native VECTOR(N).\n * Older versions fall back to JSON for vector/array storage.\n *\n * @param universalType - The universal type to map\n * @param version - Target MySQL version (optional)\n * @returns MySQL type string\n */\nexport function getUniversalToMysql(universalType: UniversalType, version?: DatabaseVersion): string {\n\n const major = version?.major ?? 8;\n\n switch (universalType) {\n\n case 'string':\n return 'varchar(255)';\n\n case 'int':\n return 'int';\n\n case 'bigint':\n return 'bigint';\n\n case 'float':\n return 'double';\n\n case 'decimal':\n return 'decimal(38,10)';\n\n case 'bool':\n return 'tinyint(1)';\n\n case 'timestamp':\n return 'datetime(6)';\n\n case 'date':\n return 'date';\n\n case 'uuid':\n return 'char(36)';\n\n case 'json':\n return 'json';\n\n case 'binary':\n return 'longblob';\n\n case 'vector':\n // MySQL 9.0+ has native VECTOR\n return major >= 9 ? 'vector(2048)' : 'json';\n\n case 'array':\n return 'json';\n\n case 'custom':\n return 'text';\n\n default:\n return 'text';\n\n }\n\n}\n","/**\n * MSSQL type mappings for the .dt universal type system.\n *\n * Version-aware: SQL Server 2025 introduced native JSON and VECTOR types.\n * Earlier versions use NVARCHAR(MAX) as a workaround.\n *\n * @example\n * ```typescript\n * import { MSSQL_TO_UNIVERSAL, getUniversalToMssql } from './mssql.js';\n * ```\n */\nimport type { TypePattern } from './postgres.js';\nimport type { UniversalType, DatabaseVersion } from '../types.js';\n\n/**\n * MSSQL source type → universal type mappings.\n *\n * Tested in order; first match wins.\n */\nexport const MSSQL_TO_UNIVERSAL: TypePattern[] = [\n // Boolean\n { pattern: /^bit$/i, universalType: 'bool', native: true },\n\n // Integer types\n { pattern: /^tinyint$/i, universalType: 'int', native: true },\n { pattern: /^smallint$/i, universalType: 'int', native: true },\n { pattern: /^int$/i, universalType: 'int', native: true },\n\n // Bigint\n { pattern: /^bigint$/i, universalType: 'bigint', native: true },\n\n // Float\n { pattern: /^float/i, universalType: 'float', native: true },\n { pattern: /^real$/i, universalType: 'float', native: true },\n\n // Decimal\n { pattern: /^decimal/i, universalType: 'decimal', native: true },\n { pattern: /^numeric/i, universalType: 'decimal', native: true },\n { pattern: /^money$/i, universalType: 'decimal', native: true },\n { pattern: /^smallmoney$/i, universalType: 'decimal', native: true },\n\n // UUID\n { pattern: /^uniqueidentifier$/i, universalType: 'uuid', native: true },\n\n // Date/time\n { pattern: /^datetime2/i, universalType: 'timestamp', native: true },\n { pattern: /^datetimeoffset/i, universalType: 'timestamp', native: true },\n { pattern: /^datetime$/i, universalType: 'timestamp', native: true },\n { pattern: /^smalldatetime$/i, universalType: 'timestamp', native: true },\n { pattern: /^date$/i, universalType: 'date', native: true },\n { pattern: /^time/i, universalType: 'string', native: true },\n\n // Native JSON (SQL Server 2025+)\n { pattern: /^json$/i, universalType: 'json', native: true },\n\n // Native VECTOR (SQL Server 2025+)\n { pattern: /^vector/i, universalType: 'vector', native: true },\n\n // Binary types\n { pattern: /^binary/i, universalType: 'binary', native: true },\n { pattern: /^varbinary/i, universalType: 'binary', native: true },\n { pattern: /^image$/i, universalType: 'binary', native: true },\n { pattern: /^rowversion$/i, universalType: 'binary', native: true },\n { pattern: /^timestamp$/i, universalType: 'binary', native: true },\n\n // XML → custom\n { pattern: /^xml$/i, universalType: 'custom', native: true },\n { pattern: /^sql_variant$/i, universalType: 'custom', native: true },\n { pattern: /^hierarchyid$/i, universalType: 'custom', native: true },\n\n // String types\n { pattern: /^nvarchar\\(max\\)$/i, universalType: 'string', native: true },\n { pattern: /^varchar\\(max\\)$/i, universalType: 'string', native: true },\n { pattern: /^nvarchar/i, universalType: 'string', native: true },\n { pattern: /^varchar/i, universalType: 'string', native: true },\n { pattern: /^nchar/i, universalType: 'string', native: true },\n { pattern: /^char/i, universalType: 'string', native: true },\n { pattern: /^ntext$/i, universalType: 'string', native: true },\n { pattern: /^text$/i, universalType: 'string', native: true },\n\n // Everything else → custom\n { pattern: /.*/, universalType: 'custom', native: false },\n];\n\n/**\n * Get MSSQL target type for a universal type, version-aware.\n *\n * SQL Server 2025+ supports native JSON and VECTOR types.\n * Earlier versions use NVARCHAR(MAX) as workaround.\n *\n * @param universalType - The universal type to map\n * @param version - Target MSSQL version (optional)\n * @returns MSSQL type string\n */\nexport function getUniversalToMssql(universalType: UniversalType, version?: DatabaseVersion): string {\n\n const major = version?.major ?? 2022;\n\n switch (universalType) {\n\n case 'string':\n return 'nvarchar(255)';\n\n case 'int':\n return 'int';\n\n case 'bigint':\n return 'bigint';\n\n case 'float':\n return 'float';\n\n case 'decimal':\n return 'decimal(38,10)';\n\n case 'bool':\n return 'bit';\n\n case 'timestamp':\n return 'datetime2(7)';\n\n case 'date':\n return 'date';\n\n case 'uuid':\n return 'uniqueidentifier';\n\n case 'json':\n // SQL Server 2025+ has native JSON\n return major >= 2025 ? 'json' : 'nvarchar(max)';\n\n case 'binary':\n return 'varbinary(max)';\n\n case 'vector':\n // SQL Server 2025+ has native VECTOR\n return major >= 2025 ? 'vector(1998)' : 'nvarchar(max)';\n\n case 'array':\n return 'nvarchar(max)';\n\n case 'custom':\n return 'nvarchar(max)';\n\n default:\n return 'nvarchar(max)';\n\n }\n\n}\n","/**\n * Dialect registry for .dt type mappings.\n *\n * Routes type mapping operations to the correct dialect implementation.\n *\n * @example\n * ```typescript\n * import { getDialectPatterns, getDialectTargetType } from './dialects/index.js';\n *\n * const patterns = getDialectPatterns('postgres');\n * const targetType = getDialectTargetType('json', 'mssql', version);\n * ```\n */\nimport type { Dialect } from '../../connection/types.js';\nimport type { UniversalType, DatabaseVersion } from '../types.js';\nimport type { TypePattern } from './postgres.js';\n\nimport { POSTGRES_TO_UNIVERSAL, UNIVERSAL_TO_POSTGRES } from './postgres.js';\nimport { MYSQL_TO_UNIVERSAL, getUniversalToMysql } from './mysql.js';\nimport { MSSQL_TO_UNIVERSAL, getUniversalToMssql } from './mssql.js';\n\n/**\n * Get source type → universal type pattern list for a dialect.\n *\n * @param dialect - Database dialect\n * @returns Array of type patterns, or empty array for unsupported dialects\n */\nexport function getDialectPatterns(dialect: Dialect): TypePattern[] {\n\n switch (dialect) {\n\n case 'postgres':\n return POSTGRES_TO_UNIVERSAL;\n\n case 'mysql':\n return MYSQL_TO_UNIVERSAL;\n\n case 'mssql':\n return MSSQL_TO_UNIVERSAL;\n\n default:\n return [];\n\n }\n\n}\n\n/**\n * Get dialect-specific target type string for a universal type.\n *\n * Version-aware: uses database version to select optimal type mappings.\n *\n * @param universalType - Universal type to map\n * @param dialect - Target database dialect\n * @param version - Target database version (optional)\n * @returns Dialect-specific type string\n */\nexport function getDialectTargetType(\n universalType: UniversalType,\n dialect: Dialect,\n version?: DatabaseVersion,\n): string {\n\n switch (dialect) {\n\n case 'postgres':\n return UNIVERSAL_TO_POSTGRES[universalType] ?? 'text';\n\n case 'mysql':\n return getUniversalToMysql(universalType, version);\n\n case 'mssql':\n return getUniversalToMssql(universalType, version);\n\n default:\n return 'text';\n\n }\n\n}\n\n// Re-export dialect-specific modules\nexport { POSTGRES_TO_UNIVERSAL, UNIVERSAL_TO_POSTGRES } from './postgres.js';\nexport { MYSQL_TO_UNIVERSAL, getUniversalToMysql } from './mysql.js';\nexport { MSSQL_TO_UNIVERSAL, getUniversalToMssql } from './mssql.js';\nexport type { TypePattern } from './postgres.js';\n","/**\n * Universal type mapping engine.\n *\n * Two core functions that convert between database-specific types\n * and the .dt universal type system. Version-aware for optimal mappings.\n *\n * @example\n * ```typescript\n * import { toUniversalType, toDialectType } from './type-map.js';\n *\n * // Database type → universal\n * const result = toUniversalType({ dbType: 'jsonb', dialect: 'postgres' });\n * // { universalType: 'json', native: true }\n *\n * // Universal → database type\n * const dialectType = toDialectType({ universalType: 'json', dialect: 'mssql', version });\n * // 'json' (2025+) or 'nvarchar(max)' (2022-)\n * ```\n */\nimport type { Dialect } from '../connection/types.js';\nimport type { UniversalType, DatabaseVersion, TypeMappingResult } from './types.js';\nimport { ENCODED_TYPES } from './constants.js';\n\nimport { getDialectPatterns, getDialectTargetType } from './dialects/index.js';\n\n/**\n * Options for mapping a database type to a universal type.\n */\nexport interface ToUniversalOptions {\n\n /** Database-specific type string (e.g., `jsonb`, `nvarchar(max)`, `vector(1536)`). */\n dbType: string;\n\n /** Source database dialect. */\n dialect: Dialect;\n\n /** Source database version (optional, for future version-aware source mapping). */\n version?: DatabaseVersion;\n\n}\n\n/**\n * Options for mapping a universal type to a dialect-specific type.\n */\nexport interface ToDialectOptions {\n\n /** Universal type to map. */\n universalType: UniversalType;\n\n /** Target database dialect. */\n dialect: Dialect;\n\n /** Target database version for version-aware mapping. */\n version?: DatabaseVersion;\n\n}\n\n/**\n * Map a database-specific type to the .dt universal type system.\n *\n * Matches the database type against dialect-specific patterns.\n * First matching pattern wins.\n *\n * @param options - Source type and dialect info\n * @returns Universal type and whether it's natively supported\n *\n * @example\n * ```typescript\n * toUniversalType({ dbType: 'vector(1536)', dialect: 'postgres' })\n * // { universalType: 'vector', native: true }\n *\n * toUniversalType({ dbType: 'nvarchar(max)', dialect: 'mssql' })\n * // { universalType: 'string', native: true }\n * ```\n */\nexport function toUniversalType(options: ToUniversalOptions): TypeMappingResult {\n\n const { dbType, dialect } = options;\n const patterns = getDialectPatterns(dialect);\n\n for (const entry of patterns) {\n\n if (entry.pattern.test(dbType)) {\n\n return {\n universalType: entry.universalType,\n native: entry.native,\n };\n\n }\n\n }\n\n // Fallback: unknown types become custom\n return { universalType: 'custom', native: false };\n\n}\n\n/**\n * Map a universal type to a dialect-specific type string.\n *\n * Version-aware: selects optimal type based on database capabilities.\n *\n * @param options - Universal type and target dialect info\n * @returns Dialect-specific type string (e.g., `jsonb`, `nvarchar(max)`)\n *\n * @example\n * ```typescript\n * toDialectType({ universalType: 'json', dialect: 'mssql', version: { major: 2025 } })\n * // 'json'\n *\n * toDialectType({ universalType: 'json', dialect: 'mssql', version: { major: 2022 } })\n * // 'nvarchar(max)'\n * ```\n */\nexport function toDialectType(options: ToDialectOptions): string {\n\n const { universalType, dialect, version } = options;\n\n return getDialectTargetType(universalType, dialect, version);\n\n}\n\n/**\n * Check if a universal type is an encoded type (uses tuples in .dt files).\n *\n * Uses O(1) hash lookup.\n *\n * @param type - Universal type to check\n * @returns True if the type uses encoded value tuples\n *\n * @example\n * ```typescript\n * isEncodedType('json') // true\n * isEncodedType('string') // false\n * ```\n */\nexport function isEncodedType(type: UniversalType): boolean {\n\n return (ENCODED_TYPES as Record<string, boolean>)[type] === true;\n\n}\n","/**\n * Database version detection.\n *\n * Queries the database to determine its version, enabling\n * version-aware type mappings (e.g., MSSQL 2025 native JSON).\n *\n * @example\n * ```typescript\n * import { queryDatabaseVersion } from './version.js';\n *\n * const [version, err] = await queryDatabaseVersion({ db, dialect: 'postgres' });\n * // { dialect: 'postgres', major: 16, minor: 2, raw: 'PostgreSQL 16.2 on ...' }\n * ```\n */\nimport { sql } from 'kysely';\nimport { attempt } from '@logosdx/utils';\n\nimport type { Kysely } from 'kysely';\nimport type { Dialect } from '../connection/types.js';\nimport type { NoormDatabase } from '../shared/tables.js';\nimport type { DatabaseVersion } from './types.js';\n\n/**\n * Options for querying database version.\n */\nexport interface QueryVersionOptions {\n\n /** Kysely database instance. */\n db: Kysely<NoormDatabase>;\n\n /** Database dialect. */\n dialect: Dialect;\n\n}\n\n/**\n * Query the database to detect its version.\n *\n * Parses dialect-specific version strings into structured version info\n * for use in version-aware type mapping.\n *\n * @param options - Database connection and dialect\n * @returns Database version or error\n *\n * @example\n * ```typescript\n * const [version, err] = await queryDatabaseVersion({ db, dialect: 'mssql' });\n * if (!err && version) {\n * console.log(version.major); // 2025\n * }\n * ```\n */\nexport async function queryDatabaseVersion(\n options: QueryVersionOptions,\n): Promise<[DatabaseVersion | null, Error | null]> {\n\n const { db, dialect } = options;\n\n switch (dialect) {\n\n case 'postgres':\n return queryPostgresVersion(db);\n\n case 'mysql':\n return queryMysqlVersion(db);\n\n case 'mssql':\n return queryMssqlVersion(db);\n\n default:\n return [null, new Error(`Unsupported dialect for version detection: ${dialect}`)];\n\n }\n\n}\n\n/**\n * Parse PostgreSQL version from `SELECT version()`.\n *\n * Format: `\"PostgreSQL 16.2 on x86_64-pc-linux-gnu, ...\"`\n */\nasync function queryPostgresVersion(db: Kysely<NoormDatabase>): Promise<[DatabaseVersion | null, Error | null]> {\n\n const [result, err] = await attempt(() =>\n sql<{ version: string }>`SELECT version() as version`.execute(db),\n );\n\n if (err) {\n\n return [null, err];\n\n }\n\n const raw = result.rows[0]?.version ?? '';\n const match = raw.match(/PostgreSQL\\s+(\\d+)\\.(\\d+)/i);\n\n if (!match) {\n\n return [null, new Error(`Cannot parse PostgreSQL version from: ${raw}`)];\n\n }\n\n return [{\n dialect: 'postgres',\n major: parseInt(match[1]!, 10),\n minor: parseInt(match[2]!, 10),\n raw,\n }, null];\n\n}\n\n/**\n * Parse MySQL version from `SELECT version()`.\n *\n * Format: `\"8.0.35\"` or `\"9.0.1\"`\n */\nasync function queryMysqlVersion(db: Kysely<NoormDatabase>): Promise<[DatabaseVersion | null, Error | null]> {\n\n const [result, err] = await attempt(() =>\n sql<{ version: string }>`SELECT version() as version`.execute(db),\n );\n\n if (err) {\n\n return [null, err];\n\n }\n\n const raw = result.rows[0]?.version ?? '';\n const match = raw.match(/^(\\d+)\\.(\\d+)/);\n\n if (!match) {\n\n return [null, new Error(`Cannot parse MySQL version from: ${raw}`)];\n\n }\n\n return [{\n dialect: 'mysql',\n major: parseInt(match[1]!, 10),\n minor: parseInt(match[2]!, 10),\n raw,\n }, null];\n\n}\n\n/**\n * Parse MSSQL version from SERVERPROPERTY queries.\n *\n * Uses ProductMajorVersion and ProductMinorVersion server properties.\n * Maps internal version numbers to marketing years (16 → 2022, 17 → 2025).\n */\nasync function queryMssqlVersion(db: Kysely<NoormDatabase>): Promise<[DatabaseVersion | null, Error | null]> {\n\n const [result, err] = await attempt(() =>\n sql<{\n major: string;\n minor: string;\n full_version: string;\n }>`\n SELECT\n CAST(SERVERPROPERTY('ProductMajorVersion') AS VARCHAR(10)) as major,\n CAST(SERVERPROPERTY('ProductMinorVersion') AS VARCHAR(10)) as minor,\n CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(50)) as full_version\n `.execute(db),\n );\n\n if (err) {\n\n return [null, err];\n\n }\n\n const row = result.rows[0];\n\n if (!row) {\n\n return [null, new Error('No version info returned from MSSQL')];\n\n }\n\n const internalMajor = parseInt(row.major, 10);\n const internalMinor = parseInt(row.minor, 10);\n\n // Map internal version to marketing year\n const marketingYear = mssqlInternalToYear(internalMajor);\n\n return [{\n dialect: 'mssql',\n major: marketingYear,\n minor: internalMinor,\n raw: row.full_version,\n }, null];\n\n}\n\n/**\n * Map MSSQL internal major version to marketing year.\n *\n * 15 → 2019, 16 → 2022, 17 → 2025\n */\nfunction mssqlInternalToYear(internalMajor: number): number {\n\n const mapping: { [key: number]: number } = {\n 11: 2012,\n 12: 2014,\n 13: 2016,\n 14: 2017,\n 15: 2019,\n 16: 2022,\n 17: 2025,\n };\n\n return mapping[internalMajor] ?? internalMajor;\n\n}\n","/**\n * Schema builder and validator for .dt format.\n *\n * Queries database column metadata and maps to universal types.\n * Validates .dt schemas against target databases before transfer.\n *\n * @example\n * ```typescript\n * import { buildDtSchema, validateSchema } from './schema.js';\n *\n * const [schema, err] = await buildDtSchema({ db, dialect: 'postgres', tableName: 'users' });\n *\n * const validation = await validateSchema({\n * dtSchema: schema,\n * targetDb: destDb,\n * targetDialect: 'mysql',\n * });\n * ```\n */\nimport { sql } from 'kysely';\nimport { attempt } from '@logosdx/utils';\n\nimport type { Kysely } from 'kysely';\nimport type { Dialect } from '../connection/types.js';\nimport type { NoormDatabase } from '../shared/tables.js';\nimport type {\n DtSchema,\n DtColumn,\n BuildSchemaOptions,\n ValidateSchemaOptions,\n SchemaValidationResult,\n} from './types.js';\nimport { FORMAT_VERSION } from './constants.js';\nimport { toUniversalType, toDialectType } from './type-map.js';\nimport { queryDatabaseVersion } from './version.js';\n\n/**\n * Build a DtSchema from a live database table.\n *\n * Queries column metadata and maps each column's type to the universal type system.\n *\n * @param options - Database connection, dialect, and table name\n * @returns DtSchema or error\n *\n * @example\n * ```typescript\n * const [schema, err] = await buildDtSchema({\n * db: kyselyDb,\n * dialect: 'postgres',\n * tableName: 'users',\n * version: { dialect: 'postgres', major: 16, minor: 2, raw: '16.2' },\n * });\n * ```\n */\nexport async function buildDtSchema(\n options: BuildSchemaOptions,\n): Promise<[DtSchema | null, Error | null]> {\n\n const { db, dialect, tableName, schema } = options;\n const kyselyDb = db as Kysely<NoormDatabase>;\n\n // Detect version if not provided\n let version = options.version;\n\n if (!version) {\n\n const [detected] = await queryDatabaseVersion({ db: kyselyDb, dialect });\n version = detected ?? undefined;\n\n }\n\n // Query column metadata\n const [columns, err] = await queryColumns(kyselyDb, dialect, tableName, schema);\n\n if (err) {\n\n return [null, err];\n\n }\n\n // Map to DtColumn with universal types\n const dtColumns: DtColumn[] = columns.map((col) => {\n\n const mapping = toUniversalType({\n dbType: col.dataType,\n dialect,\n version,\n });\n\n const dtCol: DtColumn = {\n name: col.name,\n type: mapping.universalType,\n };\n\n // Include source type if different from universal type name\n if (col.dataType.toLowerCase() !== mapping.universalType) {\n\n dtCol.sourceType = col.dataType;\n\n }\n\n if (!col.nullable) {\n\n dtCol.nullable = false;\n\n }\n\n return dtCol;\n\n });\n\n const dtSchema: DtSchema = {\n v: FORMAT_VERSION,\n d: dialect === 'postgres' ? 'postgresql' : dialect,\n dv: version ? `${version.major}.${version.minor}` : 'unknown',\n t: tableName,\n columns: dtColumns,\n };\n\n return [dtSchema, null];\n\n}\n\n/**\n * Validate a .dt schema against a target database.\n *\n * Checks that the target table exists and all columns are compatible.\n *\n * @param options - Schema and target database info\n * @returns Validation result with errors and warnings\n */\nexport async function validateSchema(\n options: ValidateSchemaOptions,\n): Promise<[SchemaValidationResult | null, Error | null]> {\n\n const { dtSchema, targetDb, targetDialect, targetVersion } = options;\n const kyselyDb = targetDb as Kysely<NoormDatabase>;\n const tableName = dtSchema.t;\n\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!tableName) {\n\n errors.push('Schema has no table name (t field)');\n\n return [{ valid: false, errors, warnings }, null];\n\n }\n\n // Query target table columns\n const [targetColumns, queryErr] = await queryColumns(kyselyDb, targetDialect, tableName);\n\n if (queryErr) {\n\n errors.push(`Target table \"${tableName}\" not found or inaccessible: ${queryErr.message}`);\n\n return [{ valid: false, errors, warnings }, null];\n\n }\n\n if (targetColumns.length === 0) {\n\n errors.push(`Target table \"${tableName}\" has no columns or does not exist`);\n\n return [{ valid: false, errors, warnings }, null];\n\n }\n\n // Build target column lookup\n const targetByName: { [key: string]: ColumnMeta } = {};\n\n for (const col of targetColumns) {\n\n targetByName[col.name] = col;\n\n }\n\n // Validate each .dt column exists in target\n for (const dtCol of dtSchema.columns) {\n\n const targetCol = targetByName[dtCol.name];\n\n if (!targetCol) {\n\n errors.push(`Column \"${dtCol.name}\" exists in .dt but not in target table`);\n continue;\n\n }\n\n // Check type compatibility\n const targetMapping = toUniversalType({\n dbType: targetCol.dataType,\n dialect: targetDialect,\n });\n\n if (targetMapping.universalType !== dtCol.type) {\n\n // Type mismatch — check if it's a known-compatible mapping\n const targetTypeStr = toDialectType({\n universalType: dtCol.type,\n dialect: targetDialect,\n version: targetVersion,\n });\n\n warnings.push(\n `Column \"${dtCol.name}\": source type \"${dtCol.type}\" maps to \"${targetTypeStr}\" ` +\n `in target, but target column is \"${targetCol.dataType}\" (${targetMapping.universalType})`,\n );\n\n }\n\n }\n\n return [{\n valid: errors.length === 0,\n errors,\n warnings,\n }, null];\n\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Column metadata from information_schema queries.\n */\ninterface ColumnMeta {\n\n name: string;\n dataType: string;\n nullable: boolean;\n\n}\n\n/**\n * Query column metadata for a table.\n */\nasync function queryColumns(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n tableName: string,\n schema?: string,\n): Promise<[ColumnMeta[], Error | null]> {\n\n switch (dialect) {\n\n case 'postgres':\n return queryPostgresColumns(db, tableName, schema ?? 'public');\n\n case 'mysql':\n return queryMysqlColumns(db, tableName);\n\n case 'mssql':\n return queryMssqlColumns(db, tableName);\n\n default:\n return [[], new Error(`Unsupported dialect: ${dialect}`)];\n\n }\n\n}\n\n/**\n * Query PostgreSQL column metadata.\n */\nasync function queryPostgresColumns(\n db: Kysely<NoormDatabase>,\n tableName: string,\n schema: string,\n): Promise<[ColumnMeta[], Error | null]> {\n\n const [result, err] = await attempt(() =>\n sql<{\n column_name: string;\n data_type: string;\n udt_name: string;\n is_nullable: string;\n }>`\n SELECT column_name, data_type, udt_name, is_nullable\n FROM information_schema.columns\n WHERE table_schema = ${schema}\n AND table_name = ${tableName}\n ORDER BY ordinal_position\n `.execute(db),\n );\n\n if (err) {\n\n return [[], err];\n\n }\n\n return [result.rows.map((r) => ({\n name: r.column_name,\n // Use udt_name for more specific types (e.g., 'jsonb' vs 'USER-DEFINED')\n dataType: r.data_type === 'USER-DEFINED' ? r.udt_name : r.data_type,\n nullable: r.is_nullable === 'YES',\n })), null];\n\n}\n\n/**\n * Query MySQL column metadata.\n */\nasync function queryMysqlColumns(\n db: Kysely<NoormDatabase>,\n tableName: string,\n): Promise<[ColumnMeta[], Error | null]> {\n\n const [result, err] = await attempt(() =>\n sql<{\n COLUMN_NAME: string;\n DATA_TYPE: string;\n COLUMN_TYPE: string;\n IS_NULLABLE: string;\n }>`\n SELECT COLUMN_NAME, DATA_TYPE, COLUMN_TYPE, IS_NULLABLE\n FROM INFORMATION_SCHEMA.COLUMNS\n WHERE TABLE_SCHEMA = DATABASE()\n AND TABLE_NAME = ${tableName}\n ORDER BY ORDINAL_POSITION\n `.execute(db),\n );\n\n if (err) {\n\n return [[], err];\n\n }\n\n return [result.rows.map((r) => ({\n name: r.COLUMN_NAME,\n // Use COLUMN_TYPE for precision (e.g., 'tinyint(1)' for bool)\n dataType: r.COLUMN_TYPE ?? r.DATA_TYPE,\n nullable: r.IS_NULLABLE === 'YES',\n })), null];\n\n}\n\n/**\n * Query MSSQL column metadata.\n */\nasync function queryMssqlColumns(\n db: Kysely<NoormDatabase>,\n tableName: string,\n): Promise<[ColumnMeta[], Error | null]> {\n\n const [result, err] = await attempt(() =>\n sql<{\n name: string;\n type_name: string;\n is_nullable: number;\n }>`\n SELECT\n c.name,\n TYPE_NAME(c.user_type_id) as type_name,\n c.is_nullable\n FROM sys.columns c\n JOIN sys.tables t ON c.object_id = t.object_id\n WHERE t.name = ${tableName}\n ORDER BY c.column_id\n `.execute(db),\n );\n\n if (err) {\n\n return [[], err];\n\n }\n\n return [result.rows.map((r) => ({\n name: r.name,\n dataType: r.type_name,\n nullable: r.is_nullable === 1,\n })), null];\n\n}\n","/**\n * Transfer planner.\n *\n * Analyzes source database schema and builds a transfer plan\n * with tables in dependency order (respecting foreign keys).\n */\nimport { sql } from 'kysely';\nimport { attempt } from '@logosdx/utils';\n\nimport type { Kysely } from 'kysely';\nimport type { Dialect } from '../connection/types.js';\nimport type { DualConnectionContext } from '../db/dual.js';\nimport type { NoormDatabase } from '../shared/tables.js';\nimport type { TransferOptions, TransferPlan, TransferTablePlan } from './types.js';\n\nimport { observer } from '../observer.js';\nimport { isSameServer } from './same-server.js';\nimport { isTransferSupported } from './dialects/index.js';\nimport { buildDtSchema } from '../dt/schema.js';\n\n/**\n * Table metadata for planning.\n */\ninterface TableMeta {\n\n name: string;\n schema?: string;\n rowCount: number;\n hasIdentity: boolean;\n identityColumn?: string;\n primaryKey: string[];\n columns: string[];\n\n}\n\n/**\n * FK relationship for dependency graph.\n */\ninterface FKRelation {\n\n fromTable: string;\n toTable: string;\n\n}\n\n/**\n * Build transfer plan from source and destination databases.\n *\n * Analyzes schemas, builds dependency graph, and returns ordered table list.\n *\n * @param ctx - Dual connection context\n * @param options - Transfer options\n * @returns Transfer plan or error\n */\nexport async function planTransfer(\n ctx: DualConnectionContext,\n options: TransferOptions = {},\n): Promise<[TransferPlan | null, Error | null]> {\n\n observer.emit('transfer:planning', {\n source: ctx.source.config.name,\n destination: ctx.destination.config.name,\n });\n\n const { dialect } = ctx.source;\n\n // Validate dialect support\n if (!isTransferSupported(dialect)) {\n\n return [null, new Error(`Transfer not supported for dialect: ${dialect}`)];\n\n }\n\n const crossDialect = ctx.source.dialect !== ctx.destination.dialect;\n\n // Validate both dialects are supported\n if (!isTransferSupported(ctx.destination.dialect)) {\n\n return [null, new Error(`Transfer not supported for dialect: ${ctx.destination.dialect}`)];\n\n }\n\n const warnings: string[] = [];\n\n if (crossDialect) {\n\n warnings.push(`Cross-dialect transfer: ${ctx.source.dialect} → ${ctx.destination.dialect}. Type conversion will be applied.`);\n\n }\n\n // Get all user tables from source\n const [allTables, tablesErr] = await listUserTables(ctx.source.db, dialect, options);\n\n if (tablesErr) {\n\n return [null, tablesErr];\n\n }\n\n // Get FK relationships\n const [fkRelations, fkErr] = await getForeignKeyRelations(ctx.source.db, dialect);\n\n if (fkErr) {\n\n return [null, fkErr];\n\n }\n\n // Build dependency map\n const dependencyMap = buildDependencyMap(allTables, fkRelations);\n\n // Topological sort for insert order\n const [sortedNames, sortErr] = topologicalSort(allTables.map((t) => t.name), dependencyMap);\n\n if (sortErr) {\n\n // Circular dependency detected\n warnings.push(`Circular FK dependency detected: ${sortErr.message}. Using original order.`);\n\n }\n\n // Build table plans in sorted order\n const tablesByName: { [key: string]: TableMeta } = {};\n\n for (const t of allTables) {\n\n tablesByName[t.name] = t;\n\n }\n\n const orderedNames = sortErr ? allTables.map((t) => t.name) : sortedNames;\n const tablePlans: TransferTablePlan[] = [];\n\n for (const name of orderedNames) {\n\n const meta = tablesByName[name];\n\n if (!meta) continue;\n\n tablePlans.push({\n name: meta.name,\n schema: meta.schema,\n rowCount: meta.rowCount,\n hasIdentity: meta.hasIdentity,\n identityColumn: meta.identityColumn,\n primaryKey: meta.primaryKey,\n columns: meta.columns,\n dependsOn: dependencyMap.get(name) ?? [],\n });\n\n }\n\n // Check destination schema compatibility\n const [destTables, destErr] = await listUserTables(ctx.destination.db, dialect, { tables: options.tables });\n\n if (destErr) {\n\n return [null, new Error(`Failed to read destination schema: ${destErr.message}`)];\n\n }\n\n const destTableNames = new Set(destTables.map((t) => t.name));\n\n for (const plan of tablePlans) {\n\n if (!destTableNames.has(plan.name)) {\n\n warnings.push(`Table \"${plan.name}\" exists in source but not destination`);\n\n }\n\n }\n\n // For cross-dialect transfers, build column type info for each table\n if (crossDialect) {\n\n for (const tablePlan of tablePlans) {\n\n const [dtSchema] = await buildDtSchema({\n db: ctx.source.db,\n dialect: ctx.source.dialect,\n tableName: tablePlan.name,\n schema: tablePlan.schema,\n });\n\n if (dtSchema) {\n\n tablePlan.columnTypes = dtSchema.columns;\n\n }\n\n }\n\n }\n\n // Detect same-server (only meaningful for same-dialect)\n const sameServer = crossDialect\n ? false\n : isSameServer(ctx.source.config.connection, ctx.destination.config.connection);\n\n const estimatedRows = tablePlans.reduce((sum, t) => sum + t.rowCount, 0);\n\n const plan: TransferPlan = {\n tables: tablePlans,\n sameServer,\n estimatedRows,\n warnings,\n crossDialect,\n sourceDialect: ctx.source.dialect,\n destinationDialect: ctx.destination.dialect,\n };\n\n observer.emit('transfer:plan:ready', {\n sameServer,\n tableCount: tablePlans.length,\n estimatedRows,\n warnings,\n });\n\n return [plan, null];\n\n}\n\n/**\n * List user tables (excluding noorm internal tables).\n */\nasync function listUserTables(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n options: TransferOptions = {},\n): Promise<[TableMeta[], Error | null]> {\n\n const [tables, err] = await attempt(() => queryTables(db, dialect));\n\n if (err) {\n\n return [[], err];\n\n }\n\n // Filter to requested tables\n let filtered = tables.filter((t) => !t.name.startsWith('__noorm_'));\n\n if (options.tables && options.tables.length > 0) {\n\n const requested = new Set(options.tables);\n filtered = filtered.filter((t) => requested.has(t.name));\n\n }\n\n return [filtered, null];\n\n}\n\n/**\n * Query table metadata based on dialect.\n */\nasync function queryTables(db: Kysely<NoormDatabase>, dialect: Dialect): Promise<TableMeta[]> {\n\n switch (dialect) {\n\n case 'postgres':\n return queryPostgresTables(db);\n\n case 'mysql':\n return queryMysqlTables(db);\n\n case 'mssql':\n return queryMssqlTables(db);\n\n default:\n return [];\n\n }\n\n}\n\n/**\n * Query PostgreSQL table metadata.\n */\nasync function queryPostgresTables(db: Kysely<NoormDatabase>): Promise<TableMeta[]> {\n\n const result = await sql<{\n table_name: string;\n table_schema: string;\n row_estimate: string;\n column_names: string;\n identity_column: string | null;\n pk_columns: string | null;\n }>`\n SELECT\n t.table_name,\n t.table_schema,\n COALESCE(c.reltuples::bigint::text, '0') as row_estimate,\n (\n SELECT string_agg(column_name, ',' ORDER BY ordinal_position)\n FROM information_schema.columns col\n WHERE col.table_schema = t.table_schema\n AND col.table_name = t.table_name\n ) as column_names,\n (\n SELECT column_name\n FROM information_schema.columns col\n WHERE col.table_schema = t.table_schema\n AND col.table_name = t.table_name\n AND (col.column_default LIKE 'nextval%' OR col.is_identity = 'YES')\n LIMIT 1\n ) as identity_column,\n (\n SELECT string_agg(kcu.column_name, ',' ORDER BY kcu.ordinal_position)\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.constraint_type = 'PRIMARY KEY'\n AND tc.table_schema = t.table_schema\n AND tc.table_name = t.table_name\n ) as pk_columns\n FROM information_schema.tables t\n LEFT JOIN pg_class c ON c.relname = t.table_name\n LEFT JOIN pg_namespace n ON n.oid = c.relnamespace AND n.nspname = t.table_schema\n WHERE t.table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n AND t.table_type = 'BASE TABLE'\n ORDER BY t.table_schema, t.table_name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.table_name,\n schema: row.table_schema,\n rowCount: Math.max(0, parseInt(row.row_estimate, 10)),\n hasIdentity: row.identity_column !== null,\n identityColumn: row.identity_column ?? undefined,\n primaryKey: row.pk_columns ? row.pk_columns.split(',') : [],\n columns: row.column_names ? row.column_names.split(',') : [],\n }));\n\n}\n\n/**\n * Query MySQL table metadata.\n */\nasync function queryMysqlTables(db: Kysely<NoormDatabase>): Promise<TableMeta[]> {\n\n const result = await sql<{\n table_name: string;\n row_estimate: string;\n column_names: string;\n identity_column: string | null;\n pk_columns: string | null;\n }>`\n SELECT\n t.TABLE_NAME as table_name,\n t.TABLE_ROWS as row_estimate,\n (\n SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY ORDINAL_POSITION)\n FROM INFORMATION_SCHEMA.COLUMNS c\n WHERE c.TABLE_SCHEMA = t.TABLE_SCHEMA\n AND c.TABLE_NAME = t.TABLE_NAME\n ) as column_names,\n (\n SELECT COLUMN_NAME\n FROM INFORMATION_SCHEMA.COLUMNS c\n WHERE c.TABLE_SCHEMA = t.TABLE_SCHEMA\n AND c.TABLE_NAME = t.TABLE_NAME\n AND c.EXTRA LIKE '%auto_increment%'\n LIMIT 1\n ) as identity_column,\n (\n SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY ORDINAL_POSITION)\n FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu\n WHERE kcu.TABLE_SCHEMA = t.TABLE_SCHEMA\n AND kcu.TABLE_NAME = t.TABLE_NAME\n AND kcu.CONSTRAINT_NAME = 'PRIMARY'\n ) as pk_columns\n FROM INFORMATION_SCHEMA.TABLES t\n WHERE t.TABLE_SCHEMA = DATABASE()\n AND t.TABLE_TYPE = 'BASE TABLE'\n ORDER BY t.TABLE_NAME\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.table_name,\n rowCount: Math.max(0, parseInt(row.row_estimate ?? '0', 10)),\n hasIdentity: row.identity_column !== null,\n identityColumn: row.identity_column ?? undefined,\n primaryKey: row.pk_columns ? row.pk_columns.split(',') : [],\n columns: row.column_names ? row.column_names.split(',') : [],\n }));\n\n}\n\n/**\n * Query MSSQL table metadata.\n */\nasync function queryMssqlTables(db: Kysely<NoormDatabase>): Promise<TableMeta[]> {\n\n const result = await sql<{\n table_name: string;\n table_schema: string;\n row_estimate: string;\n column_names: string;\n identity_column: string | null;\n pk_columns: string | null;\n }>`\n SELECT\n t.name as table_name,\n s.name as table_schema,\n COALESCE(SUM(p.rows), 0) as row_estimate,\n (\n SELECT STRING_AGG(c.name, ',') WITHIN GROUP (ORDER BY c.column_id)\n FROM sys.columns c\n WHERE c.object_id = t.object_id\n ) as column_names,\n (\n SELECT c.name\n FROM sys.columns c\n WHERE c.object_id = t.object_id\n AND c.is_identity = 1\n ) as identity_column,\n (\n SELECT STRING_AGG(c.name, ',') WITHIN GROUP (ORDER BY ic.key_ordinal)\n FROM sys.indexes i\n JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id\n JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id\n WHERE i.object_id = t.object_id\n AND i.is_primary_key = 1\n ) as pk_columns\n FROM sys.tables t\n JOIN sys.schemas s ON t.schema_id = s.schema_id\n LEFT JOIN sys.partitions p ON t.object_id = p.object_id AND p.index_id IN (0, 1)\n WHERE t.is_ms_shipped = 0\n GROUP BY t.object_id, t.name, s.name\n ORDER BY s.name, t.name\n `.execute(db);\n\n return result.rows.map((row) => ({\n name: row.table_name,\n schema: row.table_schema,\n rowCount: Math.max(0, parseInt(row.row_estimate ?? '0', 10)),\n hasIdentity: row.identity_column !== null,\n identityColumn: row.identity_column ?? undefined,\n primaryKey: row.pk_columns ? row.pk_columns.split(',') : [],\n columns: row.column_names ? row.column_names.split(',') : [],\n }));\n\n}\n\n/**\n * Get foreign key relationships from source database.\n */\nasync function getForeignKeyRelations(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n): Promise<[FKRelation[], Error | null]> {\n\n let queryFn: () => Promise<FKRelation[]>;\n\n switch (dialect) {\n\n case 'postgres':\n queryFn = () => queryPostgresFKs(db);\n break;\n\n case 'mysql':\n queryFn = () => queryMysqlFKs(db);\n break;\n\n case 'mssql':\n queryFn = () => queryMssqlFKs(db);\n break;\n\n default:\n return [[], null];\n\n }\n\n const [relations, err] = await attempt(queryFn);\n\n if (err) {\n\n return [[], err];\n\n }\n\n return [relations, null];\n\n}\n\n/**\n * Query PostgreSQL foreign keys.\n */\nasync function queryPostgresFKs(db: Kysely<NoormDatabase>): Promise<FKRelation[]> {\n\n const result = await sql<{\n from_table: string;\n to_table: string;\n }>`\n SELECT DISTINCT\n tc.table_name as from_table,\n ccu.table_name as to_table\n FROM information_schema.table_constraints tc\n JOIN information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\n AND tc.table_schema = ccu.table_schema\n WHERE tc.constraint_type = 'FOREIGN KEY'\n AND tc.table_schema NOT IN ('pg_catalog', 'information_schema', 'pg_toast')\n `.execute(db);\n\n return result.rows.map((r) => ({\n fromTable: r.from_table,\n toTable: r.to_table,\n }));\n\n}\n\n/**\n * Query MySQL foreign keys.\n */\nasync function queryMysqlFKs(db: Kysely<NoormDatabase>): Promise<FKRelation[]> {\n\n const result = await sql<{\n from_table: string;\n to_table: string;\n }>`\n SELECT DISTINCT\n TABLE_NAME as from_table,\n REFERENCED_TABLE_NAME as to_table\n FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE\n WHERE TABLE_SCHEMA = DATABASE()\n AND REFERENCED_TABLE_NAME IS NOT NULL\n `.execute(db);\n\n return result.rows.map((r) => ({\n fromTable: r.from_table,\n toTable: r.to_table,\n }));\n\n}\n\n/**\n * Query MSSQL foreign keys.\n */\nasync function queryMssqlFKs(db: Kysely<NoormDatabase>): Promise<FKRelation[]> {\n\n const result = await sql<{\n from_table: string;\n to_table: string;\n }>`\n SELECT DISTINCT\n OBJECT_NAME(fk.parent_object_id) as from_table,\n OBJECT_NAME(fk.referenced_object_id) as to_table\n FROM sys.foreign_keys fk\n `.execute(db);\n\n return result.rows.map((r) => ({\n fromTable: r.from_table,\n toTable: r.to_table,\n }));\n\n}\n\n/**\n * Build dependency map from FK relations.\n *\n * Map key = table name, value = tables it depends on (must be inserted first)\n */\nfunction buildDependencyMap(\n tables: TableMeta[],\n relations: FKRelation[],\n): Map<string, string[]> {\n\n const tableNames = new Set(tables.map((t) => t.name));\n const deps = new Map<string, string[]>();\n\n // Initialize empty deps for all tables\n for (const name of tableNames) {\n\n deps.set(name, []);\n\n }\n\n // Add FK dependencies\n for (const rel of relations) {\n\n // Only add if both tables are in our list\n if (tableNames.has(rel.fromTable) && tableNames.has(rel.toTable)) {\n\n // fromTable depends on toTable (toTable must be inserted first)\n const current = deps.get(rel.fromTable) ?? [];\n\n if (!current.includes(rel.toTable) && rel.fromTable !== rel.toTable) {\n\n current.push(rel.toTable);\n deps.set(rel.fromTable, current);\n\n }\n\n }\n\n }\n\n return deps;\n\n}\n\n/**\n * Topological sort of tables based on dependencies.\n *\n * Returns tables in order where dependencies come before dependents.\n */\nfunction topologicalSort(\n nodes: string[],\n deps: Map<string, string[]>,\n): [string[], Error | null] {\n\n const result: string[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n function visit(node: string): Error | null {\n\n if (visited.has(node)) return null;\n\n if (visiting.has(node)) {\n\n return new Error(`Circular dependency involving \"${node}\"`);\n\n }\n\n visiting.add(node);\n\n const nodeDeps = deps.get(node) ?? [];\n\n for (const dep of nodeDeps) {\n\n const err = visit(dep);\n\n if (err) return err;\n\n }\n\n visiting.delete(node);\n visited.add(node);\n result.push(node);\n\n return null;\n\n }\n\n for (const node of nodes) {\n\n const err = visit(node);\n\n if (err) return [[], err];\n\n }\n\n return [result, null];\n\n}\n","/**\n * In-memory cross-dialect data streamer.\n *\n * Converts rows from one dialect's type system to another without\n * file I/O, JSON5 encoding, or gzip compression. Pure type conversion\n * for efficient cross-dialect DB-to-DB transfers.\n *\n * @example\n * ```typescript\n * import { DtStreamer } from './streamer.js';\n *\n * const streamer = new DtStreamer({\n * sourceDialect: 'postgres',\n * targetDialect: 'mysql',\n * columns: [\n * { name: 'id', type: 'int' },\n * { name: 'data', type: 'json' },\n * ],\n * });\n *\n * const targetRows = streamer.convertBatch(sourceRows);\n * ```\n */\nimport { gigabytes } from '@logosdx/utils';\n\nimport type { Dialect } from '../connection/types.js';\nimport type { DtColumn, DtStreamerOptions, DatabaseVersion } from './types.js';\nimport { isEncodedType } from './type-map.js';\n\n/**\n * Default soft batch row limit.\n */\nconst DEFAULT_BATCH_SIZE = 100;\n\n/**\n * Default max batch memory (1 GB).\n */\nconst DEFAULT_MAX_BATCH_BYTES = gigabytes(1);\n\n/**\n * In-memory cross-dialect data converter.\n *\n * Operates on plain objects: no serialization to strings, no encoding tuples.\n * Used by the cross-dialect executor path: fetch batch -> convertBatch -> insert.\n *\n * Soft-limit batching: flushes at batchSize OR maxBatchBytes, whichever comes first.\n * Prevents OOM on tables with large BLOB/BINARY columns.\n */\nexport class DtStreamer {\n\n #sourceDialect: Dialect;\n #sourceVersion?: DatabaseVersion;\n #targetDialect: Dialect;\n #targetVersion?: DatabaseVersion;\n #columns: DtColumn[];\n #batchSize: number;\n #maxBatchBytes: number;\n\n /**\n * Create a new DtStreamer for cross-dialect conversion.\n *\n * @param options - Source/target dialects, columns, and batch limits\n */\n constructor(options: DtStreamerOptions) {\n\n this.#sourceDialect = options.sourceDialect;\n this.#sourceVersion = options.sourceVersion;\n this.#targetDialect = options.targetDialect;\n this.#targetVersion = options.targetVersion;\n this.#columns = options.columns;\n this.#batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;\n this.#maxBatchBytes = options.maxBatchBytes ?? DEFAULT_MAX_BATCH_BYTES;\n\n }\n\n /**\n * The soft batch size limit.\n */\n get batchSize(): number {\n\n return this.#batchSize;\n\n }\n\n /**\n * Convert a batch of source-dialect rows to target-dialect rows.\n *\n * Performs in-memory type conversion without any file I/O or encoding.\n *\n * @param rows - Source database rows\n * @returns Target-dialect rows ready for insertion\n */\n convertBatch(rows: Record<string, unknown>[]): Record<string, unknown>[] {\n\n const result: Record<string, unknown>[] = [];\n\n for (const row of rows) {\n\n result.push(this.#convertRow(row));\n\n }\n\n return result;\n\n }\n\n /**\n * Check if accumulated rows should be flushed.\n *\n * Returns true when row count exceeds batchSize OR estimated memory\n * exceeds maxBatchBytes. Prevents OOM on tables with large values.\n *\n * @param rows - Currently accumulated rows\n * @returns True if the batch should be flushed\n */\n shouldFlush(rows: Record<string, unknown>[]): boolean {\n\n if (rows.length >= this.#batchSize) {\n\n return true;\n\n }\n\n // Estimate memory usage of accumulated rows\n return estimateRowsBytes(rows) >= this.#maxBatchBytes;\n\n }\n\n /**\n * Convert a single row from source to target dialect.\n */\n #convertRow(row: Record<string, unknown>): Record<string, unknown> {\n\n const result: Record<string, unknown> = {};\n\n for (const col of this.#columns) {\n\n const value = row[col.name];\n\n if (value === null || value === undefined) {\n\n result[col.name] = null;\n continue;\n\n }\n\n if (isEncodedType(col.type)) {\n\n result[col.name] = this.#convertEncodedValue(value, col.type);\n\n }\n else {\n\n result[col.name] = this.#convertSimpleValue(value, col.type);\n\n }\n\n }\n\n return result;\n\n }\n\n /**\n * Convert an encoded-type value between dialects.\n *\n * No serialization overhead: works directly with native objects.\n */\n #convertEncodedValue(value: unknown, type: string): unknown {\n\n switch (type) {\n\n case 'json':\n return this.#convertJson(value);\n\n case 'binary':\n // Binary data passes through unchanged\n return value;\n\n case 'vector':\n return this.#convertVector(value);\n\n case 'array':\n return this.#convertArray(value);\n\n case 'custom':\n // Custom types: stringify for non-native targets\n if (this.#targetDialect !== this.#sourceDialect && typeof value === 'object') {\n\n return JSON.stringify(value);\n\n }\n\n return value;\n\n default:\n return value;\n\n }\n\n }\n\n /**\n * Convert JSON between dialects.\n */\n #convertJson(value: unknown): unknown {\n\n if (this.#targetDialect === 'mssql') {\n\n const major = this.#targetVersion?.major ?? 2022;\n\n if (major < 2025) {\n\n return typeof value === 'string' ? value : JSON.stringify(value);\n\n }\n\n }\n\n // If source was MSSQL < 2025 (string), parse it for other targets\n if (this.#sourceDialect === 'mssql' && typeof value === 'string') {\n\n const major = this.#sourceVersion?.major ?? 2022;\n\n if (major < 2025) {\n\n return JSON.parse(value);\n\n }\n\n }\n\n return value;\n\n }\n\n /**\n * Convert vector between dialects.\n */\n #convertVector(value: unknown): unknown {\n\n // Parse source vector to array if it's a string\n let arr: unknown;\n\n if (typeof value === 'string') {\n\n // PostgreSQL pgvector format: '[0.1,0.2,0.3]'\n const trimmed = value.replace(/^\\[/, '').replace(/\\]$/, '');\n arr = trimmed.split(',').map(Number);\n\n }\n else {\n\n arr = value;\n\n }\n\n // Convert to target format\n if (this.#targetDialect === 'postgres') {\n\n // pgvector string format\n return Array.isArray(arr) ? `[${arr.join(',')}]` : String(value);\n\n }\n\n if (this.#targetDialect === 'mysql') {\n\n const major = this.#targetVersion?.major ?? 8;\n\n if (major >= 9) {\n\n // MySQL 9+ native VECTOR string format\n return Array.isArray(arr) ? `[${arr.join(',')}]` : String(value);\n\n }\n\n // MySQL < 9: JSON array\n return Array.isArray(arr) ? JSON.stringify(arr) : String(value);\n\n }\n\n // MSSQL: JSON array string\n return Array.isArray(arr) ? JSON.stringify(arr) : String(value);\n\n }\n\n /**\n * Convert array between dialects.\n */\n #convertArray(value: unknown): unknown {\n\n if (this.#targetDialect === 'postgres') {\n\n // Parse JSON array string back to native array for PostgreSQL\n if (typeof value === 'string') return JSON.parse(value);\n\n return value;\n\n }\n\n // MySQL/MSSQL: store as JSON string\n if (Array.isArray(value)) return JSON.stringify(value);\n\n return value;\n\n }\n\n /**\n * Convert a simple-type value between dialects.\n */\n #convertSimpleValue(value: unknown, type: string): unknown {\n\n switch (type) {\n\n case 'bool':\n // PostgreSQL uses true/false, MSSQL uses 0/1, MySQL uses 0/1\n if (this.#targetDialect === 'mssql' || this.#targetDialect === 'mysql') {\n\n if (typeof value === 'boolean') return value ? 1 : 0;\n\n }\n else if (this.#sourceDialect === 'mssql' || this.#sourceDialect === 'mysql') {\n\n if (typeof value === 'number') return value !== 0;\n\n }\n\n return value;\n\n case 'uuid':\n // All dialects accept UUID strings\n return value;\n\n default:\n return value;\n\n }\n\n }\n\n}\n\n/**\n * Rough estimate of memory consumed by an array of row objects.\n *\n * Uses JSON.stringify length as a proxy. Not precise, but good enough\n * for the soft-limit batching purpose.\n */\nfunction estimateRowsBytes(rows: Record<string, unknown>[]): number {\n\n let total = 0;\n\n for (const row of rows) {\n\n for (const key in row) {\n\n const val = row[key];\n\n if (val === null || val === undefined) {\n\n total += 8;\n\n }\n else if (Buffer.isBuffer(val)) {\n\n total += val.length;\n\n }\n else if (typeof val === 'string') {\n\n total += val.length * 2; // UTF-16 estimate\n\n }\n else if (typeof val === 'object') {\n\n total += JSON.stringify(val).length * 2;\n\n }\n else {\n\n total += 8; // number, boolean\n\n }\n\n }\n\n }\n\n return total;\n\n}\n","/**\n * Transfer executor.\n *\n * Executes data transfer based on the transfer plan.\n * Handles both same-server (direct SQL) and cross-server (batch) transfers.\n */\nimport { sql } from 'kysely';\nimport { attempt } from '@logosdx/utils';\n\nimport type { Kysely } from 'kysely';\nimport type { DualConnectionContext } from '../db/dual.js';\nimport type { NoormDatabase } from '../shared/tables.js';\nimport type { Dialect } from '../connection/types.js';\nimport type { TransferDialectOperations } from './dialects/types.js';\nimport type {\n TransferOptions,\n TransferPlan,\n TransferTablePlan,\n TransferResult,\n TransferTableResult,\n ConflictStrategy,\n} from './types.js';\n\nimport { observer } from '../observer.js';\nimport { getTransferOperations } from './dialects/index.js';\nimport { DtStreamer } from '../dt/streamer.js';\nimport { queryDatabaseVersion } from '../dt/version.js';\n\n/**\n * Default batch size for cross-server transfers.\n */\nconst DEFAULT_BATCH_SIZE = 1000;\n\n/**\n * Execute transfer based on plan.\n *\n * @param ctx - Dual connection context\n * @param plan - Transfer plan from planner\n * @param options - Transfer options\n * @returns Transfer result or error\n */\nexport async function executeTransfer(\n ctx: DualConnectionContext,\n plan: TransferPlan,\n options: TransferOptions = {},\n): Promise<[TransferResult | null, Error | null]> {\n\n const startTime = Date.now();\n const { dialect: _srcDialect } = ctx.source;\n const destDialect = ctx.destination.dialect;\n const ops = getTransferOperations(destDialect);\n\n if (!ops) {\n\n return [null, new Error(`Unsupported dialect: ${destDialect}`)];\n\n }\n\n const tableResults: TransferTableResult[] = [];\n let totalRows = 0;\n let hasFailures = false;\n\n observer.emit('transfer:starting', {\n tableCount: plan.tables.length,\n sameServer: plan.sameServer,\n });\n\n // Disable FK checks on destination\n if (options.disableForeignKeys !== false) {\n\n const [, disableErr] = await attempt(() =>\n ops.executeDisableFK(\n ctx.destination.db,\n plan.tables.map((t) => t.name),\n ),\n );\n\n if (disableErr) {\n\n return [null, new Error(`Failed to disable FK checks: ${disableErr.message}`)];\n\n }\n\n }\n\n // Transfer each table in order\n for (let i = 0; i < plan.tables.length; i++) {\n\n const tablePlan = plan.tables[i]!;\n\n observer.emit('transfer:table:before', {\n table: tablePlan.name,\n index: i,\n total: plan.tables.length,\n rowCount: tablePlan.rowCount,\n });\n\n const tableStart = Date.now();\n let result: TransferTableResult;\n const strategy = options.onConflict ?? 'fail';\n\n // Choose transfer strategy\n const useSameServer = plan.sameServer && strategy === 'fail' && !plan.crossDialect;\n const useCrossDialect = plan.crossDialect && tablePlan.columnTypes;\n\n let tableResult: TransferTableResult | null = null;\n let tableErr: Error | null = null;\n\n if (useSameServer) {\n\n [tableResult, tableErr] = await transferTableSameServer(\n ctx,\n tablePlan,\n options,\n ops,\n );\n\n }\n else if (useCrossDialect) {\n\n [tableResult, tableErr] = await transferTableCrossDialect(\n ctx,\n tablePlan,\n plan,\n options,\n );\n\n }\n else {\n\n [tableResult, tableErr] = await transferTableCrossServer(\n ctx,\n tablePlan,\n options,\n ops,\n );\n\n }\n\n if (tableErr) {\n\n result = {\n table: tablePlan.name,\n status: 'failed',\n rowsTransferred: 0,\n rowsSkipped: 0,\n durationMs: Date.now() - tableStart,\n error: tableErr.message,\n };\n hasFailures = true;\n\n }\n else {\n\n result = tableResult!;\n\n }\n\n tableResults.push(result);\n totalRows += result.rowsTransferred;\n\n observer.emit('transfer:table:after', {\n table: tablePlan.name,\n status: result.status,\n rowsTransferred: result.rowsTransferred,\n rowsSkipped: result.rowsSkipped,\n durationMs: result.durationMs,\n error: result.error,\n });\n\n }\n\n // Re-enable FK checks on destination\n if (options.disableForeignKeys !== false) {\n\n const [, enableErr] = await attempt(() =>\n ops.executeEnableFK(\n ctx.destination.db,\n plan.tables.map((t) => t.name),\n ),\n );\n\n if (enableErr) {\n\n // Log warning but don't fail the transfer\n observer.emit('error', {\n source: 'transfer',\n error: enableErr,\n context: { phase: 'enable-fk' },\n });\n\n }\n\n }\n\n const durationMs = Date.now() - startTime;\n const allSuccess = tableResults.every((r) => r.status === 'success');\n\n const result: TransferResult = {\n status: hasFailures ? (allSuccess ? 'partial' : 'failed') : 'success',\n tables: tableResults,\n totalRows,\n durationMs,\n };\n\n observer.emit('transfer:complete', {\n status: result.status,\n totalRows,\n tableCount: plan.tables.length,\n durationMs,\n });\n\n return [result, null];\n\n}\n\n/**\n * Transfer table using same-server direct SQL.\n */\nasync function transferTableSameServer(\n ctx: DualConnectionContext,\n plan: TransferTablePlan,\n options: TransferOptions,\n ops: ReturnType<typeof getTransferOperations>,\n): Promise<[TransferTableResult | null, Error | null]> {\n\n const startTime = Date.now();\n\n if (!ops) {\n\n return [null, new Error('No dialect operations')];\n\n }\n\n // Truncate if requested\n if (options.truncateFirst) {\n\n const [, truncateErr] = await truncateTable(\n ctx.destination.db,\n ctx.destination.dialect,\n plan.name,\n );\n\n if (truncateErr) {\n\n return [null, new Error(`Failed to truncate: ${truncateErr.message}`)];\n\n }\n\n }\n\n // Enable identity insert if needed\n if (options.preserveIdentity !== false && plan.hasIdentity) {\n\n const enableSql = ops.getEnableIdentityInsertSql(plan.name);\n\n if (enableSql) {\n\n const [, enableErr] = await attempt(() =>\n sql.raw(enableSql).execute(ctx.destination.db),\n );\n\n if (enableErr) {\n\n return [null, new Error(`Failed to enable identity insert: ${enableErr.message}`)];\n\n }\n\n }\n\n }\n\n // Build and execute direct transfer\n const transferSql = ops.buildDirectTransfer(\n ctx.source.config.connection.database,\n plan.name,\n plan.name,\n plan.columns,\n plan.schema,\n plan.schema,\n );\n\n const [, transferErr] = await attempt(() =>\n sql.raw(transferSql).execute(ctx.destination.db),\n );\n\n // Cleanup: disable identity insert (best effort)\n if (options.preserveIdentity !== false && plan.hasIdentity) {\n\n const disableSql = ops.getDisableIdentityInsertSql(plan.name);\n\n if (disableSql) {\n\n await attempt(() => sql.raw(disableSql).execute(ctx.destination.db));\n\n }\n\n // Reset sequence (best effort)\n if (plan.identityColumn) {\n\n const resetSql = ops.getResetSequenceSql(plan.name, plan.identityColumn, plan.schema);\n\n if (resetSql) {\n\n await attempt(() => sql.raw(resetSql).execute(ctx.destination.db));\n\n }\n\n }\n\n }\n\n if (transferErr) {\n\n return [null, new Error(`Transfer failed: ${transferErr.message}`)];\n\n }\n\n const rowsTransferred = plan.rowCount;\n\n observer.emit('transfer:table:progress', {\n table: plan.name,\n rowsTransferred,\n rowsTotal: plan.rowCount,\n rowsSkipped: 0,\n });\n\n return [{\n table: plan.name,\n status: 'success',\n rowsTransferred,\n rowsSkipped: 0,\n durationMs: Date.now() - startTime,\n }, null];\n\n}\n\n/**\n * Transfer table using cross-server batch approach.\n */\nasync function transferTableCrossServer(\n ctx: DualConnectionContext,\n plan: TransferTablePlan,\n options: TransferOptions,\n ops: ReturnType<typeof getTransferOperations>,\n): Promise<[TransferTableResult | null, Error | null]> {\n\n const startTime = Date.now();\n const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;\n const strategy = options.onConflict ?? 'fail';\n\n if (!ops) {\n\n return [null, new Error('No dialect operations')];\n\n }\n\n // Truncate if requested\n if (options.truncateFirst) {\n\n const [, truncateErr] = await truncateTable(\n ctx.destination.db,\n ctx.destination.dialect,\n plan.name,\n );\n\n if (truncateErr) {\n\n return [null, new Error(`Failed to truncate: ${truncateErr.message}`)];\n\n }\n\n }\n\n // Enable identity insert if needed\n if (options.preserveIdentity !== false && plan.hasIdentity) {\n\n const enableSql = ops.getEnableIdentityInsertSql(plan.name);\n\n if (enableSql) {\n\n const [, enableErr] = await attempt(() =>\n sql.raw(enableSql).execute(ctx.destination.db),\n );\n\n if (enableErr) {\n\n return [null, new Error(`Failed to enable identity insert: ${enableErr.message}`)];\n\n }\n\n }\n\n }\n\n let rowsTransferred = 0;\n let rowsSkipped = 0;\n let offset = 0;\n let transferError: Error | null = null;\n\n // Fetch and insert in batches\n while (true) {\n\n // Fetch batch from source\n const [rows, fetchErr] = await attempt(() =>\n fetchBatch(\n ctx.source.db,\n ctx.source.dialect,\n plan.name,\n plan.columns,\n batchSize,\n offset,\n plan.schema,\n ),\n );\n\n if (fetchErr) {\n\n transferError = new Error(`Failed to fetch batch: ${fetchErr.message}`);\n break;\n\n }\n\n if (rows.length === 0) {\n\n break;\n\n }\n\n // Insert batch to destination\n const [batchResult, insertErr] = await insertBatch(\n ctx.destination.db,\n ctx.destination.dialect,\n plan.name,\n plan.columns,\n plan.primaryKey,\n rows,\n strategy,\n ops,\n );\n\n if (insertErr) {\n\n transferError = new Error(`Failed to insert batch: ${insertErr.message}`);\n break;\n\n }\n\n rowsTransferred += batchResult.inserted;\n rowsSkipped += batchResult.skipped;\n offset += rows.length;\n\n observer.emit('transfer:table:progress', {\n table: plan.name,\n rowsTransferred,\n rowsTotal: plan.rowCount,\n rowsSkipped,\n });\n\n // Check if we got fewer rows than batch size (end of data)\n if (rows.length < batchSize) {\n\n break;\n\n }\n\n }\n\n // Cleanup: disable identity insert (best effort)\n if (options.preserveIdentity !== false && plan.hasIdentity) {\n\n const disableSql = ops.getDisableIdentityInsertSql(plan.name);\n\n if (disableSql) {\n\n await attempt(() => sql.raw(disableSql).execute(ctx.destination.db));\n\n }\n\n // Reset sequence (best effort)\n if (plan.identityColumn) {\n\n const resetSql = ops.getResetSequenceSql(plan.name, plan.identityColumn, plan.schema);\n\n if (resetSql) {\n\n await attempt(() => sql.raw(resetSql).execute(ctx.destination.db));\n\n }\n\n }\n\n }\n\n if (transferError) {\n\n return [null, transferError];\n\n }\n\n return [{\n table: plan.name,\n status: 'success',\n rowsTransferred,\n rowsSkipped,\n durationMs: Date.now() - startTime,\n }, null];\n\n}\n\n/**\n * Transfer table using cross-dialect conversion via DtStreamer.\n *\n * Fetches rows from source, converts types in memory, inserts into target.\n */\nasync function transferTableCrossDialect(\n ctx: DualConnectionContext,\n plan: TransferTablePlan,\n transferPlan: TransferPlan,\n options: TransferOptions,\n): Promise<[TransferTableResult | null, Error | null]> {\n\n const startTime = Date.now();\n const batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;\n const destOps = getTransferOperations(ctx.destination.dialect);\n\n if (!destOps || !plan.columnTypes) {\n\n return [null, new Error('Missing dialect operations or column types for cross-dialect transfer')];\n\n }\n\n // Detect database versions for version-aware type conversion\n const [srcVersion] = await queryDatabaseVersion({ db: ctx.source.db, dialect: ctx.source.dialect });\n const [dstVersion] = await queryDatabaseVersion({ db: ctx.destination.db, dialect: ctx.destination.dialect });\n\n // Create streamer for in-memory type conversion\n const streamer = new DtStreamer({\n sourceDialect: ctx.source.dialect,\n sourceVersion: srcVersion ?? undefined,\n targetDialect: ctx.destination.dialect,\n targetVersion: dstVersion ?? undefined,\n columns: plan.columnTypes,\n batchSize,\n });\n\n // Truncate if requested\n if (options.truncateFirst) {\n\n const [, truncateErr] = await truncateTable(\n ctx.destination.db,\n ctx.destination.dialect,\n plan.name,\n );\n\n if (truncateErr) {\n\n return [null, new Error(`Failed to truncate: ${truncateErr.message}`)];\n\n }\n\n }\n\n // Enable identity insert if needed\n if (options.preserveIdentity !== false && plan.hasIdentity) {\n\n const enableSql = destOps.getEnableIdentityInsertSql(plan.name);\n\n if (enableSql) {\n\n const [, enableErr] = await attempt(() =>\n sql.raw(enableSql).execute(ctx.destination.db),\n );\n\n if (enableErr) {\n\n return [null, new Error(`Failed to enable identity insert: ${enableErr.message}`)];\n\n }\n\n }\n\n }\n\n let rowsTransferred = 0;\n let rowsSkipped = 0;\n let offset = 0;\n let transferError: Error | null = null;\n\n observer.emit('dt:stream:start', {\n table: plan.name,\n sourceDialect: ctx.source.dialect,\n targetDialect: ctx.destination.dialect,\n });\n\n while (true) {\n\n // Fetch batch from source\n const [rows, fetchErr] = await attempt(() =>\n fetchBatch(\n ctx.source.db,\n ctx.source.dialect,\n plan.name,\n plan.columns,\n batchSize,\n offset,\n plan.schema,\n ),\n );\n\n if (fetchErr) {\n\n transferError = new Error(`Failed to fetch batch: ${fetchErr.message}`);\n break;\n\n }\n\n if (rows.length === 0) break;\n\n // Convert types via DtStreamer\n const convertedRows = streamer.convertBatch(rows);\n\n // Insert converted rows into destination\n for (const row of convertedRows) {\n\n const [, insertErr] = await attempt(() =>\n ctx.destination.db.insertInto(plan.name as never).values(row as never).execute(),\n );\n\n if (insertErr) {\n\n const lower = insertErr.message.toLowerCase();\n const isDuplicate = lower.includes('duplicate') || lower.includes('unique') || lower.includes('primary key');\n\n if (isDuplicate && options.onConflict === 'skip') {\n\n rowsSkipped++;\n\n }\n else if (options.onConflict !== 'fail') {\n\n rowsSkipped++;\n\n }\n else {\n\n transferError = new Error(`Failed to insert row: ${insertErr.message}`);\n break;\n\n }\n\n }\n else {\n\n rowsTransferred++;\n\n }\n\n }\n\n if (transferError) break;\n\n offset += rows.length;\n\n observer.emit('transfer:table:progress', {\n table: plan.name,\n rowsTransferred,\n rowsTotal: plan.rowCount,\n rowsSkipped,\n });\n\n observer.emit('dt:stream:progress', {\n table: plan.name,\n rowsConverted: rowsTransferred + rowsSkipped,\n });\n\n if (rows.length < batchSize) break;\n\n }\n\n // Cleanup: disable identity insert\n if (options.preserveIdentity !== false && plan.hasIdentity) {\n\n const disableSql = destOps.getDisableIdentityInsertSql(plan.name);\n\n if (disableSql) {\n\n await attempt(() => sql.raw(disableSql).execute(ctx.destination.db));\n\n }\n\n }\n\n const durationMs = Date.now() - startTime;\n\n observer.emit('dt:stream:complete', {\n table: plan.name,\n rowsConverted: rowsTransferred + rowsSkipped,\n durationMs,\n });\n\n if (transferError) {\n\n return [null, transferError];\n\n }\n\n return [{\n table: plan.name,\n status: 'success',\n rowsTransferred,\n rowsSkipped,\n durationMs,\n }, null];\n\n}\n\n/**\n * Fetch a batch of rows from source table.\n *\n * Uses dialect-specific syntax for column quoting and pagination.\n */\nasync function fetchBatch(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n table: string,\n columns: string[],\n limit: number,\n offset: number,\n _schema?: string,\n): Promise<Record<string, unknown>[]> {\n\n // Quote column names based on dialect\n const quoteIdent = dialect === 'mssql'\n ? (c: string) => `[${c}]`\n : dialect === 'mysql'\n ? (c: string) => `\\`${c}\\``\n : (c: string) => `\"${c}\"`;\n\n const columnList = columns.map(quoteIdent).join(', ');\n\n // MSSQL uses different pagination syntax\n if (dialect === 'mssql') {\n\n // MSSQL requires ORDER BY for OFFSET/FETCH\n // Use first column as default order (usually PK)\n const orderCol = quoteIdent(columns[0]!);\n const result = await sql<Record<string, unknown>>`\n SELECT ${sql.raw(columnList)}\n FROM ${sql.table(table)}\n ORDER BY ${sql.raw(orderCol)}\n OFFSET ${offset} ROWS\n FETCH NEXT ${limit} ROWS ONLY\n `.execute(db);\n\n return result.rows;\n\n }\n\n // PostgreSQL and MySQL use LIMIT/OFFSET\n const result = await sql<Record<string, unknown>>`\n SELECT ${sql.raw(columnList)}\n FROM ${sql.table(table)}\n LIMIT ${limit}\n OFFSET ${offset}\n `.execute(db);\n\n return result.rows;\n\n}\n\n/**\n * Batch insert result.\n */\ninterface BatchInsertResult {\n\n inserted: number;\n skipped: number;\n\n}\n\n/**\n * Insert a batch of rows to destination table.\n *\n * Uses dialect-specific SQL for MSSQL MERGE statements.\n * Falls back to Kysely's onConflict for PostgreSQL and MySQL.\n *\n * Returns inserted/skipped counts or error.\n */\nasync function insertBatch(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n table: string,\n columns: string[],\n primaryKey: string[],\n rows: Record<string, unknown>[],\n strategy: ConflictStrategy,\n ops: TransferDialectOperations | undefined,\n): Promise<[BatchInsertResult, Error | null]> {\n\n if (rows.length === 0) {\n\n return [{ inserted: 0, skipped: 0 }, null];\n\n }\n\n // MSSQL requires MERGE and MySQL requires INSERT IGNORE / ON DUPLICATE KEY\n // Use dialect-specific raw SQL for conflict handling on non-PostgreSQL dialects\n if ((dialect === 'mssql' || dialect === 'mysql') && strategy !== 'fail' && primaryKey.length > 0 && ops) {\n\n return insertBatchRawSql(db, dialect, table, columns, primaryKey, rows, strategy, ops);\n\n }\n\n let inserted = 0;\n let skipped = 0;\n\n // Insert row by row\n for (const row of rows) {\n\n const query = db\n .insertInto(table as never)\n .values(row as never);\n\n // Handle conflict based on strategy\n if (strategy === 'skip' && primaryKey.length > 0) {\n\n const [, err] = await attempt(() =>\n query\n .onConflict((oc) => oc.columns(primaryKey as never[]).doNothing())\n .execute(),\n );\n\n if (err) {\n\n if (isDuplicateKeyError(err.message)) {\n\n skipped++;\n\n }\n else {\n\n return [{ inserted, skipped }, err];\n\n }\n\n }\n else {\n\n inserted++;\n\n }\n\n }\n else if (strategy === 'update' && primaryKey.length > 0) {\n\n const updateSet: Record<string, unknown> = {};\n\n for (const col of columns) {\n\n if (!primaryKey.includes(col)) {\n\n updateSet[col] = row[col];\n\n }\n\n }\n\n const [, err] = await attempt(() =>\n query\n .onConflict((oc) => oc.columns(primaryKey as never[]).doUpdateSet(updateSet as never))\n .execute(),\n );\n\n if (err) {\n\n if (isDuplicateKeyError(err.message)) {\n\n skipped++;\n\n }\n else {\n\n return [{ inserted, skipped }, err];\n\n }\n\n }\n else {\n\n inserted++;\n\n }\n\n }\n else {\n\n // Standard insert (fail on conflict) or replace\n const [, err] = await attempt(() => query.execute());\n\n if (err) {\n\n if (strategy === 'fail') {\n\n return [{ inserted, skipped }, err];\n\n }\n\n // For replace strategy, skip on error\n skipped++;\n\n }\n else {\n\n inserted++;\n\n }\n\n }\n\n }\n\n return [{ inserted, skipped }, null];\n\n}\n\n/**\n * Insert batch using dialect-specific raw SQL.\n *\n * MSSQL uses MERGE statements, MySQL uses INSERT IGNORE / ON DUPLICATE KEY.\n * Handles both @p{n} (MSSQL) and ? (MySQL) parameter placeholders.\n */\nasync function insertBatchRawSql(\n db: Kysely<NoormDatabase>,\n dialect: Dialect,\n table: string,\n columns: string[],\n primaryKey: string[],\n rows: Record<string, unknown>[],\n strategy: ConflictStrategy,\n ops: TransferDialectOperations,\n): Promise<[BatchInsertResult, Error | null]> {\n\n let inserted = 0;\n let skipped = 0;\n\n // Build the SQL template once\n const sqlTemplate = ops.buildConflictInsert(table, columns, primaryKey, strategy);\n\n for (const row of rows) {\n\n // Build parameter values in column order\n const values = columns.map((col) => row[col]);\n\n const sqlParts: string[] = [];\n const sqlValues: unknown[] = [];\n\n if (dialect === 'mssql') {\n\n // MSSQL uses @p0, @p1, etc. — split by named parameter markers\n let match: RegExpExecArray | null;\n const paramRegex = /@p(\\d+)/g;\n let lastIndex = 0;\n\n paramRegex.lastIndex = 0;\n\n while ((match = paramRegex.exec(sqlTemplate)) !== null) {\n\n sqlParts.push(sqlTemplate.slice(lastIndex, match.index));\n sqlValues.push(values[parseInt(match[1]!, 10)]);\n lastIndex = match.index + match[0].length;\n\n }\n\n sqlParts.push(sqlTemplate.slice(lastIndex));\n\n }\n else {\n\n // MySQL uses ? positional placeholders\n const parts = sqlTemplate.split('?');\n let paramIdx = 0;\n\n for (let i = 0; i < parts.length; i++) {\n\n sqlParts.push(parts[i]!);\n\n if (i < parts.length - 1) {\n\n sqlValues.push(values[paramIdx++]);\n\n }\n\n }\n\n }\n\n // Build parameterized SQL using Kysely's sql function\n const finalSql = sql.join(\n sqlParts.map((part, i) => {\n\n if (i < sqlValues.length) {\n\n return sql`${sql.raw(part)}${sql.val(sqlValues[i])}`;\n\n }\n\n return sql.raw(part);\n\n }),\n sql.raw(''),\n );\n\n const [, err] = await attempt(() => finalSql.execute(db));\n\n if (err) {\n\n if (isDuplicateKeyError(err.message)) {\n\n skipped++;\n\n }\n else {\n\n return [{ inserted, skipped }, err];\n\n }\n\n }\n else {\n\n inserted++;\n\n }\n\n }\n\n return [{ inserted, skipped }, null];\n\n}\n\n/**\n * Check if an error message indicates a duplicate key violation.\n */\nfunction isDuplicateKeyError(message: string): boolean {\n\n const lower = message.toLowerCase();\n\n return (\n lower.includes('duplicate') ||\n lower.includes('unique constraint') ||\n lower.includes('primary key') ||\n lower.includes('violates unique') ||\n lower.includes('cannot insert duplicate') ||\n lower.includes('duplicate entry')\n );\n\n}\n\n/**\n * Truncate a table with dialect-specific handling.\n *\n * PostgreSQL requires CASCADE for FK relationships.\n * MSSQL doesn't support TRUNCATE with FK constraints - use DELETE instead.\n */\nasync function truncateTable(\n db: Kysely<NoormDatabase>,\n dialect: string,\n table: string,\n): Promise<[void, Error | null]> {\n\n let truncateSql: string;\n\n switch (dialect) {\n\n case 'postgres':\n // PostgreSQL needs CASCADE for FK relationships\n truncateSql = `TRUNCATE TABLE \"${table}\" CASCADE`;\n break;\n\n case 'mssql':\n // MSSQL can't TRUNCATE with FK constraints, use DELETE\n truncateSql = `DELETE FROM [${table}]`;\n break;\n\n case 'mysql':\n truncateSql = `TRUNCATE TABLE \\`${table}\\``;\n break;\n\n default:\n truncateSql = `TRUNCATE TABLE ${table}`;\n\n }\n\n const [, err] = await attempt(() => sql.raw(truncateSql).execute(db));\n\n return [undefined, err];\n\n}\n","/**\n * Data transfer module.\n *\n * Provides cross-database data transfer functionality with:\n * - Same-server optimization (direct SQL)\n * - Cross-server batch transfers\n * - Configurable conflict resolution\n * - FK ordering with dependency analysis\n * - Identity column preservation\n *\n * @example\n * ```typescript\n * const [result, err] = await transferData(sourceConfig, destConfig, {\n * tables: ['users', 'posts'],\n * onConflict: 'skip',\n * batchSize: 5000,\n * });\n *\n * if (err) {\n * console.error('Transfer failed:', err.message);\n * } else {\n * console.log(`Transferred ${result.totalRows} rows`);\n * }\n * ```\n */\nimport { withDualConnection } from '../db/dual.js';\nimport type { Config } from '../config/types.js';\nimport type { TransferOptions, TransferResult, TransferPlan } from './types.js';\n\nimport { planTransfer } from './planner.js';\nimport { executeTransfer } from './executor.js';\nimport { isTransferSupported, TRANSFER_SUPPORTED_DIALECTS } from './dialects/index.js';\n\n/**\n * Transfer data between two database configurations.\n *\n * Both databases must use the same dialect (PostgreSQL, MySQL, or MSSQL).\n * Tables are transferred in FK dependency order.\n *\n * @param sourceConfig - Source database config\n * @param destConfig - Destination database config\n * @param options - Transfer options\n * @returns Transfer result or error\n *\n * @example\n * ```typescript\n * // Transfer all tables\n * const [result, err] = await transferData(staging, production);\n *\n * // Transfer specific tables with options\n * const [result, err] = await transferData(staging, production, {\n * tables: ['users', 'posts', 'comments'],\n * onConflict: 'update',\n * batchSize: 2000,\n * truncateFirst: true,\n * });\n *\n * // Dry run to see the plan\n * const [result, err] = await transferData(staging, production, {\n * dryRun: true,\n * });\n * console.log(result.plan.tables); // Shows table order\n * ```\n */\nexport async function transferData(\n sourceConfig: Config,\n destConfig: Config,\n options: TransferOptions = {},\n): Promise<[TransferResult | null, Error | null]> {\n\n // Validate dialects are supported\n const srcDialect = sourceConfig.connection.dialect;\n const dstDialect = destConfig.connection.dialect;\n\n if (!isTransferSupported(srcDialect)) {\n\n return [null, new Error(`Transfer not supported for dialect: ${srcDialect}. Supported: ${TRANSFER_SUPPORTED_DIALECTS.join(', ')}`)];\n\n }\n\n if (!isTransferSupported(dstDialect)) {\n\n return [null, new Error(`Transfer not supported for dialect: ${dstDialect}. Supported: ${TRANSFER_SUPPORTED_DIALECTS.join(', ')}`)];\n\n }\n\n // Use dual connection infrastructure\n return withDualConnection(\n {\n sourceConfig,\n destConfig,\n ensureSchema: false, // Don't create noorm tables on destination\n },\n async (ctx) => {\n\n // Plan the transfer\n const [plan, planErr] = await planTransfer(ctx, options);\n\n if (planErr) {\n\n throw planErr;\n\n }\n\n if (!plan || plan.tables.length === 0) {\n\n return {\n status: 'success',\n tables: [],\n totalRows: 0,\n durationMs: 0,\n };\n\n }\n\n // Dry run - return plan info\n if (options.dryRun) {\n\n return {\n status: 'success',\n tables: plan.tables.map((t) => ({\n table: t.name,\n status: 'skipped' as const,\n rowsTransferred: 0,\n rowsSkipped: 0,\n durationMs: 0,\n })),\n totalRows: 0,\n durationMs: 0,\n };\n\n }\n\n // Execute the transfer\n const [result, execErr] = await executeTransfer(ctx, plan, options);\n\n if (execErr) {\n\n throw execErr;\n\n }\n\n return result!;\n\n },\n );\n\n}\n\n/**\n * Get transfer plan without executing.\n *\n * Useful for previewing what will be transferred.\n *\n * @param sourceConfig - Source database config\n * @param destConfig - Destination database config\n * @param options - Transfer options\n * @returns Transfer plan or error\n */\nexport async function getTransferPlan(\n sourceConfig: Config,\n destConfig: Config,\n options: TransferOptions = {},\n): Promise<[TransferPlan | null, Error | null]> {\n\n // Validate dialects are supported\n const srcDialect = sourceConfig.connection.dialect;\n const dstDialect = destConfig.connection.dialect;\n\n if (!isTransferSupported(srcDialect)) {\n\n return [null, new Error(`Transfer not supported for dialect: ${srcDialect}`)];\n\n }\n\n if (!isTransferSupported(dstDialect)) {\n\n return [null, new Error(`Transfer not supported for dialect: ${dstDialect}`)];\n\n }\n\n return withDualConnection(\n {\n sourceConfig,\n destConfig,\n ensureSchema: false,\n },\n async (ctx) => {\n\n const [plan, err] = await planTransfer(ctx, options);\n\n if (err) {\n\n throw err;\n\n }\n\n return plan!;\n\n },\n );\n\n}\n\n// Re-export types\nexport type {\n TransferOptions,\n TransferPlan,\n TransferTablePlan,\n TransferResult,\n TransferTableResult,\n ConflictStrategy,\n} from './types.js';\n\nexport type { TransferEvents } from './events.js';\n\n// Re-export utilities\nexport { isSameServer } from './same-server.js';\nexport { isTransferSupported, TRANSFER_SUPPORTED_DIALECTS } from './dialects/index.js';\n","/**\n * Streaming .dt file writer.\n *\n * Writes .dt files in JSON5 format with extension-based output handling:\n * - `.dt`: raw text\n * - `.dtz`: gzip-compressed stream\n * - `.dtzx`: gzip buffer then encrypt with passphrase\n *\n * @example\n * ```typescript\n * import { DtWriter } from './writer.js';\n *\n * const writer = new DtWriter({\n * filepath: './data/users.dtz',\n * schema: { v: 1, d: 'postgresql', dv: '16.2', t: 'users', columns: [...] },\n * });\n *\n * await writer.open();\n * await writer.writeRows(serializedRows);\n * await writer.close();\n * ```\n */\nimport { createWriteStream, writeFileSync } from 'node:fs';\nimport { createGzip } from 'node:zlib';\nimport { pipeline } from 'node:stream/promises';\nimport { PassThrough } from 'node:stream';\nimport path from 'node:path';\nimport JSON5 from 'json5';\n\nimport type { Writable } from 'node:stream';\nimport type { DtSchema, DtValue, DtWriterOptions } from './types.js';\nimport { DT_EXTENSIONS } from './constants.js';\nimport { encryptWithPassphrase } from './crypto.js';\n\n/**\n * Streaming .dt file writer.\n *\n * Handles raw, compressed, and encrypted output based on file extension.\n * Tracks bytes written for progress reporting.\n */\nexport class DtWriter {\n\n #filepath: string;\n #schema: DtSchema;\n #passphrase?: string;\n #extension: string;\n #stream: Writable | null = null;\n #passthrough: PassThrough | null = null;\n #pipelinePromise: Promise<void> | null = null;\n #bytesWritten = 0;\n #rowsWritten = 0;\n #buffer: Buffer[] | null = null;\n\n /**\n * Create a new DtWriter.\n *\n * @param options - File path, schema, and optional passphrase\n */\n constructor(options: DtWriterOptions) {\n\n this.#filepath = options.filepath;\n this.#schema = options.schema;\n this.#passphrase = options.passphrase;\n this.#extension = path.extname(options.filepath).toLowerCase();\n\n }\n\n /** Total bytes written to disk. */\n get bytesWritten(): number {\n\n return this.#bytesWritten;\n\n }\n\n /** Total rows written. */\n get rowsWritten(): number {\n\n return this.#rowsWritten;\n\n }\n\n /**\n * Open the writer and write the schema header.\n *\n * Must be called before writing any rows.\n */\n async open(): Promise<void> {\n\n if (this.#extension === DT_EXTENSIONS.ENCRYPTED) {\n\n // .dtzx: buffer everything, encrypt on close\n if (!this.#passphrase) {\n\n throw new Error('Passphrase required for .dtzx files');\n\n }\n\n this.#buffer = [];\n const schemaLine = JSON5.stringify(this.#schema) + '\\n';\n this.#buffer.push(Buffer.from(schemaLine, 'utf8'));\n\n return;\n\n }\n\n // .dt or .dtz: streaming output\n const fileStream = createWriteStream(this.#filepath);\n const schemaLine = JSON5.stringify(this.#schema) + '\\n';\n\n if (this.#extension === DT_EXTENSIONS.COMPRESSED) {\n\n // .dtz: pipe through gzip\n this.#passthrough = new PassThrough();\n const gzip = createGzip();\n\n this.#pipelinePromise = pipeline(this.#passthrough, gzip, fileStream);\n this.#stream = this.#passthrough;\n this.#writeToStream(schemaLine);\n\n }\n else {\n\n // .dt: raw output\n this.#stream = fileStream;\n this.#writeToStream(schemaLine);\n\n }\n\n }\n\n /**\n * Write a single serialized row.\n *\n * @param values - Serialized .dt values in column order\n */\n writeRow(values: DtValue[]): void {\n\n const line = JSON5.stringify(values) + '\\n';\n\n if (this.#buffer) {\n\n this.#buffer.push(Buffer.from(line, 'utf8'));\n\n }\n else {\n\n this.#writeToStream(line);\n\n }\n\n this.#rowsWritten++;\n\n }\n\n /**\n * Write multiple serialized rows.\n *\n * @param rows - Array of serialized row value arrays\n */\n writeRows(rows: DtValue[][]): void {\n\n for (const row of rows) {\n\n this.writeRow(row);\n\n }\n\n }\n\n /**\n * Close the writer and finalize the file.\n *\n * For .dtzx files, this is where compression and encryption happen.\n */\n async close(): Promise<void> {\n\n if (this.#buffer) {\n\n // .dtzx: compress then encrypt the buffered content\n const { gzipSync } = await import('node:zlib');\n\n const raw = Buffer.concat(this.#buffer);\n const compressed = gzipSync(raw);\n const payload = encryptWithPassphrase(compressed, this.#passphrase!);\n\n const payloadJson = JSON.stringify(payload);\n writeFileSync(this.#filepath, payloadJson, 'utf8');\n this.#bytesWritten = Buffer.byteLength(payloadJson, 'utf8');\n this.#buffer = null;\n\n return;\n\n }\n\n if (this.#passthrough) {\n\n // .dtz: end the passthrough and wait for pipeline\n this.#passthrough.end();\n await this.#pipelinePromise;\n\n }\n else if (this.#stream) {\n\n // .dt: end the file stream\n await new Promise<void>((resolve, reject) => {\n\n this.#stream!.end(() => resolve());\n this.#stream!.on('error', reject);\n\n });\n\n }\n\n }\n\n /**\n * Write a string to the active stream and track bytes.\n */\n #writeToStream(data: string): void {\n\n if (!this.#stream) {\n\n throw new Error('Writer not opened');\n\n }\n\n const buf = Buffer.from(data, 'utf8');\n this.#bytesWritten += buf.length;\n this.#stream.write(buf);\n\n }\n\n}\n","/**\n * Serialization for .dt file format.\n *\n * Converts database row values to .dt format values.\n * Simple types become native JSON; encoded types become `[value, encoding]` tuples\n * with smart compression based on payload size.\n *\n * @example\n * ```typescript\n * import { serializeRow } from './serialize.js';\n *\n * const dtValues = serializeRow({\n * row: { id: 1, metadata: { title: 'Doc' }, embedding: [0.1, 0.2] },\n * columns: [\n * { name: 'id', type: 'int' },\n * { name: 'metadata', type: 'json' },\n * { name: 'embedding', type: 'vector' },\n * ],\n * });\n * // [1, [{ title: 'Doc' }, 'raw'], [[0.1, 0.2], 'raw']]\n * ```\n */\nimport { gzipSync } from 'node:zlib';\n\nimport type { DtColumn, DtValue, EncodedValue } from './types.js';\nimport { GZIP_THRESHOLD, GZIP_RATIO_THRESHOLD } from './constants.js';\nimport { isEncodedType } from './type-map.js';\n\n/**\n * Options for serializing a row.\n */\nexport interface SerializeRowOptions {\n\n /** Database row as key-value pairs. */\n row: Record<string, unknown>;\n\n /** Column definitions (determines serialization strategy per value). */\n columns: DtColumn[];\n\n}\n\n/**\n * Serialize a database row to .dt format values.\n *\n * Returns an array of values in column order. Simple types are passed through\n * with appropriate conversions; encoded types become `[value, encoding]` tuples.\n *\n * @param options - Row data and column definitions\n * @returns Array of .dt values in column order\n */\nexport function serializeRow(options: SerializeRowOptions): DtValue[] {\n\n const { row, columns } = options;\n const result: DtValue[] = [];\n\n for (const col of columns) {\n\n const value = row[col.name];\n result.push(serializeValue(value, col));\n\n }\n\n return result;\n\n}\n\n/**\n * Serialize a single value based on its column type.\n *\n * @param value - Raw database value\n * @param column - Column definition\n * @returns Serialized .dt value\n */\nexport function serializeValue(value: unknown, column: DtColumn): DtValue {\n\n // NULL is always null\n if (value === null || value === undefined) {\n\n return null;\n\n }\n\n // Encoded types → tuple\n if (isEncodedType(column.type)) {\n\n return encodeValue(value, column.type);\n\n }\n\n // Simple types → native JSON representation\n return serializeSimple(value, column.type);\n\n}\n\n/**\n * Serialize a simple type value to its JSON representation.\n *\n * bigint and decimal are stored as strings to preserve precision.\n * Timestamps are stored as ISO 8601 strings.\n */\nfunction serializeSimple(value: unknown, type: string): DtValue {\n\n switch (type) {\n\n case 'bigint':\n // Preserve precision beyond Number.MAX_SAFE_INTEGER\n return String(value);\n\n case 'decimal':\n // Preserve exact decimal precision\n return String(value);\n\n case 'bool':\n // Normalize truthy values (MSSQL bit, MySQL tinyint)\n if (typeof value === 'number') return value !== 0;\n if (typeof value === 'string') return value === '1' || value.toLowerCase() === 'true';\n\n return Boolean(value);\n\n case 'timestamp': {\n\n // ISO 8601 string\n if (value instanceof Date) return value.toISOString();\n\n return String(value);\n\n }\n\n case 'date': {\n\n // ISO 8601 date-only string\n if (value instanceof Date) return value.toISOString().split('T')[0];\n\n return String(value);\n\n }\n\n case 'uuid':\n return String(value);\n\n case 'int':\n case 'float':\n // Native JSON number\n return typeof value === 'string' ? Number(value) : value;\n\n case 'string':\n default:\n return String(value);\n\n }\n\n}\n\n/**\n * Encode a value for an encoded type column.\n *\n * Applies smart compression: small values stay human-readable,\n * large values are gzip+base64 compressed.\n *\n * @param value - Raw value from database\n * @param type - Universal encoded type\n * @returns Encoded value tuple `[value, encoding]`\n */\nexport function encodeValue(value: unknown, type: string): EncodedValue {\n\n if (type === 'binary') {\n\n return encodeBinary(value);\n\n }\n\n // json, vector, array, custom — all follow the same compression logic\n return encodeJsonLike(value);\n\n}\n\n/**\n * Encode a binary value.\n *\n * Small binary → base64, large binary → gzip+base64 if worthwhile.\n */\nfunction encodeBinary(value: unknown): EncodedValue {\n\n const buf = toBuffer(value);\n const byteLength = buf.length;\n\n // Small binary: just base64\n if (byteLength < GZIP_THRESHOLD) {\n\n return [buf.toString('base64'), 'b64'];\n\n }\n\n // Try gzip compression\n const compressed = gzipSync(buf);\n\n if (compressed.length < byteLength * GZIP_RATIO_THRESHOLD) {\n\n return [compressed.toString('base64'), 'gz64'];\n\n }\n\n // Gzip didn't help enough, use plain base64\n return [buf.toString('base64'), 'b64'];\n\n}\n\n/**\n * Encode a JSON-like value (json, vector, array, custom).\n *\n * Small payloads stay raw for readability; large ones get compressed.\n */\nfunction encodeJsonLike(value: unknown): EncodedValue {\n\n const jsonStr = JSON.stringify(value);\n const byteLength = Buffer.byteLength(jsonStr, 'utf8');\n\n // Small value: keep human-readable\n if (byteLength < GZIP_THRESHOLD) {\n\n return [value, 'raw'];\n\n }\n\n // Try gzip compression\n const buf = Buffer.from(jsonStr, 'utf8');\n const compressed = gzipSync(buf);\n\n if (compressed.length < byteLength * GZIP_RATIO_THRESHOLD) {\n\n return [compressed.toString('base64'), 'gz64'];\n\n }\n\n // Gzip didn't help, keep raw\n return [value, 'raw'];\n\n}\n\n/**\n * Convert a value to a Buffer.\n *\n * Handles Buffer, Uint8Array, and base64 strings.\n */\nfunction toBuffer(value: unknown): Buffer {\n\n if (Buffer.isBuffer(value)) return value;\n if (value instanceof Uint8Array) return Buffer.from(value);\n if (typeof value === 'string') return Buffer.from(value, 'base64');\n\n return Buffer.from(String(value), 'utf8');\n\n}\n","/**\n * Deserialization for .dt file format.\n *\n * Converts .dt format values back to database-ready values.\n * Reverses encoding tuples and applies version-aware target conversions.\n *\n * @example\n * ```typescript\n * import { deserializeRow } from './deserialize.js';\n *\n * const row = deserializeRow({\n * values: [1, [{ title: 'Doc' }, 'raw'], [[0.1, 0.2], 'raw']],\n * columns: [\n * { name: 'id', type: 'int' },\n * { name: 'metadata', type: 'json' },\n * { name: 'embedding', type: 'vector' },\n * ],\n * targetDialect: 'postgres',\n * });\n * // { id: 1, metadata: { title: 'Doc' }, embedding: '[0.1,0.2]' }\n * ```\n */\nimport { gunzipSync } from 'node:zlib';\n\nimport type { Dialect } from '../connection/types.js';\nimport type { DtColumn, DtValue, DatabaseVersion, Encoding } from './types.js';\nimport { isEncodedType } from './type-map.js';\n\n/**\n * Options for deserializing a row.\n */\nexport interface DeserializeRowOptions {\n\n /** Array of .dt values in column order. */\n values: DtValue[];\n\n /** Column definitions. */\n columns: DtColumn[];\n\n /** Target database dialect for value conversion. */\n targetDialect: Dialect;\n\n /** Target database version for version-aware conversion. */\n targetVersion?: DatabaseVersion;\n\n}\n\n/**\n * Deserialize a .dt row back to a database-ready record.\n *\n * Reverses encoding and applies target-dialect conversions.\n *\n * @param options - Values, columns, and target info\n * @returns Record ready for database insertion\n */\nexport function deserializeRow(options: DeserializeRowOptions): Record<string, unknown> {\n\n const { values, columns, targetDialect, targetVersion } = options;\n const result: Record<string, unknown> = {};\n\n for (let i = 0; i < columns.length; i++) {\n\n const col = columns[i]!;\n const value = values[i];\n\n result[col.name] = deserializeValue(value, col, targetDialect, targetVersion);\n\n }\n\n return result;\n\n}\n\n/**\n * Deserialize a single .dt value.\n *\n * @param value - .dt value (native JSON or encoded tuple)\n * @param column - Column definition\n * @param targetDialect - Target database dialect\n * @param targetVersion - Target database version\n * @returns Database-ready value\n */\nexport function deserializeValue(\n value: DtValue,\n column: DtColumn,\n targetDialect: Dialect,\n targetVersion?: DatabaseVersion,\n): unknown {\n\n // NULL passthrough\n if (value === null || value === undefined) {\n\n return null;\n\n }\n\n // Encoded types: decode the tuple first, then convert for target\n if (isEncodedType(column.type)) {\n\n const decoded = decodeTuple(value as [unknown, Encoding, ...unknown[]]);\n\n return convertEncodedForTarget(decoded, column.type, targetDialect, targetVersion);\n\n }\n\n // Simple types: convert for target dialect\n return convertSimpleForTarget(value, column.type, targetDialect);\n\n}\n\n/**\n * Decode an encoded value tuple.\n *\n * Reverses the encoding applied by serialize:\n * - `raw`: value is already the decoded object/array\n * - `b64`: base64 string → Buffer\n * - `gz64`: base64 string → gunzip → raw data\n *\n * @param tuple - Encoded value tuple `[value, encoding]`\n * @returns Decoded value\n */\nfunction decodeTuple(tuple: [unknown, Encoding, ...unknown[]]): unknown {\n\n // Safety: if not an array or missing encoding, treat as raw\n if (!Array.isArray(tuple) || tuple.length < 2) {\n\n return tuple;\n\n }\n\n const [value, encoding] = tuple;\n\n switch (encoding) {\n\n case 'raw':\n return value;\n\n case 'b64':\n return Buffer.from(value as string, 'base64');\n\n case 'gz64': {\n\n const compressed = Buffer.from(value as string, 'base64');\n const decompressed = gunzipSync(compressed);\n\n // Try parsing as JSON; if it fails, return the buffer\n const str = decompressed.toString('utf8');\n\n // Check if it looks like JSON (starts with {, [, \", or is a number)\n if (/^[[{\"\\d]/.test(str)) {\n\n // Attempt JSON parse; raw buffer fallback handled by caller\n return JSON.parse(str);\n\n }\n\n return decompressed;\n\n }\n\n default:\n return value;\n\n }\n\n}\n\n/**\n * Convert a decoded encoded-type value for the target dialect.\n *\n * Handles dialect-specific differences like:\n * - vector: pgvector string format vs JSON string vs native\n * - json: native object vs JSON.stringify for MSSQL < 2025\n * - array: native vs JSON string\n */\nfunction convertEncodedForTarget(\n decoded: unknown,\n type: string,\n targetDialect: Dialect,\n targetVersion?: DatabaseVersion,\n): unknown {\n\n switch (type) {\n\n case 'json':\n return convertJsonForTarget(decoded, targetDialect, targetVersion);\n\n case 'binary':\n // Binary is always a Buffer after decoding\n return decoded;\n\n case 'vector':\n return convertVectorForTarget(decoded, targetDialect, targetVersion);\n\n case 'array':\n return convertArrayForTarget(decoded, targetDialect);\n\n case 'custom':\n // Custom types: stringify for non-native targets\n if (typeof decoded === 'object') return JSON.stringify(decoded);\n\n return decoded;\n\n default:\n return decoded;\n\n }\n\n}\n\n/**\n * Convert JSON value for target dialect.\n *\n * PostgreSQL: pass object directly (Kysely handles jsonb)\n * MySQL: pass object (driver handles native JSON)\n * MSSQL 2025+: pass object (native JSON)\n * MSSQL < 2025: JSON.stringify (stored in nvarchar)\n */\nfunction convertJsonForTarget(\n decoded: unknown,\n targetDialect: Dialect,\n targetVersion?: DatabaseVersion,\n): unknown {\n\n if (targetDialect === 'mssql') {\n\n const major = targetVersion?.major ?? 2022;\n\n // MSSQL < 2025 stores JSON as NVARCHAR(MAX) string\n if (major < 2025) {\n\n return typeof decoded === 'string' ? decoded : JSON.stringify(decoded);\n\n }\n\n }\n\n // PostgreSQL, MySQL, MSSQL 2025+: pass native object\n return decoded;\n\n}\n\n/**\n * Convert vector value for target dialect.\n *\n * PostgreSQL: `'[0.1,0.2,0.3]'` string format for pgvector\n * MySQL 9+: string format for native VECTOR\n * MySQL < 9: JSON string (stored in JSON column)\n * MSSQL 2025+: JSON array string for native VECTOR\n * MSSQL < 2025: JSON array string for NVARCHAR(MAX)\n */\nfunction convertVectorForTarget(\n decoded: unknown,\n targetDialect: Dialect,\n targetVersion?: DatabaseVersion,\n): unknown {\n\n // Ensure we have an array\n const arr = Array.isArray(decoded) ? decoded : decoded;\n\n if (targetDialect === 'postgres') {\n\n // pgvector expects '[0.1,0.2,0.3]' string format\n return Array.isArray(arr) ? `[${arr.join(',')}]` : String(arr);\n\n }\n\n if (targetDialect === 'mysql') {\n\n const major = targetVersion?.major ?? 8;\n\n if (major >= 9) {\n\n // MySQL 9+ native VECTOR: string format '[0.1,0.2]'\n return Array.isArray(arr) ? `[${arr.join(',')}]` : String(arr);\n\n }\n\n // MySQL < 9: store as JSON array string\n return Array.isArray(arr) ? JSON.stringify(arr) : String(arr);\n\n }\n\n // MSSQL: JSON array string (both native VECTOR and NVARCHAR workaround)\n return Array.isArray(arr) ? JSON.stringify(arr) : String(arr);\n\n}\n\n/**\n * Convert array value for target dialect.\n *\n * PostgreSQL: native array (pass through)\n * MySQL/MSSQL: JSON string (no native array support)\n */\nfunction convertArrayForTarget(decoded: unknown, targetDialect: Dialect): unknown {\n\n if (targetDialect === 'postgres') {\n\n // PostgreSQL has native arrays\n return decoded;\n\n }\n\n // MySQL and MSSQL: store as JSON string\n return Array.isArray(decoded) ? JSON.stringify(decoded) : String(decoded);\n\n}\n\n/**\n * Convert a simple type value for the target dialect.\n */\nfunction convertSimpleForTarget(value: DtValue, type: string, targetDialect: Dialect): unknown {\n\n switch (type) {\n\n case 'bigint':\n // MSSQL and some drivers need actual bigint values\n if (typeof value === 'string') {\n\n const num = Number(value);\n\n if (Number.isSafeInteger(num)) return num;\n\n }\n\n return value;\n\n case 'decimal':\n // Keep as string for precision\n return value;\n\n case 'bool':\n // MSSQL uses BIT (0/1), MySQL uses TINYINT(1)\n if (targetDialect === 'mssql') return value ? 1 : 0;\n if (targetDialect === 'mysql') return value ? 1 : 0;\n\n return value;\n\n case 'timestamp':\n // Convert ISO string to Date object for some drivers\n if (typeof value === 'string') return new Date(value);\n\n return value;\n\n case 'date':\n // Keep as string for date-only columns\n return value;\n\n case 'uuid':\n return value;\n\n case 'int':\n case 'float':\n return value;\n\n case 'string':\n default:\n return value;\n\n }\n\n}\n","/**\n * .dt data transfer format module.\n *\n * Provides the public API for:\n * - File export: DB table → .dt/.dtz/.dtzx file\n * - File import: .dt/.dtz/.dtzx file → DB table\n * - In-memory cross-dialect conversion (DtStreamer)\n * - Schema building and validation\n * - Database version detection\n *\n * @example\n * ```typescript\n * import { exportTable, importDtFile, createStreamer } from './dt/index.js';\n *\n * // Export a table to .dt file\n * const [result, err] = await exportTable({\n * db: kyselyDb,\n * dialect: 'postgres',\n * tableName: 'users',\n * filepath: './data/users.dtz',\n * });\n *\n * // Import from .dt file\n * const [importResult, importErr] = await importDtFile({\n * filepath: './data/users.dtz',\n * db: destDb,\n * dialect: 'mysql',\n * });\n *\n * // Cross-dialect streaming (used internally by transfer module)\n * const streamer = createStreamer({\n * sourceDialect: 'postgres',\n * targetDialect: 'mysql',\n * columns: schema.columns,\n * });\n * ```\n */\nimport { sql } from 'kysely';\nimport { attempt } from '@logosdx/utils';\n\nimport type { Kysely } from 'kysely';\nimport type { NoormDatabase } from '../shared/tables.js';\nimport type { ExportTableOptions, ImportFileOptions, DtStreamerOptions } from './types.js';\n\nimport { observer } from '../observer.js';\nimport { DtWriter } from './writer.js';\nimport { DtReader } from './reader.js';\nimport { DtStreamer } from './streamer.js';\nimport { buildDtSchema, validateSchema } from './schema.js';\nimport { serializeRow } from './serialize.js';\nimport { deserializeRow } from './deserialize.js';\n\n/**\n * Export a database table to a .dt/.dtz/.dtzx file.\n *\n * Queries all rows from the table, serializes to .dt format,\n * and writes to the specified file path.\n *\n * @param options - Export configuration\n * @returns Row count and bytes written, or error\n *\n * @example\n * ```typescript\n * const [result, err] = await exportTable({\n * db: kyselyDb,\n * dialect: 'postgres',\n * tableName: 'users',\n * filepath: './data/users.dtz',\n * batchSize: 5000,\n * });\n * ```\n */\nexport async function exportTable(\n options: ExportTableOptions,\n): Promise<[{ rowsWritten: number; bytesWritten: number } | null, Error | null]> {\n\n const startTime = Date.now();\n const { db, dialect, tableName, filepath, passphrase, schema: schemaName } = options;\n const kyselyDb = db as Kysely<NoormDatabase>;\n const batchSize = options.batchSize ?? 1000;\n\n // Build schema\n const [dtSchema, schemaErr] = await buildDtSchema({\n db: kyselyDb,\n dialect,\n tableName,\n version: options.version,\n schema: schemaName,\n });\n\n if (schemaErr || !dtSchema) {\n\n return [null, schemaErr ?? new Error('Failed to build schema')];\n\n }\n\n observer.emit('dt:export:start', {\n filepath,\n table: tableName,\n columnCount: dtSchema.columns.length,\n });\n\n // Create writer\n const writer = new DtWriter({ filepath, schema: dtSchema, passphrase });\n const [, openErr] = await attempt(() => writer.open());\n\n if (openErr) {\n\n return [null, openErr];\n\n }\n\n // Fetch and write in batches\n let offset = 0;\n const columns = dtSchema.columns.map((c) => c.name);\n const quoteIdent = dialect === 'mssql'\n ? (c: string) => `[${c}]`\n : dialect === 'mysql'\n ? (c: string) => `\\`${c}\\``\n : (c: string) => `\"${c}\"`;\n\n const columnList = columns.map(quoteIdent).join(', ');\n\n while (true) {\n\n const [rows, fetchErr] = await attempt(() => {\n\n if (dialect === 'mssql') {\n\n const orderCol = quoteIdent(columns[0]!);\n\n return sql<Record<string, unknown>>`\n SELECT ${sql.raw(columnList)}\n FROM ${sql.table(tableName)}\n ORDER BY ${sql.raw(orderCol)}\n OFFSET ${offset} ROWS\n FETCH NEXT ${batchSize} ROWS ONLY\n `.execute(kyselyDb);\n\n }\n\n return sql<Record<string, unknown>>`\n SELECT ${sql.raw(columnList)}\n FROM ${sql.table(tableName)}\n LIMIT ${batchSize}\n OFFSET ${offset}\n `.execute(kyselyDb);\n\n });\n\n if (fetchErr) {\n\n return [null, fetchErr];\n\n }\n\n if (rows.rows.length === 0) break;\n\n // Serialize and write each row\n for (const row of rows.rows) {\n\n const values = serializeRow({ row, columns: dtSchema.columns });\n writer.writeRow(values);\n\n }\n\n offset += rows.rows.length;\n\n observer.emit('dt:export:progress', {\n filepath,\n table: tableName,\n rowsWritten: writer.rowsWritten,\n bytesWritten: writer.bytesWritten,\n });\n\n if (rows.rows.length < batchSize) break;\n\n }\n\n // Close writer\n const [, closeErr] = await attempt(() => writer.close());\n\n if (closeErr) {\n\n return [null, closeErr];\n\n }\n\n const durationMs = Date.now() - startTime;\n\n observer.emit('dt:export:complete', {\n filepath,\n table: tableName,\n rowsWritten: writer.rowsWritten,\n bytesWritten: writer.bytesWritten,\n durationMs,\n });\n\n return [{ rowsWritten: writer.rowsWritten, bytesWritten: writer.bytesWritten }, null];\n\n}\n\n/**\n * Import a .dt/.dtz/.dtzx file into a database table.\n *\n * Reads the file, validates schema against the target, then inserts rows.\n *\n * @param options - Import configuration\n * @returns Row counts, or error\n *\n * @example\n * ```typescript\n * const [result, err] = await importDtFile({\n * filepath: './data/users.dtz',\n * db: destDb,\n * dialect: 'mysql',\n * onConflict: 'skip',\n * });\n * ```\n */\nexport async function importDtFile(\n options: ImportFileOptions,\n): Promise<[{ rowsImported: number; rowsSkipped: number } | null, Error | null]> {\n\n const startTime = Date.now();\n const { filepath, db, dialect, passphrase, version } = options;\n const kyselyDb = db as Kysely<NoormDatabase>;\n const batchSize = options.batchSize ?? 1000;\n\n // Open reader\n const reader = new DtReader({ filepath, passphrase });\n const [, openErr] = await attempt(() => reader.open());\n\n if (openErr) {\n\n observer.emit('error', { source: 'dt:import', error: openErr, context: { filepath } });\n\n return [null, openErr];\n\n }\n\n const dtSchema = reader.schema;\n\n if (!dtSchema) {\n\n const err = new Error('Failed to read .dt schema');\n observer.emit('error', { source: 'dt:import', error: err, context: { filepath } });\n\n return [null, err];\n\n }\n\n const tableName = dtSchema.t ?? 'unknown';\n\n observer.emit('dt:import:start', {\n filepath,\n sourceDialect: dtSchema.d,\n sourceVersion: dtSchema.dv,\n table: tableName,\n });\n\n // Validate schema against target\n const [validation, validateErr] = await validateSchema({\n dtSchema,\n targetDb: kyselyDb,\n targetDialect: dialect,\n targetVersion: version,\n });\n\n if (validateErr) {\n\n reader.close();\n observer.emit('error', { source: 'dt:import', error: validateErr, context: { filepath, table: tableName } });\n\n return [null, validateErr];\n\n }\n\n observer.emit('dt:import:schema', {\n filepath,\n table: tableName,\n columns: dtSchema.columns.length,\n validation: validation!,\n });\n\n // If validation has errors, abort\n if (validation && !validation.valid) {\n\n reader.close();\n const err = new Error(`Schema validation failed: ${validation.errors.join('; ')}`);\n observer.emit('error', { source: 'dt:import', error: err, context: { filepath, table: tableName } });\n\n return [null, err];\n\n }\n\n // Truncate if requested\n if (options.truncate && tableName !== 'unknown') {\n\n const truncateSql = dialect === 'postgres'\n ? `TRUNCATE TABLE \"${tableName}\" CASCADE`\n : dialect === 'mssql'\n ? `DELETE FROM [${tableName}]`\n : `TRUNCATE TABLE \\`${tableName}\\``;\n\n const [, truncErr] = await attempt(() => sql.raw(truncateSql).execute(kyselyDb));\n\n if (truncErr) {\n\n reader.close();\n const err = new Error(`Failed to truncate: ${truncErr.message}`);\n observer.emit('error', { source: 'dt:import', error: err, context: { filepath, table: tableName } });\n\n return [null, err];\n\n }\n\n }\n\n // Import rows in batches\n let rowsImported = 0;\n let rowsSkipped = 0;\n let batch: Record<string, unknown>[] = [];\n\n for await (const values of reader.rows()) {\n\n const row = deserializeRow({\n values,\n columns: dtSchema.columns,\n targetDialect: dialect,\n targetVersion: version,\n });\n\n batch.push(row);\n\n if (batch.length >= batchSize) {\n\n const columnNames = dtSchema.columns.map((c) => c.name);\n const [batchResult, insertErr] = await insertImportBatch(\n kyselyDb,\n tableName,\n batch,\n options.onConflict ?? 'fail',\n dialect,\n columnNames,\n );\n\n if (insertErr) {\n\n reader.close();\n observer.emit('error', { source: 'dt:import', error: insertErr, context: { filepath, table: tableName } });\n\n return [null, insertErr];\n\n }\n\n rowsImported += batchResult.inserted + batchResult.updated;\n rowsSkipped += batchResult.skipped;\n batch = [];\n\n observer.emit('dt:import:progress', {\n filepath,\n table: tableName,\n rowsImported,\n rowsSkipped,\n });\n\n }\n\n }\n\n // Insert remaining rows\n if (batch.length > 0) {\n\n const columnNames = dtSchema.columns.map((c) => c.name);\n const [batchResult, insertErr] = await insertImportBatch(\n kyselyDb,\n tableName,\n batch,\n options.onConflict ?? 'fail',\n dialect,\n columnNames,\n );\n\n if (insertErr) {\n\n reader.close();\n observer.emit('error', { source: 'dt:import', error: insertErr, context: { filepath, table: tableName } });\n\n return [null, insertErr];\n\n }\n\n rowsImported += batchResult.inserted + batchResult.updated;\n rowsSkipped += batchResult.skipped;\n\n }\n\n reader.close();\n\n const durationMs = Date.now() - startTime;\n\n observer.emit('dt:import:complete', {\n filepath,\n table: tableName,\n rowsImported,\n rowsSkipped,\n durationMs,\n });\n\n return [{ rowsImported, rowsSkipped }, null];\n\n}\n\n/**\n * Create a DtStreamer for in-memory cross-dialect conversion.\n *\n * Used internally by the transfer module for cross-dialect DB-to-DB transfers.\n *\n * @param options - Source/target dialects and column definitions\n * @returns Configured DtStreamer instance\n */\nexport function createStreamer(options: DtStreamerOptions): DtStreamer {\n\n return new DtStreamer(options);\n\n}\n\n/**\n * Insert a batch of rows for import.\n */\nasync function insertImportBatch(\n db: Kysely<NoormDatabase>,\n table: string,\n rows: Record<string, unknown>[],\n onConflict: string,\n dialect: string,\n columns: string[],\n): Promise<[{ inserted: number; skipped: number; updated: number }, Error | null]> {\n\n let inserted = 0;\n let skipped = 0;\n let updated = 0;\n\n for (const row of rows) {\n\n const [, err] = await attempt(() =>\n db.insertInto(table as never).values(row as never).execute(),\n );\n\n if (err) {\n\n if (!isDuplicateError(err.message)) {\n\n // Non-duplicate error\n if (onConflict === 'fail') {\n\n return [{ inserted, skipped, updated }, err];\n\n }\n\n skipped++;\n continue;\n\n }\n\n // Duplicate key error\n if (onConflict === 'skip') {\n\n skipped++;\n\n }\n else if (onConflict === 'update') {\n\n // Try to update existing row\n const [updateResult, updateErr] = await attemptUpdate(db, table, row, dialect, columns);\n\n if (updateErr) {\n\n return [{ inserted, skipped, updated }, updateErr];\n\n }\n\n if (updateResult) {\n\n updated++;\n\n }\n else {\n\n skipped++;\n\n }\n\n }\n else if (onConflict === 'fail') {\n\n return [{ inserted, skipped, updated }, err];\n\n }\n else {\n\n skipped++;\n\n }\n\n }\n else {\n\n inserted++;\n\n }\n\n }\n\n return [{ inserted, skipped, updated }, null];\n\n}\n\n/**\n * Attempt to update an existing row.\n *\n * Uses the first column as the primary key for the WHERE clause.\n * This is a heuristic - ideally we'd know the actual PK from schema.\n */\nasync function attemptUpdate(\n db: Kysely<NoormDatabase>,\n table: string,\n row: Record<string, unknown>,\n _dialect: string,\n columns: string[],\n): Promise<[boolean, Error | null]> {\n\n // Assume first column is the primary key (common convention)\n const pkColumn = columns[0];\n\n if (!pkColumn || row[pkColumn] === undefined) {\n\n return [false, null];\n\n }\n\n const pkValue = row[pkColumn];\n\n // Build update values (exclude PK column)\n const updateValues: Record<string, unknown> = {};\n\n for (const col of columns) {\n\n if (col !== pkColumn && row[col] !== undefined) {\n\n updateValues[col] = row[col];\n\n }\n\n }\n\n if (Object.keys(updateValues).length === 0) {\n\n // Nothing to update besides PK\n return [true, null];\n\n }\n\n // Use Kysely's update builder for proper value handling\n const [, err] = await attempt(() =>\n db\n .updateTable(table as never)\n .set(updateValues as never)\n .where(pkColumn as never, '=', pkValue as never)\n .execute(),\n );\n\n if (err) {\n\n return [false, err];\n\n }\n\n return [true, null];\n\n}\n\n/**\n * Check if an error is a duplicate key violation.\n */\nfunction isDuplicateError(message: string): boolean {\n\n const lower = message.toLowerCase();\n\n return (\n lower.includes('duplicate') ||\n lower.includes('unique constraint') ||\n lower.includes('primary key') ||\n lower.includes('violates unique') ||\n lower.includes('cannot insert duplicate') ||\n lower.includes('duplicate entry')\n );\n\n}\n\n// Re-export public types and classes\nexport type {\n DtSchema,\n DtColumn,\n DtValue,\n UniversalType,\n SimpleType,\n EncodedType,\n Encoding,\n EncodedValue,\n FormatVersion,\n DatabaseVersion,\n TypeMappingResult,\n DtWriterOptions,\n DtReaderOptions,\n DtStreamerOptions,\n BuildSchemaOptions,\n ValidateSchemaOptions,\n SchemaValidationResult,\n ExportTableOptions,\n ImportFileOptions,\n DtEncryptedPayload,\n} from './types.js';\n\nexport type { DtEvents } from './events.js';\n\nexport { DtWriter } from './writer.js';\nexport { DtReader } from './reader.js';\nexport { DtStreamer } from './streamer.js';\nexport { buildDtSchema, validateSchema } from './schema.js';\nexport { queryDatabaseVersion } from './version.js';\nexport { toUniversalType, toDialectType, isEncodedType } from './type-map.js';\nexport { serializeRow, serializeValue, encodeValue } from './serialize.js';\nexport { deserializeRow, deserializeValue } from './deserialize.js';\nexport { encryptWithPassphrase, decryptWithPassphrase } from './crypto.js';\nexport { FORMAT_VERSION, GZIP_THRESHOLD, GZIP_RATIO_THRESHOLD, SIMPLE_TYPES, ENCODED_TYPES } from './constants.js';\nexport { resolveExportExtension, resolveExportPath, ensureExportDirectory } from './paths.js';\n","/**\n * SDK Safety Guards.\n *\n * Guards protect against accidental destructive operations\n * on production or protected databases.\n */\nimport type { Config } from '../core/config/types.js';\nimport type { CreateContextOptions } from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Error Classes\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Error thrown when requireTest is enabled but config.isTest is false.\n *\n * @example\n * ```typescript\n * const ctx = await createContext({\n * config: 'prod',\n * requireTest: true, // Will throw RequireTestError\n * })\n * ```\n */\nexport class RequireTestError extends Error {\n\n override readonly name = 'RequireTestError' as const;\n\n constructor(public readonly configName: string) {\n\n super(`Config \"${configName}\" does not have isTest: true`);\n\n }\n\n}\n\n/**\n * Error thrown when attempting destructive operations on protected configs.\n *\n * @example\n * ```typescript\n * // If config.protected is true and allowProtected is false\n * await ctx.truncate() // Throws ProtectedConfigError\n * ```\n */\nexport class ProtectedConfigError extends Error {\n\n override readonly name = 'ProtectedConfigError' as const;\n\n constructor(\n public readonly configName: string,\n public readonly operation: string,\n ) {\n\n super(`Cannot ${operation} on protected config \"${configName}\"`);\n\n }\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Guard Functions\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Check if requireTest option is satisfied.\n *\n * @throws RequireTestError if requireTest is true but config.isTest is false\n */\nexport function checkRequireTest(\n config: Config,\n options: CreateContextOptions,\n): void {\n\n if (options.requireTest && !config.isTest) {\n\n throw new RequireTestError(config.name);\n\n }\n\n}\n\n/**\n * Check if operation is allowed on protected config.\n *\n * @throws ProtectedConfigError if config is protected and allowProtected is false\n */\nexport function checkProtectedConfig(\n config: Config,\n operation: string,\n options: CreateContextOptions,\n): void {\n\n if (config.protected && !options.allowProtected) {\n\n throw new ProtectedConfigError(config.name, operation);\n\n }\n\n}\n","/**\n * NoormOps — noorm-specific operations behind ctx.noorm namespace.\n *\n * Separates database management operations (build, truncate, changes,\n * locks, etc.) from the SQL-focused top-level Context API. Both share\n * the same ContextState so connection state stays in sync.\n */\nimport path from 'node:path';\n\nimport type { Kysely } from 'kysely';\n\nimport type { Dialect } from '../core/connection/index.js';\nimport type { Config } from '../core/config/types.js';\nimport type { Settings } from '../core/settings/index.js';\nimport type { Identity } from '../core/identity/index.js';\nimport type { NoormDatabase } from '../core/shared/index.js';\nimport type {\n TableSummary,\n TableDetail,\n ExploreOverview,\n} from '../core/explore/index.js';\nimport type { TruncateResult, TeardownResult } from '../core/teardown/index.js';\nimport type { BatchResult, FileResult, RunOptions, RunContext } from '../core/runner/index.js';\nimport type {\n ChangeResult,\n BatchChangeResult,\n ChangeListItem,\n ChangeOptions,\n ChangeContext,\n ChangeHistoryRecord,\n} from '../core/change/index.js';\nimport type { Lock, LockStatus, LockOptions } from '../core/lock/index.js';\nimport type { ProcessResult as TemplateResult } from '../core/template/index.js';\nimport type { TransferOptions, TransferResult, TransferPlan } from '../core/transfer/types.js';\n\nimport { fetchOverview, fetchList, fetchDetail } from '../core/explore/index.js';\nimport { truncateData, teardownSchema } from '../core/teardown/index.js';\nimport {\n runBuild,\n runFile as coreRunFile,\n runDir as coreRunDir,\n runFiles as coreRunFiles,\n computeChecksum as coreComputeChecksum,\n} from '../core/runner/index.js';\nimport { ChangeManager } from '../core/change/index.js';\nimport { getLockManager } from '../core/lock/index.js';\nimport { processFile } from '../core/template/index.js';\nimport { formatIdentity } from '../core/identity/index.js';\nimport { observer } from '../core/observer.js';\nimport { getStateManager } from '../core/state/index.js';\nimport { testConnection as coreTestConnection } from '../core/connection/index.js';\nimport { transferData, getTransferPlan } from '../core/transfer/index.js';\nimport { exportTable as coreExportTable, importDtFile } from '../core/dt/index.js';\n\nimport { checkProtectedConfig } from './guards.js';\nimport type { ContextState } from './state.js';\nimport type { BuildOptions, ExportOptions, ImportOptions } from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// NoormOps Class\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Noorm-specific operations accessed via ctx.noorm.\n *\n * All database management operations — schema, changes, locks,\n * runner, explore, transfer, DT — live here. The shared ContextState\n * keeps connection state in sync with the parent Context.\n *\n * @example\n * ```typescript\n * const ctx = await createContext({ config: 'dev' })\n * await ctx.connect()\n *\n * await ctx.noorm.build()\n * await ctx.noorm.fastForward()\n * const tables = await ctx.noorm.listTables()\n * ```\n */\nexport class NoormOps {\n\n #state: ContextState;\n\n constructor(state: ContextState) {\n\n this.#state = state;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Read-only Properties\n // ─────────────────────────────────────────────────────────\n\n get config(): Config {\n\n return this.#state.config;\n\n }\n\n get settings(): Settings {\n\n return this.#state.settings;\n\n }\n\n get identity(): Identity {\n\n return this.#state.identity;\n\n }\n\n get observer() {\n\n return observer;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Private Accessors\n // ─────────────────────────────────────────────────────────\n\n get #kysely(): Kysely<unknown> {\n\n if (!this.#state.connection) {\n\n throw new Error('Not connected. Call connect() first.');\n\n }\n\n return this.#state.connection.db;\n\n }\n\n get #dialect(): Dialect {\n\n return this.#state.config.connection.dialect;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Explore\n // ─────────────────────────────────────────────────────────\n\n /**\n * List all tables in the database.\n *\n * @example\n * ```typescript\n * const tables = await ctx.noorm.listTables()\n * ```\n */\n async listTables(): Promise<TableSummary[]> {\n\n return fetchList(this.#kysely, this.#dialect, 'tables');\n\n }\n\n /**\n * Get detailed information about a table.\n *\n * @example\n * ```typescript\n * const detail = await ctx.noorm.describeTable('users')\n * ```\n */\n async describeTable(name: string, schema?: string): Promise<TableDetail | null> {\n\n return fetchDetail(this.#kysely, this.#dialect, 'tables', name, schema);\n\n }\n\n /**\n * Get database overview with counts of all object types.\n *\n * @example\n * ```typescript\n * const overview = await ctx.noorm.overview()\n * ```\n */\n async overview(): Promise<ExploreOverview> {\n\n return fetchOverview(this.#kysely, this.#dialect);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Schema Operations\n // ─────────────────────────────────────────────────────────\n\n /**\n * Wipe all data, keeping the schema intact.\n *\n * @example\n * ```typescript\n * const result = await ctx.noorm.truncate()\n * ```\n */\n async truncate(): Promise<TruncateResult> {\n\n checkProtectedConfig(this.#state.config, 'truncate', this.#state.options);\n\n return truncateData(this.#kysely, this.#dialect);\n\n }\n\n /**\n * Drop all database objects except noorm tracking tables.\n *\n * @example\n * ```typescript\n * const result = await ctx.noorm.teardown()\n * ```\n */\n async teardown(): Promise<TeardownResult> {\n\n checkProtectedConfig(this.#state.config, 'teardown', this.#state.options);\n\n return teardownSchema(this.#kysely, this.#dialect, {\n configName: this.#state.config.name,\n executedBy: formatIdentity(this.#state.identity),\n });\n\n }\n\n /**\n * Execute all SQL files in the schema directory.\n *\n * @example\n * ```typescript\n * const result = await ctx.noorm.build({ force: true })\n * ```\n */\n async build(options?: BuildOptions): Promise<BatchResult> {\n\n const runContext = this.#createRunContext();\n const sqlPath = path.join(\n this.#state.projectRoot,\n this.#state.config.paths.sql,\n );\n\n return runBuild(runContext, sqlPath, { force: options?.force });\n\n }\n\n /**\n * Full rebuild: teardown + build.\n *\n * @example\n * ```typescript\n * await ctx.noorm.reset()\n * ```\n */\n async reset(): Promise<void> {\n\n checkProtectedConfig(this.#state.config, 'reset', this.#state.options);\n\n await this.teardown();\n await this.build({ force: true });\n\n }\n\n // ─────────────────────────────────────────────────────────\n // File Runner\n // ─────────────────────────────────────────────────────────\n\n /**\n * Execute a single SQL file.\n *\n * @example\n * ```typescript\n * await ctx.noorm.runFile('seeds/test-data.sql')\n * ```\n */\n async runFile(filepath: string, options?: RunOptions): Promise<FileResult> {\n\n const runContext = this.#createRunContext();\n const absolutePath = path.isAbsolute(filepath)\n ? filepath\n : path.join(this.#state.projectRoot, filepath);\n\n return coreRunFile(runContext, absolutePath, options);\n\n }\n\n /**\n * Execute multiple SQL files sequentially.\n *\n * @example\n * ```typescript\n * await ctx.noorm.runFiles(['functions/utils.sql', 'triggers/audit.sql'])\n * ```\n */\n async runFiles(filepaths: string[], options?: RunOptions): Promise<BatchResult> {\n\n const runContext = this.#createRunContext();\n const absolutePaths = filepaths.map((fp) =>\n path.isAbsolute(fp) ? fp : path.join(this.#state.projectRoot, fp),\n );\n\n return coreRunFiles(runContext, absolutePaths, options);\n\n }\n\n /**\n * Execute all SQL files in a directory.\n *\n * @example\n * ```typescript\n * await ctx.noorm.runDir('seeds/')\n * ```\n */\n async runDir(dirpath: string, options?: RunOptions): Promise<BatchResult> {\n\n const runContext = this.#createRunContext();\n const absolutePath = path.isAbsolute(dirpath)\n ? dirpath\n : path.join(this.#state.projectRoot, dirpath);\n\n return coreRunDir(runContext, absolutePath, options);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Changes\n // ─────────────────────────────────────────────────────────\n\n /**\n * Apply a specific change.\n *\n * @example\n * ```typescript\n * const result = await ctx.noorm.applyChange('2024-01-15-add-users')\n * ```\n */\n async applyChange(\n name: string,\n options?: ChangeOptions,\n ): Promise<ChangeResult> {\n\n return this.#getChangeManager().run(name, options);\n\n }\n\n /**\n * Revert a specific change.\n *\n * @example\n * ```typescript\n * const result = await ctx.noorm.revertChange('2024-01-15-add-users')\n * ```\n */\n async revertChange(\n name: string,\n options?: ChangeOptions,\n ): Promise<ChangeResult> {\n\n return this.#getChangeManager().revert(name, options);\n\n }\n\n /**\n * Apply all pending changes.\n *\n * @example\n * ```typescript\n * const result = await ctx.noorm.fastForward()\n * ```\n */\n async fastForward(): Promise<BatchChangeResult> {\n\n return this.#getChangeManager().ff();\n\n }\n\n /**\n * Get status of all changes.\n *\n * @example\n * ```typescript\n * const changes = await ctx.noorm.getChangeStatus()\n * ```\n */\n async getChangeStatus(): Promise<ChangeListItem[]> {\n\n return this.#getChangeManager().list();\n\n }\n\n /**\n * Get only pending changes.\n *\n * @example\n * ```typescript\n * const pending = await ctx.noorm.getPendingChanges()\n * ```\n */\n async getPendingChanges(): Promise<ChangeListItem[]> {\n\n const all = await this.getChangeStatus();\n\n return all.filter(\n (cs) => !cs.orphaned && (cs.status === 'pending' || cs.status === 'reverted'),\n );\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Secrets\n // ─────────────────────────────────────────────────────────\n\n /**\n * Get a config-scoped secret.\n *\n * @example\n * ```typescript\n * const apiKey = ctx.noorm.getSecret('API_KEY')\n * ```\n */\n getSecret(key: string): string | undefined {\n\n const state = getStateManager(this.#state.projectRoot);\n const value = state.getSecret(this.#state.config.name, key);\n\n return value ?? undefined;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Locks\n // ─────────────────────────────────────────────────────────\n\n /**\n * Acquire a database lock.\n *\n * @example\n * ```typescript\n * const lock = await ctx.noorm.acquireLock({ timeout: 60000 })\n * ```\n */\n async acquireLock(options?: LockOptions): Promise<Lock> {\n\n const lockManager = getLockManager();\n const identityStr = formatIdentity(this.#state.identity);\n\n return lockManager.acquire(\n this.#kysely as unknown as Kysely<NoormDatabase>,\n this.#state.config.name,\n identityStr,\n { ...options, dialect: this.#state.config.connection.dialect },\n );\n\n }\n\n /**\n * Release the current lock.\n *\n * @example\n * ```typescript\n * await ctx.noorm.releaseLock()\n * ```\n */\n async releaseLock(): Promise<void> {\n\n const lockManager = getLockManager();\n const identityStr = formatIdentity(this.#state.identity);\n\n await lockManager.release(\n this.#kysely as unknown as Kysely<NoormDatabase>,\n this.#state.config.name,\n identityStr,\n );\n\n }\n\n /**\n * Get current lock status.\n *\n * @example\n * ```typescript\n * const status = await ctx.noorm.getLockStatus()\n * ```\n */\n async getLockStatus(): Promise<LockStatus> {\n\n const lockManager = getLockManager();\n\n return lockManager.status(\n this.#kysely as unknown as Kysely<NoormDatabase>,\n this.#state.config.name,\n this.#state.config.connection.dialect,\n );\n\n }\n\n /**\n * Execute an operation with automatic lock acquisition and release.\n *\n * @example\n * ```typescript\n * await ctx.noorm.withLock(async () => {\n * await ctx.noorm.build()\n * await ctx.noorm.fastForward()\n * })\n * ```\n */\n async withLock<T>(fn: () => Promise<T>, options?: LockOptions): Promise<T> {\n\n const lockManager = getLockManager();\n const identityStr = formatIdentity(this.#state.identity);\n\n return lockManager.withLock(\n this.#kysely as unknown as Kysely<NoormDatabase>,\n this.#state.config.name,\n identityStr,\n fn,\n { ...options, dialect: this.#state.config.connection.dialect },\n );\n\n }\n\n /**\n * Force release any database lock regardless of ownership.\n *\n * @example\n * ```typescript\n * await ctx.noorm.forceReleaseLock()\n * ```\n */\n async forceReleaseLock(): Promise<boolean> {\n\n const lockManager = getLockManager();\n\n return lockManager.forceRelease(\n this.#kysely as unknown as Kysely<NoormDatabase>,\n this.#state.config.name,\n );\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Templates\n // ─────────────────────────────────────────────────────────\n\n /**\n * Render a template file without executing.\n *\n * @example\n * ```typescript\n * const result = await ctx.noorm.renderTemplate('sql/001_users.sql.tmpl')\n * ```\n */\n async renderTemplate(filepath: string): Promise<TemplateResult> {\n\n const absolutePath = path.isAbsolute(filepath)\n ? filepath\n : path.join(this.#state.projectRoot, filepath);\n\n const state = getStateManager(this.#state.projectRoot);\n\n return processFile(absolutePath, {\n projectRoot: this.#state.projectRoot,\n config: this.#state.config as unknown as Record<string, unknown>,\n secrets: state.getAllSecrets(this.#state.config.name),\n globalSecrets: state.getAllGlobalSecrets(),\n });\n\n }\n\n // ─────────────────────────────────────────────────────────\n // History\n // ─────────────────────────────────────────────────────────\n\n /**\n * Get execution history.\n *\n * @example\n * ```typescript\n * const history = await ctx.noorm.getHistory(10)\n * ```\n */\n async getHistory(limit?: number): Promise<ChangeHistoryRecord[]> {\n\n return this.#getChangeManager().getHistory(undefined, limit);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Utilities\n // ─────────────────────────────────────────────────────────\n\n /**\n * Compute SHA-256 checksum for a file.\n *\n * @example\n * ```typescript\n * const checksum = await ctx.noorm.computeChecksum('sql/001_users.sql')\n * ```\n */\n async computeChecksum(filepath: string): Promise<string> {\n\n const absolutePath = path.isAbsolute(filepath)\n ? filepath\n : path.join(this.#state.projectRoot, filepath);\n\n return coreComputeChecksum(absolutePath);\n\n }\n\n /**\n * Tests if the connection can be established.\n *\n * @example\n * ```typescript\n * const result = await ctx.noorm.testConnection()\n * ```\n */\n async testConnection(): Promise<{ ok: boolean; error?: string }> {\n\n return coreTestConnection(this.#state.config.connection);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Transfer\n // ─────────────────────────────────────────────────────────\n\n /**\n * Transfer data from this context's database to a destination context.\n *\n * Both contexts must be connected. Uses each context's config for\n * connection management.\n *\n * @example\n * ```typescript\n * const [result, err] = await source.noorm.transferTo(dest, {\n * tables: ['users', 'posts'],\n * onConflict: 'skip',\n * })\n * ```\n */\n async transferTo(\n destConfig: Config,\n options?: TransferOptions,\n ): Promise<[TransferResult | null, Error | null]> {\n\n return transferData(this.#state.config, destConfig, options);\n\n }\n\n /**\n * Generate a transfer plan without executing.\n *\n * @example\n * ```typescript\n * const [plan, err] = await source.noorm.transferPlan(destConfig)\n * ```\n */\n async transferPlan(\n destConfig: Config,\n options?: TransferOptions,\n ): Promise<[TransferPlan | null, Error | null]> {\n\n return getTransferPlan(this.#state.config, destConfig, options);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // DT File Operations\n // ─────────────────────────────────────────────────────────\n\n /**\n * Export a table to a .dt file.\n *\n * @example\n * ```typescript\n * const [result, err] = await ctx.noorm.exportTable('users', './exports/users.dtz')\n * ```\n */\n async exportTable(\n tableName: string,\n filepath: string,\n options?: ExportOptions,\n ): Promise<[{ rowsWritten: number; bytesWritten: number } | null, Error | null]> {\n\n return coreExportTable({\n db: this.#kysely,\n dialect: this.#dialect,\n tableName,\n filepath,\n schema: options?.schema,\n passphrase: options?.passphrase,\n batchSize: options?.batchSize,\n });\n\n }\n\n /**\n * Import a .dt file into the connected database.\n *\n * @example\n * ```typescript\n * const [result, err] = await ctx.noorm.importFile('./exports/users.dtz', {\n * onConflict: 'skip',\n * })\n * ```\n */\n async importFile(\n filepath: string,\n options?: ImportOptions,\n ): Promise<[{ rowsImported: number; rowsSkipped: number } | null, Error | null]> {\n\n return importDtFile({\n filepath,\n db: this.#kysely,\n dialect: this.#dialect,\n passphrase: options?.passphrase,\n batchSize: options?.batchSize,\n onConflict: options?.onConflict,\n truncate: options?.truncate,\n });\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Private Helpers\n // ─────────────────────────────────────────────────────────\n\n #createRunContext(): RunContext {\n\n const state = getStateManager(this.#state.projectRoot);\n\n return {\n db: this.#kysely as unknown as Kysely<NoormDatabase>,\n configName: this.#state.config.name,\n identity: this.#state.identity,\n projectRoot: this.#state.projectRoot,\n config: this.#state.config as unknown as Record<string, unknown>,\n secrets: state.getAllSecrets(this.#state.config.name),\n globalSecrets: state.getAllGlobalSecrets(),\n };\n\n }\n\n #createChangeContext(): ChangeContext {\n\n const state = getStateManager(this.#state.projectRoot);\n\n return {\n db: this.#kysely as unknown as Kysely<NoormDatabase>,\n configName: this.#state.config.name,\n identity: this.#state.identity,\n projectRoot: this.#state.projectRoot,\n changesDir: path.join(this.#state.projectRoot, this.#state.config.paths.changes),\n sqlDir: path.join(this.#state.projectRoot, this.#state.config.paths.sql),\n config: this.#state.config as unknown as Record<string, unknown>,\n secrets: state.getAllSecrets(this.#state.config.name),\n globalSecrets: state.getAllGlobalSecrets(),\n };\n\n }\n\n #getChangeManager(): ChangeManager {\n\n if (!this.#state.changeManager) {\n\n this.#state.changeManager = new ChangeManager(this.#createChangeContext());\n\n }\n\n return this.#state.changeManager;\n\n }\n\n}\n","/**\n * SDK Context Implementation.\n *\n * The Context class provides SQL-focused programmatic access to the\n * database. Noorm-specific operations (schema, changes, locks, etc.)\n * live behind the ctx.noorm namespace via NoormOps.\n */\nimport type { Kysely, Transaction } from 'kysely';\n\nimport type { Dialect } from '../core/connection/index.js';\nimport type { Config } from '../core/config/types.js';\nimport type { Settings } from '../core/settings/index.js';\nimport type { Identity } from '../core/identity/index.js';\nimport { createConnection } from '../core/connection/index.js';\n\nimport { buildProcCall, buildFuncCall } from './sql.js';\nimport { NoormOps } from './noorm-ops.js';\nimport type { ContextState } from './state.js';\nimport type { CreateContextOptions } from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Context Class\n// ─────────────────────────────────────────────────────────────\n\n/**\n * SDK Context implementation.\n *\n * Provides SQL-focused programmatic access to the database.\n * Noorm management operations are accessible via ctx.noorm.\n *\n * @example\n * ```typescript\n * const ctx = await createContext({ config: 'dev' })\n * await ctx.connect()\n *\n * // Top-level — SQL focused\n * const users = await ctx.kysely\n * .selectFrom('users')\n * .selectAll()\n * .execute()\n *\n * // Noorm operations — under namespace\n * await ctx.noorm.build()\n * await ctx.noorm.fastForward()\n *\n * await ctx.disconnect()\n * ```\n */\nexport class Context<DB = unknown, Procs = object, Funcs = object> {\n\n #state: ContextState;\n #noorm: NoormOps | null = null;\n\n constructor(\n config: Config,\n settings: Settings,\n identity: Identity,\n options: CreateContextOptions,\n projectRoot: string,\n ) {\n\n this.#state = {\n connection: null,\n config,\n settings,\n identity,\n options,\n projectRoot,\n changeManager: null,\n };\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Read-only Properties\n // ─────────────────────────────────────────────────────────\n\n get dialect(): Dialect {\n\n return this.#state.config.connection.dialect;\n\n }\n\n get connected(): boolean {\n\n return this.#state.connection !== null;\n\n }\n\n get kysely(): Kysely<DB> {\n\n if (!this.#state.connection) {\n\n throw new Error('Not connected. Call connect() first.');\n\n }\n\n return this.#state.connection.db as Kysely<DB>;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Noorm Namespace\n // ─────────────────────────────────────────────────────────\n\n /**\n * Noorm management operations.\n *\n * Lazily instantiated on first access. Returns the same instance\n * on repeated access (singleton per Context).\n *\n * @example\n * ```typescript\n * await ctx.noorm.build()\n * await ctx.noorm.fastForward()\n * const tables = await ctx.noorm.listTables()\n * ```\n */\n get noorm(): NoormOps {\n\n if (!this.#noorm) {\n\n this.#noorm = new NoormOps(this.#state);\n\n }\n\n return this.#noorm;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async connect(): Promise<void> {\n\n if (this.#state.connection) return;\n\n this.#state.connection = await createConnection(\n this.#state.config.connection,\n this.#state.config.name,\n );\n\n }\n\n async disconnect(): Promise<void> {\n\n if (!this.#state.connection) return;\n\n await this.#state.connection.destroy();\n this.#state.connection = null;\n this.#state.changeManager = null;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Transactions\n // ─────────────────────────────────────────────────────────\n\n /**\n * Execute operations within a database transaction.\n *\n * The callback receives a full Kysely Transaction instance with\n * query builder, `sql` template literal, and all Kysely features.\n *\n * @example\n * ```typescript\n * await ctx.transaction(async (trx) => {\n * await trx\n * .updateTable('accounts')\n * .set({ balance: sql`balance - ${amount}` })\n * .where('id', '=', fromId)\n * .execute();\n * await trx\n * .updateTable('accounts')\n * .set({ balance: sql`balance + ${amount}` })\n * .where('id', '=', toId)\n * .execute();\n * });\n * ```\n */\n async transaction<T>(fn: (trx: Transaction<DB>) => Promise<T>): Promise<T> {\n\n return this.kysely.transaction().execute(fn);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Stored Procedures & Functions\n // ─────────────────────────────────────────────────────────\n\n /**\n * Call a stored procedure and return the result set.\n *\n * Generates dialect-specific SQL: EXEC (MSSQL), CALL (PG/MySQL).\n * Named params use dialect-appropriate syntax; MySQL falls back\n * to positional. SQLite throws — no procedure support.\n *\n * @example\n * ```typescript\n * // Named params\n * const users = await ctx.proc<User>('get_users', { department_id: 1 });\n *\n * // Positional params\n * await ctx.proc('simple_proc', [42, 'hello']);\n *\n * // No params\n * await ctx.proc('refresh_cache');\n * ```\n */\n async proc<T = unknown, N extends keyof Procs & string = keyof Procs & string>(\n name: N,\n ...args: Procs[N] extends void ? [] : [params: Procs[N]]\n ): Promise<T[]> {\n\n if (this.dialect === 'sqlite') {\n\n throw new Error('SQLite does not support stored procedures.');\n\n }\n\n const params = args[0] as Record<string, unknown> | unknown[] | undefined;\n const query = buildProcCall<T>(this.dialect, name, params);\n const result = await query.execute(this.kysely);\n\n return (result.rows ?? []) as T[];\n\n }\n\n /**\n * Call a database function and return the scalar result.\n *\n * Generates SELECT name(...) AS column. Named params only on PG;\n * other dialects fall back to positional. SQLite throws.\n *\n * @example\n * ```typescript\n * // Named params + column alias\n * const result = await ctx.func<{ total: number }>('calc_total', { order_id: 42 }, 'total');\n *\n * // Positional params + column alias\n * const sum = await ctx.func<{ result: number }>('add_numbers', [1, 2], 'result');\n *\n * // No params — just column alias\n * const ver = await ctx.func<{ v: string }>('get_version', 'v');\n * ```\n */\n async func<T = unknown, N extends keyof Funcs & string = keyof Funcs & string>(\n name: N,\n ...args: Funcs[N] extends void ? [column: string] : [params: Funcs[N], column: string]\n ): Promise<T> {\n\n if (this.dialect === 'sqlite') {\n\n throw new Error('SQLite does not support database function calls.');\n\n }\n\n // Extract params and column from rest args\n const hasParams = !(args.length === 1 && typeof args[0] === 'string');\n const params = hasParams ? args[0] as Record<string, unknown> | unknown[] : undefined;\n const column = (hasParams ? args[1] : args[0]) as string;\n\n const query = buildFuncCall<T>(this.dialect, name, column, params);\n const result = await query.execute(this.kysely);\n\n return (result.rows?.[0] ?? null) as T;\n\n }\n\n}\n","/**\n * noorm SDK\n *\n * Programmatic access to noorm-managed databases.\n *\n * @example\n * ```typescript\n * import { createContext } from 'noorm/sdk'\n *\n * const ctx = await createContext<MyDatabase>({ config: 'dev' })\n * await ctx.connect()\n *\n * // Type-safe queries via Kysely\n * const users = await ctx.kysely\n * .selectFrom('users')\n * .selectAll()\n * .execute()\n *\n * // Run SQL files\n * await ctx.runFile('./seeds/users.sql')\n *\n * // Apply changes\n * await ctx.fastForward()\n *\n * await ctx.disconnect()\n * ```\n */\nimport { initState, getStateManager } from '../core/state/index.js';\nimport { getSettingsManager, type SettingsManager } from '../core/settings/index.js';\nimport { getIdentityForConfig } from '../core/identity/index.js';\nimport { resolveConfig, SettingsProvider } from '../core/config/resolver.js';\n\nimport { Context } from './context.js';\nimport { checkRequireTest } from './guards.js';\nimport type { CreateContextOptions } from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Adapt SettingsManager to SettingsProvider interface.\n *\n * The resolver uses a minimal interface to avoid circular deps.\n */\nfunction toSettingsProvider(manager: SettingsManager): SettingsProvider {\n\n return new SettingsProvider(manager);\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Factory Function\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create an SDK context for programmatic database access.\n *\n * Configuration is resolved using the full priority chain:\n * defaults <- stage <- stored <- env <- flags\n *\n * This enables:\n * - ENV var overrides (`NOORM_*`) for stored configs\n * - Env-only mode (no stored config) for CI/CD\n *\n * @param options - Context creation options\n * @returns Unconnected context (call connect() to use)\n *\n * @example\n * ```typescript\n * // Basic usage with stored config\n * const ctx = await createContext({ config: 'dev' })\n * await ctx.connect()\n *\n * // Require test database for safety in tests\n * const ctx = await createContext({\n * config: 'test',\n * requireTest: true,\n * })\n *\n * // Allow destructive ops on protected config\n * const ctx = await createContext({\n * config: 'staging',\n * allowProtected: true,\n * })\n *\n * // Env-only mode (CI/CD) - no stored config needed\n * // Requires NOORM_CONNECTION_DIALECT and NOORM_CONNECTION_DATABASE\n * const ctx = await createContext()\n * ```\n */\nexport async function createContext<DB = unknown, Procs = object, Funcs = object>(\n options: CreateContextOptions = {},\n): Promise<Context<DB, Procs, Funcs>> {\n\n // Resolve project root\n const projectRoot = options.projectRoot ?? process.cwd();\n\n // Initialize state (may have no configs in CI)\n await initState(projectRoot);\n const state = getStateManager(projectRoot);\n\n // Load settings (for stage defaults)\n const settingsManager = getSettingsManager(projectRoot);\n await settingsManager.load();\n const settings = settingsManager.settings;\n\n // Use resolver - applies full priority chain:\n // defaults <- stage <- stored <- env <- flags\n const config = resolveConfig(state, {\n name: options.config,\n stage: options.stage,\n settings: toSettingsProvider(settingsManager),\n });\n\n if (!config) {\n\n throw new Error(\n options.config\n ? `Config \"${options.config}\" not found`\n : 'No config available. Either:\\n' +\n ' - Pass { config: \"name\" } to use a stored config\\n' +\n ' - Set NOORM_CONFIG env var\\n' +\n ' - Set NOORM_CONNECTION_DIALECT and NOORM_CONNECTION_DATABASE for env-only mode',\n );\n\n }\n\n // Safety guards\n checkRequireTest(config, options);\n\n // Resolve identity (respecting config override if set)\n const identity = getIdentityForConfig(config);\n\n return new Context<DB, Procs, Funcs>(config, settings, identity, options, projectRoot);\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Re-exports\n// ─────────────────────────────────────────────────────────────\n\nexport { Context } from './context.js';\nexport { NoormOps } from './noorm-ops.js';\n\n// Types\nexport type {\n CreateContextOptions,\n BuildOptions,\n ExportOptions,\n ImportOptions,\n} from './types.js';\n\n// Guards (errors for catching)\nexport { RequireTestError, ProtectedConfigError } from './guards.js';\n\n// Re-export observer types for event subscriptions\nexport type { NoormEvents, NoormEventNames } from '../core/observer.js';\n\n// Re-export commonly needed types\nexport type { Config } from '../core/config/types.js';\nexport type { Settings } from '../core/settings/index.js';\nexport type { Identity } from '../core/identity/index.js';\nexport type { Dialect } from '../core/connection/index.js';\nexport type {\n TableSummary,\n TableDetail,\n ExploreOverview,\n} from '../core/explore/index.js';\nexport type { TruncateResult, TeardownResult } from '../core/teardown/index.js';\nexport type { BatchResult, FileResult, RunOptions } from '../core/runner/index.js';\nexport type {\n ChangeResult,\n BatchChangeResult,\n ChangeListItem,\n ChangeOptions,\n ChangeHistoryRecord,\n} from '../core/change/index.js';\n\n// Lock types\nexport type { Lock, LockStatus, LockOptions } from '../core/lock/index.js';\nexport { LockAcquireError, LockExpiredError } from '../core/lock/index.js';\n\n// Template types\nexport type { ProcessResult as TemplateResult } from '../core/template/index.js';\n\n// Transfer types\nexport type {\n TransferOptions,\n TransferPlan,\n TransferTablePlan,\n TransferResult,\n TransferTableResult,\n ConflictStrategy,\n} from '../core/transfer/index.js';\n"]}
|