@noormdev/sdk 1.0.0-alpha.5 → 1.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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/connection/manager.ts","../../../src/core/connection/factory.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/index.ts","../../../src/core/config/schema.ts","../../../src/core/config/index.ts","../../../src/core/config/resolver.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/sdk/guards.ts","../../../src/sdk/context.ts","../../../src/sdk/index.ts"],"names":["randomBytes","createCipheriv","createDecipheriv","require","join","attempt","attemptSync","path","fileExists","readFile","parseYaml","mkdir","stringifyYaml","writeFile","instance","conn","err","resolveIdentity","DialectSchema","z","PortSchema","envConfig","merge","sql","EXCLUDED_SCHEMAS","quote","qualifiedName","stat","readdir","access","fsConstants","data","durationMs","updateErr","fsWriteFile","isNoormTable","SQL_EXTENSIONS","loadAndRenderFile","executeFiles","results","executeDryRun","result","writeDryRunOutput","getDryRunOutputPath"],"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.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 * Uses createRequire since ESM JSON imports are experimental.\n */\nimport { createRequire } from 'module';\n\nconst require = createRequire(import.meta.url);\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 const pkg = require('../../../package.json') as { version: string };\n\n return pkg.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';\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/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/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 * 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 * 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';\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 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 * 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\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\nexport type NoormIdentity = Selectable<NoormIdentitiesTable>;\nexport type NewNoormIdentity = Insertable<NoormIdentitiesTable>;\nexport type NoormIdentityUpdate = Updateable<NoormIdentitiesTable>;\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}\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 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 type { CryptoIdentity, Identity, IdentityOptions } from './types.js';\nimport { resolveIdentity as resolve } from './resolver.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// 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","/**\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} 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 * Check if a config is complete and usable.\n *\n * A config is complete when all required secrets (from its stage) are set.\n * Also checks for stage constraint violations.\n *\n * @example\n * ```typescript\n * const check = checkConfigCompleteness(config, state, settings)\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 stageName?: string,\n): CompletenessCheck {\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\n const existingSecrets = state.listSecrets(config.name);\n\n for (const secret of stage.secrets ?? []) {\n\n const isRequired = secret.required !== false; // Default to true\n if (isRequired && !existingSecrets.includes(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 * 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 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 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} 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 * @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): 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(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 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// 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 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 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 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 * 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 * SDK Context Implementation.\n *\n * The Context class provides programmatic access to all noorm operations.\n * It wraps core modules and provides a clean API for SDK users.\n */\nimport path from 'node:path';\n\nimport { sql, type Kysely } from 'kysely';\n\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 { ConnectionResult, Dialect } from '../core/connection/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 { createConnection, testConnection as coreTestConnection } from '../core/connection/index.js';\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';\n\nimport { checkProtectedConfig } from './guards.js';\nimport type {\n CreateContextOptions,\n ExecuteResult,\n TransactionContext,\n BuildOptions,\n} from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Context Class\n// ─────────────────────────────────────────────────────────────\n\n/**\n * SDK Context implementation.\n *\n * Provides programmatic access to all noorm operations.\n *\n * @example\n * ```typescript\n * const ctx = await createContext({ config: 'dev' })\n * await ctx.connect()\n *\n * // Run queries\n * const users = await ctx.query('SELECT * FROM users')\n *\n * // Clean disconnect\n * await ctx.disconnect()\n * ```\n */\nexport class Context<DB = unknown> {\n\n #connection: ConnectionResult | null = null;\n #config: Config;\n #settings: Settings;\n #identity: Identity;\n #options: CreateContextOptions;\n #projectRoot: string;\n #changeManager: ChangeManager | null = null;\n\n constructor(\n config: Config,\n settings: Settings,\n identity: Identity,\n options: CreateContextOptions,\n projectRoot: string,\n ) {\n\n this.#config = config;\n this.#settings = settings;\n this.#identity = identity;\n this.#options = options;\n this.#projectRoot = projectRoot;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Read-only Properties\n // ─────────────────────────────────────────────────────────\n\n get config(): Config {\n\n return this.#config;\n\n }\n\n get settings(): Settings {\n\n return this.#settings;\n\n }\n\n get identity(): Identity {\n\n return this.#identity;\n\n }\n\n get dialect(): Dialect {\n\n return this.#config.connection.dialect;\n\n }\n\n get connected(): boolean {\n\n return this.#connection !== null;\n\n }\n\n get observer() {\n\n return observer;\n\n }\n\n get kysely(): Kysely<DB> {\n\n if (!this.#connection) {\n\n throw new Error('Not connected. Call connect() first.');\n\n }\n\n return this.#connection.db as Kysely<DB>;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async connect(): Promise<void> {\n\n if (this.#connection) return;\n\n this.#connection = await createConnection(\n this.#config.connection,\n this.#config.name,\n );\n\n }\n\n async disconnect(): Promise<void> {\n\n if (!this.#connection) return;\n\n await this.#connection.destroy();\n this.#connection = null;\n this.#changeManager = null;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // SQL Execution\n // ─────────────────────────────────────────────────────────\n\n async query<T = Record<string, unknown>>(\n sqlStr: string,\n _params?: unknown[],\n ): Promise<T[]> {\n\n // Note: Kysely's sql.raw() executes raw SQL without parameter binding.\n // For parameterized queries, users should use ctx.kysely directly with\n // Kysely's type-safe query builder or sql tagged template literals.\n const db = this.kysely;\n const result = await sql.raw<T>(sqlStr).execute(db);\n\n return (result.rows ?? []) as T[];\n\n }\n\n async execute(sqlStr: string, _params?: unknown[]): Promise<ExecuteResult> {\n\n // Note: Kysely's sql.raw() executes raw SQL without parameter binding.\n // For parameterized queries, users should use ctx.kysely directly.\n const db = this.kysely;\n const result = await sql.raw(sqlStr).execute(db);\n\n return {\n rowsAffected: result.numAffectedRows\n ? Number(result.numAffectedRows)\n : undefined,\n };\n\n }\n\n async transaction<T>(fn: (tx: TransactionContext) => Promise<T>): Promise<T> {\n\n const db = this.kysely;\n\n return db.transaction().execute(async (trx) => {\n\n const tx: TransactionContext = {\n async query<R>(s: string, _p?: unknown[]): Promise<R[]> {\n\n const r = await sql.raw<R>(s).execute(trx);\n\n return (r.rows ?? []) as R[];\n\n },\n async execute(s: string, _p?: unknown[]): Promise<ExecuteResult> {\n\n const r = await sql.raw(s).execute(trx);\n\n return {\n rowsAffected: r.numAffectedRows\n ? Number(r.numAffectedRows)\n : undefined,\n };\n\n },\n };\n\n return fn(tx);\n\n });\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Explore\n // ─────────────────────────────────────────────────────────\n\n async listTables(): Promise<TableSummary[]> {\n\n return fetchList(this.kysely as Kysely<unknown>, this.dialect, 'tables');\n\n }\n\n async describeTable(name: string, schema?: string): Promise<TableDetail | null> {\n\n return fetchDetail(this.kysely as Kysely<unknown>, this.dialect, 'tables', name, schema);\n\n }\n\n async overview(): Promise<ExploreOverview> {\n\n return fetchOverview(this.kysely as Kysely<unknown>, this.dialect);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Schema Operations\n // ─────────────────────────────────────────────────────────\n\n async truncate(): Promise<TruncateResult> {\n\n checkProtectedConfig(this.#config, 'truncate', this.#options);\n\n return truncateData(this.kysely as Kysely<unknown>, this.dialect);\n\n }\n\n async teardown(): Promise<TeardownResult> {\n\n checkProtectedConfig(this.#config, 'teardown', this.#options);\n\n return teardownSchema(this.kysely as Kysely<unknown>, this.dialect, {\n configName: this.#config.name,\n executedBy: formatIdentity(this.#identity),\n });\n\n }\n\n async build(options?: BuildOptions): Promise<BatchResult> {\n\n const runContext = this.#createRunContext();\n const sqlPath = path.join(\n this.#projectRoot,\n this.#config.paths.sql,\n );\n\n return runBuild(runContext, sqlPath, { force: options?.force });\n\n }\n\n async reset(): Promise<void> {\n\n checkProtectedConfig(this.#config, 'reset', this.#options);\n\n await this.teardown();\n await this.build({ force: true });\n\n }\n\n // ─────────────────────────────────────────────────────────\n // File Runner\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.#projectRoot, filepath);\n\n return coreRunFile(runContext, absolutePath, options);\n\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.#projectRoot, fp),\n );\n\n return coreRunFiles(runContext, absolutePaths, options);\n\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.#projectRoot, dirpath);\n\n return coreRunDir(runContext, absolutePath, options);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Changes\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 async revertChange(\n name: string,\n options?: ChangeOptions,\n ): Promise<ChangeResult> {\n\n return this.#getChangeManager().revert(name, options);\n\n }\n\n async fastForward(): Promise<BatchChangeResult> {\n\n return this.#getChangeManager().ff();\n\n }\n\n async getChangeStatus(): Promise<ChangeListItem[]> {\n\n return this.#getChangeManager().list();\n\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 getSecret(key: string): string | undefined {\n\n const state = getStateManager(this.#projectRoot);\n const value = state.getSecret(this.#config.name, key);\n\n return value ?? undefined;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Locks\n // ─────────────────────────────────────────────────────────\n\n async acquireLock(options?: LockOptions): Promise<Lock> {\n\n const lockManager = getLockManager();\n const identityStr = formatIdentity(this.#identity);\n\n return lockManager.acquire(\n this.kysely as unknown as Kysely<NoormDatabase>,\n this.#config.name,\n identityStr,\n { ...options, dialect: this.#config.connection.dialect },\n );\n\n }\n\n async releaseLock(): Promise<void> {\n\n const lockManager = getLockManager();\n const identityStr = formatIdentity(this.#identity);\n\n await lockManager.release(\n this.kysely as unknown as Kysely<NoormDatabase>,\n this.#config.name,\n identityStr,\n );\n\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.#config.name,\n this.#config.connection.dialect,\n );\n\n }\n\n async withLock<T>(fn: () => Promise<T>, options?: LockOptions): Promise<T> {\n\n const lockManager = getLockManager();\n const identityStr = formatIdentity(this.#identity);\n\n return lockManager.withLock(\n this.kysely as unknown as Kysely<NoormDatabase>,\n this.#config.name,\n identityStr,\n fn,\n { ...options, dialect: this.#config.connection.dialect },\n );\n\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.#config.name,\n );\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Templates\n // ─────────────────────────────────────────────────────────\n\n async renderTemplate(filepath: string): Promise<TemplateResult> {\n\n const absolutePath = path.isAbsolute(filepath)\n ? filepath\n : path.join(this.#projectRoot, filepath);\n\n const state = getStateManager(this.#projectRoot);\n\n return processFile(absolutePath, {\n projectRoot: this.#projectRoot,\n config: this.#config as unknown as Record<string, unknown>,\n secrets: state.getAllSecrets(this.#config.name),\n globalSecrets: state.getAllGlobalSecrets(),\n });\n\n }\n\n // ─────────────────────────────────────────────────────────\n // History\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 async computeChecksum(filepath: string): Promise<string> {\n\n const absolutePath = path.isAbsolute(filepath)\n ? filepath\n : path.join(this.#projectRoot, filepath);\n\n return coreComputeChecksum(absolutePath);\n\n }\n\n async testConnection(): Promise<{ ok: boolean; error?: string }> {\n\n return coreTestConnection(this.#config.connection);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Private Helpers\n // ─────────────────────────────────────────────────────────\n\n #createRunContext(): RunContext {\n\n const state = getStateManager(this.#projectRoot);\n\n return {\n db: this.kysely as unknown as Kysely<NoormDatabase>,\n configName: this.#config.name,\n identity: this.#identity,\n projectRoot: this.#projectRoot,\n config: this.#config as unknown as Record<string, unknown>,\n secrets: state.getAllSecrets(this.#config.name),\n globalSecrets: state.getAllGlobalSecrets(),\n };\n\n }\n\n #createChangeContext(): ChangeContext {\n\n const state = getStateManager(this.#projectRoot);\n\n return {\n db: this.kysely as unknown as Kysely<NoormDatabase>,\n configName: this.#config.name,\n identity: this.#identity,\n projectRoot: this.#projectRoot,\n changesDir: path.join(this.#projectRoot, this.#config.paths.changes),\n sqlDir: path.join(this.#projectRoot, this.#config.paths.sql),\n config: this.#config as unknown as Record<string, unknown>,\n secrets: state.getAllSecrets(this.#config.name),\n globalSecrets: state.getAllGlobalSecrets(),\n };\n\n }\n\n #getChangeManager(): ChangeManager {\n\n if (!this.#changeManager) {\n\n this.#changeManager = new ChangeManager(this.#createChangeContext());\n\n }\n\n return this.#changeManager;\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({ config: 'dev' })\n * await ctx.connect()\n *\n * // Query the database\n * const users = await ctx.query<User>('SELECT * FROM users')\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>(\n options: CreateContextOptions = {},\n): Promise<Context<DB>> {\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>(config, settings, identity, options, projectRoot);\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Re-exports\n// ─────────────────────────────────────────────────────────────\n\nexport { Context } from './context.js';\n\n// Types\nexport type {\n CreateContextOptions,\n ExecuteResult,\n TransactionContext,\n BuildOptions,\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"]}
|
|
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/connection/manager.ts","../../../src/core/connection/factory.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/index.ts","../../../src/core/config/schema.ts","../../../src/core/config/index.ts","../../../src/core/config/resolver.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/sdk/guards.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","resolveIdentity","DialectSchema","z","PortSchema","envConfig","merge","sql","EXCLUDED_SCHEMAS","quote","qualifiedName","stat","readdir","access","fsConstants","data","durationMs","updateErr","fsWriteFile","isNoormTable","SQL_EXTENSIONS","loadAndRenderFile","executeFiles","results","executeDryRun","result","writeDryRunOutput","getDryRunOutputPath"],"mappings":";;;;;;;;;;;;;;AA+BA,IAAM,UAAA,GAAa,IAAA,CAAK,OAAA,EAAQ,EAAG,QAAQ,CAAA;AAG3C,IAAM,gBAAA,GAAmB,IAAA,CAAK,UAAA,EAAY,cAAc,CAAA;AAGhC,IAAA,CAAK,UAAA,EAAY,cAAc;AASxB,IAAA,CAAK,UAAA,EAAY,eAAe;AA4K/D,eAAsB,cAAA,GAAyC;AAE3D,EAAA,MAAM,CAAC,OAAA,EAAS,GAAG,CAAA,GAAI,MAAM,OAAA,CAAQ,MAAM,QAAA,CAAS,gBAAA,EAAkB,EAAE,QAAA,EAAU,MAAA,EAAQ,CAAC,CAAA;AAE3F,EAAA,IAAI,GAAA,EAAK;AAGL,IAAA,IAAK,GAAA,CAA8B,SAAS,QAAA,EAAU;AAElD,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,4BAAA,EAA+B,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAA,EAEhE;AAEA,EAAA,OAAO,QAAQ,IAAA,EAAK;AAExB;ACMO,SAAS,eAAe,UAAA,EAA4B;AAEvD,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,IAAA,CAAK,UAAA,EAAY,KAAK,CAAA;AAEtD,EAAA,OAAO,MAAA,CAAO,IAAA;AAAA,IACV,QAAA;AAAA,MACI,QAAA;AAAA,MACA,gBAAA;AAAA,MACA,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA;AAAA,MACd,wBAAA;AAAA,MACA;AAAA;AACJ,GACJ;AAEJ;;;ACrPA,IAAM,SAAA,GAAY,aAAA;AAClB,IAAM,SAAA,GAAY,EAAA;AAClB,IAAM,eAAA,GAAkB,EAAA;AAmBjB,SAAS,OAAA,CAAQ,WAAmB,UAAA,EAAsC;AAE7E,EAAA,MAAM,GAAA,GAAM,eAAe,UAAU,CAAA;AACrC,EAAA,MAAM,EAAA,GAAKA,YAAY,SAAS,CAAA;AAEhC,EAAA,MAAM,MAAA,GAASC,cAAAA,CAAe,SAAA,EAAW,GAAA,EAAK,EAAA,EAAI;AAAA,IAC9C,aAAA,EAAe;AAAA,GAClB,CAAA;AAED,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,CAAC,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,MAAM,CAAA,EAAG,MAAA,CAAO,KAAA,EAAO,CAAC,CAAA;AAEnF,EAAA,MAAM,OAAA,GAAU,OAAO,UAAA,EAAW;AAElC,EAAA,OAAO;AAAA,IACH,SAAA,EAAW,SAAA;AAAA,IACX,EAAA,EAAI,EAAA,CAAG,QAAA,CAAS,QAAQ,CAAA;AAAA,IACxB,OAAA,EAAS,OAAA,CAAQ,QAAA,CAAS,QAAQ,CAAA;AAAA,IAClC,UAAA,EAAY,UAAA,CAAW,QAAA,CAAS,QAAQ;AAAA,GAC5C;AAEJ;AAYO,SAAS,OAAA,CAAQ,SAA2B,UAAA,EAA4B;AAE3E,EAAA,IAAI,OAAA,CAAQ,cAAc,SAAA,EAAW;AAEjC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,OAAA,CAAQ,SAAS,CAAA,CAAE,CAAA;AAAA,EAEjE;AAEA,EAAA,MAAM,GAAA,GAAM,eAAe,UAAU,CAAA;AACrC,EAAA,MAAM,EAAA,GAAK,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,IAAI,QAAQ,CAAA;AAC3C,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,SAAS,QAAQ,CAAA;AACrD,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,YAAY,QAAQ,CAAA;AAE3D,EAAA,MAAM,QAAA,GAAWC,gBAAAA,CAAiB,SAAA,EAAW,GAAA,EAAK,EAAA,EAAI;AAAA,IAClD,aAAA,EAAe;AAAA,GAClB,CAAA;AAED,EAAA,QAAA,CAAS,WAAW,OAAO,CAAA;AAE3B,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,MAAA,CAAO,CAAC,QAAA,CAAS,MAAA,CAAO,UAAU,CAAA,EAAG,QAAA,CAAS,KAAA,EAAO,CAAC,CAAA;AAE/E,EAAA,OAAO,SAAA,CAAU,SAAS,MAAM,CAAA;AAEpC;;;AClBO,SAAS,iBAAiB,OAAA,EAAwB;AAErD,EAAA,OAAO;AAAA,IACH,OAAA;AAAA,IACA,YAAY,EAAC;AAAA,IACb,YAAA,EAAc,IAAA;AAAA,IACd,SAAS,EAAC;AAAA,IACV,SAAS,EAAC;AAAA,IACV,eAAe;AAAC,GACpB;AAEJ;;;ACvDO,SAAS,YAAA,CAAa,OAAgB,cAAA,EAA+B;AAExE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,EAAM;AAE7C,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EAE3D;AAEA,EAAA,MAAM,GAAA,GAAM,KAAA;AACZ,EAAA,MAAM,eAAA,GAAkB,IAAI,SAAS,CAAA;AAIrC,EAAA,MAAM,QAAA,GAAkB;AAAA,IACpB,OAAA,EAAS,cAAA;AAAA,IACT,UAAA,EAAa,GAAA,CAAI,YAAY,CAAA,IAAmC,EAAC;AAAA,IACjE,YAAA,EAAe,GAAA,CAAI,cAAc,CAAA,IAAuB,IAAA;AAAA,IACxD,OAAA,EAAU,GAAA,CAAI,SAAS,CAAA,IAAqD,EAAC;AAAA,IAC7E,OAAA,EAAU,GAAA,CAAI,SAAS,CAAA,IAAgD,EAAC;AAAA,IACxE,aAAA,EAAgB,GAAA,CAAI,eAAe,CAAA,IAAgC;AAAC,GACxE;AAEA,EAAA,IAAI,oBAAoB,cAAA,EAAgB;AAEpC,IAAA,QAAA,CAAS,KAAK,gBAAA,EAAkB;AAAA,MAC5B,MAAM,eAAA,IAAmB,SAAA;AAAA,MACzB,EAAA,EAAI;AAAA,KACP,CAAA;AAAA,EAEL;AAEA,EAAA,OAAO,QAAA;AAEX;AAKO,SAAS,cAAA,CAAe,OAAgB,cAAA,EAAiC;AAE5E,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,MAAM,OAAO,IAAA;AAExD,EAAA,MAAM,GAAA,GAAM,KAAA;AAGZ,EAAA,IAAI,GAAA,CAAI,SAAS,CAAA,KAAM,cAAA,EAAgB,OAAO,IAAA;AAG9C,EAAA,IAAI,EAAE,eAAA,IAAmB,GAAA,CAAA,EAAM,OAAO,IAAA;AACtC,EAAA,IAAI,EAAE,UAAA,IAAc,GAAA,CAAA,EAAM,OAAO,IAAA;AACjC,EAAA,IAAI,EAAE,YAAA,IAAgB,GAAA,CAAA,EAAM,OAAO,IAAA;AAEnC,EAAA,OAAO,KAAA;AAEX;;;ACrEA,IAAM,OAAA,GAAU,OAAO,eAAA,KAAoB,WAAA,GACrC,eAAA,GACA,WAAA;AAQC,SAAS,iBAAA,GAA4B;AAExC,EAAA,OAAO,OAAA;AAEX;;;ACJA,IAAM,iBAAA,GAAoB,QAAA;AAC1B,IAAM,kBAAA,GAAqB,WAAA;AAwCpB,IAAM,eAAN,MAAmB;AAAA,EAOtB,WAAA,CACqB,WAAA,EACjB,OAAA,GAA+B,EAAC,EAClC;AAFmB,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAIjB,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,UAAA;AAC1B,IAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,iBAAA;AACrC,IAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,kBAAA;AACvC,IAAA,IAAA,CAAK,SAAA,GAAYC,IAAAA,CAAK,WAAA,EAAa,QAAA,EAAU,SAAS,CAAA;AAAA,EAE1D;AAAA,EAfQ,KAAA,GAAsB,IAAA;AAAA,EACtB,UAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBjB,MAAM,IAAA,GAAsB;AAExB,IAAA,IAAI,KAAK,MAAA,EAAQ;AAGjB,IAAA,IAAI,CAAC,KAAK,UAAA,EAAY;AAElB,MAAA,MAAM,CAAC,GAAG,CAAA,GAAI,MAAMC,OAAAA,CAAQ,MAAM,gBAAgB,CAAA;AAClD,MAAA,IAAI,GAAA,EAAK;AAEL,QAAA,IAAA,CAAK,UAAA,GAAa,GAAA;AAAA,MAEtB;AAAA,IAEJ;AAEA,IAAA,MAAM,iBAAiB,iBAAA,EAAkB;AAGzC,IAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,SAAS,CAAA,EAAG;AAE7B,MAAA,IAAA,CAAK,KAAA,GAAQ,iBAAiB,cAAc,CAAA;AAC5C,MAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,MAAA,QAAA,CAAS,KAAK,cAAA,EAAgB;AAAA,QAC1B,WAAA,EAAa,CAAA;AAAA,QACb,YAAA,EAAc,IAAA;AAAA,QACd,OAAA,EAAS;AAAA,OACZ,CAAA;AAED,MAAA;AAAA,IAEJ;AAGA,IAAA,IAAI,CAAC,KAAK,UAAA,EAAY;AAElB,MAAA,MAAM,IAAI,KAAA;AAAA,QACN;AAAA,OACJ;AAAA,IAEJ;AAEA,IAAA,MAAM,CAAC,GAAA,EAAK,OAAO,CAAA,GAAIC,WAAAA,CAAY,MAAM,YAAA,CAAa,IAAA,CAAK,SAAA,EAAW,MAAM,CAAC,CAAA;AAC7E,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAS,KAAA,EAAO,SAAS,CAAA;AAC1D,MAAA,MAAM,OAAA;AAAA,IAEV;AAEA,IAAA,MAAM,CAAC,SAAS,QAAQ,CAAA,GAAIA,YAAY,MAAM,IAAA,CAAK,KAAA,CAAM,GAAI,CAAqB,CAAA;AAClF,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAS,KAAA,EAAO,UAAU,CAAA;AAC3D,MAAA,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAAA,IAExE;AAEA,IAAA,MAAM,CAAC,SAAA,EAAW,UAAU,CAAA,GAAIA,WAAAA,CAAY,MAAM,OAAA,CAAQ,OAAA,EAAU,IAAA,CAAK,UAAW,CAAC,CAAA;AACrF,IAAA,IAAI,UAAA,EAAY;AAEZ,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAS,KAAA,EAAO,YAAY,CAAA;AAC7D,MAAA,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAAA,IAE3E;AAEA,IAAA,MAAM,CAAC,aAAa,aAAa,CAAA,GAAIA,YAAY,MAAM,IAAA,CAAK,KAAA,CAAM,SAAU,CAAY,CAAA;AACxF,IAAA,IAAI,aAAA,EAAe;AAEf,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAS,KAAA,EAAO,eAAe,CAAA;AAChE,MAAA,MAAM,IAAI,MAAM,kCAAkC,CAAA;AAAA,IAEtD;AAGA,IAAA,MAAM,WAAA,GAAc,cAAA,CAAe,WAAA,EAAa,cAAc,CAAA;AAC9D,IAAA,IAAA,CAAK,KAAA,GAAQ,YAAA,CAAa,WAAA,EAAa,cAAc,CAAA;AACrD,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAGd,IAAA,IAAI,WAAA,EAAa;AAEb,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IAEjB;AAEA,IAAA,QAAA,CAAS,KAAK,cAAA,EAAgB;AAAA,MAC1B,aAAa,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,CAAE,MAAA;AAAA,MAC7C,YAAA,EAAc,KAAK,KAAA,CAAM,YAAA;AAAA,MACzB,OAAA,EAAS,KAAK,KAAA,CAAM;AAAA,KACvB,CAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,gBAAA,GAAqC;AAEvC,IAAA,MAAM,CAAC,GAAG,CAAA,GAAI,MAAMD,OAAAA,CAAQ,MAAM,gBAAgB,CAAA;AAClD,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,IAAA,CAAK,UAAA,GAAa,GAAA;AAElB,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,OAAO,KAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,OAAA,GAAgB;AAEpB,IAAA,IAAI,CAAC,KAAK,UAAA,EAAY;AAElB,MAAA,MAAM,IAAI,KAAA;AAAA,QACN;AAAA,OACJ;AAAA,IAEJ;AAEA,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAA;AAClC,IAAA,IAAI,CAAC,UAAA,CAAW,GAAG,CAAA,EAAG;AAElB,MAAA,SAAA,CAAU,GAAA,EAAK,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAAA,IAEtC;AAEA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AACjC,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,IAAA,EAAM,IAAA,CAAK,UAAU,CAAA;AAE7C,IAAA,MAAM,GAAG,QAAQ,CAAA,GAAIC,WAAAA;AAAA,MAAY,MAC7B,cAAc,IAAA,CAAK,SAAA,EAAW,KAAK,SAAA,CAAU,OAAA,EAAS,IAAA,EAAM,CAAC,CAAC;AAAA,KAClE;AAEA,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,OAAA,EAAS,KAAA,EAAO,UAAU,CAAA;AAC3D,MAAA,MAAM,QAAA;AAAA,IAEV;AAEA,IAAA,QAAA,CAAS,KAAK,iBAAA,EAAmB;AAAA,MAC7B,WAAA,EAAa,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,CAAE;AAAA,KAC3C,CAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA,EAKQ,QAAA,GAAkB;AAEtB,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,CAAC,KAAK,KAAA,EAAO;AAE7B,MAAA,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAAA,IAEjE;AAEA,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EAEhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAU,IAAA,EAA6B;AAEnC,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA;AAAA,EAElC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAA,CAAU,IAAA,EAAc,MAAA,EAA+B;AAEzD,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,IAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AACjC,IAAA,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,GAAI,MAAA;AACtB,IAAA,IAAA,CAAK,OAAA,EAAQ;AAEb,IAAA,QAAA,CAAS,IAAA,CAAK,KAAA,GAAQ,gBAAA,GAAmB,gBAAA,EAAkB;AAAA,MACvD,IAAA;AAAA,MACA,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,MAAM;AAAA,KAC7B,CAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,IAAA,EAA6B;AAE5C,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,IAAA,OAAO,KAAA,CAAM,QAAQ,IAAI,CAAA;AACzB,IAAA,OAAO,KAAA,CAAM,QAAQ,IAAI,CAAA;AAEzB,IAAA,IAAI,KAAA,CAAM,iBAAiB,IAAA,EAAM;AAE7B,MAAA,KAAA,CAAM,YAAA,GAAe,IAAA;AAAA,IAEzB;AAEA,IAAA,IAAA,CAAK,OAAA,EAAQ;AACb,IAAA,QAAA,CAAS,IAAA,CAAK,gBAAA,EAAkB,EAAE,IAAA,EAAM,CAAA;AAAA,EAE5C;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAA+B;AAE3B,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,OAAO,CAAA,CAAE,IAAI,CAAC,CAAC,IAAA,EAAM,MAAM,CAAA,MAAO;AAAA,MAC1D,IAAA;AAAA,MACA,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,QAAA,EAAU,MAAM,YAAA,KAAiB,IAAA;AAAA,MACjC,OAAA,EAAS,OAAO,UAAA,CAAW,OAAA;AAAA,MAC3B,QAAA,EAAU,OAAO,UAAA,CAAW;AAAA,KAChC,CAAE,CAAA;AAAA,EAEN;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GAAiC;AAE7B,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,IAAA,IAAI,CAAC,KAAA,CAAM,YAAA,EAAc,OAAO,IAAA;AAEhC,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,YAAY,CAAA,IAAK,IAAA;AAAA,EAEhD;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAA,GAAqC;AAEjC,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,KAAA,CAAM,YAAA;AAAA,EAEjB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,IAAA,EAA6B;AAE/C,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AAEtB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,IAAI,CAAA,iBAAA,CAAmB,CAAA;AAAA,IAEtD;AAEA,IAAA,MAAM,WAAW,KAAA,CAAM,YAAA;AACvB,IAAA,KAAA,CAAM,YAAA,GAAe,IAAA;AACrB,IAAA,IAAA,CAAK,OAAA,EAAQ;AAEb,IAAA,QAAA,CAAS,IAAA,CAAK,kBAAA,EAAoB,EAAE,IAAA,EAAM,UAAU,CAAA;AAAA,EAExD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAA,CAAU,YAAoB,GAAA,EAA4B;AAEtD,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,GAAI,GAAG,CAAA,IAAK,IAAA;AAAA,EAE/C;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,UAAA,EAA4C;AAEtD,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,GAAI,EAAE,GAAG,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,EAAE,GAAI,EAAC;AAAA,EAE3E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAA,CAAU,UAAA,EAAoB,GAAA,EAAa,KAAA,EAA8B;AAE3E,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,EAAG;AAE5B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,UAAU,CAAA,iBAAA,CAAmB,CAAA;AAAA,IAE5D;AAEA,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,EAAG;AAE5B,MAAA,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,GAAI,EAAC;AAAA,IAEjC;AAEA,IAAA,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,CAAE,GAAG,CAAA,GAAI,KAAA;AACjC,IAAA,IAAA,CAAK,OAAA,EAAQ;AAEb,IAAA,QAAA,CAAS,IAAA,CAAK,YAAA,EAAc,EAAE,UAAA,EAAY,KAAK,CAAA;AAAA,EAEnD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAA,CAAa,UAAA,EAAoB,GAAA,EAA4B;AAE/D,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,EAAG;AAE3B,MAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,CAAE,GAAG,CAAA;AACpC,MAAA,IAAA,CAAK,OAAA,EAAQ;AAEb,MAAA,QAAA,CAAS,IAAA,CAAK,gBAAA,EAAkB,EAAE,UAAA,EAAY,KAAK,CAAA;AAAA,IAEvD;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,UAAA,EAA8B;AAEtC,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,OAAO,IAAA,CAAK,KAAA,CAAM,QAAQ,UAAU,CAAA,IAAK,EAAE,CAAA;AAAA,EAEtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,gBAAgB,GAAA,EAA4B;AAExC,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,KAAA,CAAM,aAAA,CAAc,GAAG,CAAA,IAAK,IAAA;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAA,GAA8C;AAE1C,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,EAAE,GAAG,KAAA,CAAM,aAAA,EAAc;AAAA,EAEpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,eAAA,CAAgB,GAAA,EAAa,KAAA,EAA8B;AAE7D,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,IAAA,KAAA,CAAM,aAAA,CAAc,GAAG,CAAA,GAAI,KAAA;AAC3B,IAAA,IAAA,CAAK,OAAA,EAAQ;AAEb,IAAA,QAAA,CAAS,IAAA,CAAK,mBAAA,EAAqB,EAAE,GAAA,EAAK,CAAA;AAAA,EAE9C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,GAAA,EAA4B;AAEjD,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,IAAI,GAAA,IAAO,MAAM,aAAA,EAAe;AAE5B,MAAA,OAAO,KAAA,CAAM,cAAc,GAAG,CAAA;AAC9B,MAAA,IAAA,CAAK,OAAA,EAAQ;AAEb,MAAA,QAAA,CAAS,IAAA,CAAK,uBAAA,EAAyB,EAAE,GAAA,EAAK,CAAA;AAAA,IAElD;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAA,GAA8B;AAE1B,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,aAAa,CAAA;AAAA,EAE1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAA,GAA2C;AAEvC,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,EAAE,GAAG,KAAA,CAAM,UAAA,EAAW;AAAA,EAEjC;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,YAAA,EAAwC;AAEjD,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,KAAA,CAAM,UAAA,CAAW,YAAY,CAAA,IAAK,IAAA;AAAA,EAE7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,sBAAsB,KAAA,EAA4B;AAE9C,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA,CAAE,OAAO,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,KAAU,KAAK,CAAA;AAAA,EAE1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAa,IAAA,EAAgC;AAE/C,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,IAAA,KAAA,CAAM,UAAA,CAAW,IAAA,CAAK,YAAY,CAAA,GAAI,IAAA;AACtC,IAAA,IAAA,CAAK,OAAA,EAAQ;AAEb,IAAA,QAAA,CAAS,KAAK,kBAAA,EAAoB;AAAA,MAC9B,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK;AAAA,KAChB,CAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,KAAA,EAAmC;AAEnD,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAEtB,MAAA,KAAA,CAAM,UAAA,CAAW,IAAA,CAAK,YAAY,CAAA,GAAI,IAAA;AAAA,IAE1C;AAEA,IAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,EAEjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAA,GAAqB;AAEjB,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,KAAA,CAAM,OAAA;AAAA,EAEjB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,GAAkB;AAEd,IAAA,OAAO,UAAA,CAAW,KAAK,SAAS,CAAA;AAAA,EAEpC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAAuB;AAEnB,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EAEhB;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GAAiC;AAE7B,IAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,SAAS,GAAG,OAAO,IAAA;AAExC,IAAA,OAAO,YAAA,CAAa,IAAA,CAAK,SAAA,EAAW,MAAM,CAAA;AAAA,EAE9C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,SAAA,EAAkC;AAEpD,IAAA,IAAI,CAAC,KAAK,UAAA,EAAY;AAElB,MAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,IAE3D;AAGA,IAAA,MAAM,CAAC,SAAS,QAAQ,CAAA,GAAIA,YAAY,MAAM,IAAA,CAAK,KAAA,CAAM,SAAS,CAAqB,CAAA;AACvF,IAAA,IAAI,UAAU,MAAM,QAAA;AAEpB,IAAA,MAAM,GAAG,UAAU,CAAA,GAAIA,WAAAA,CAAY,MAAM,OAAA,CAAQ,OAAA,EAAU,IAAA,CAAK,UAAW,CAAC,CAAA;AAC5E,IAAA,IAAI,YAAY,MAAM,UAAA;AAEtB,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAA;AAClC,IAAA,IAAI,CAAC,UAAA,CAAW,GAAG,CAAA,EAAG;AAElB,MAAA,SAAA,CAAU,GAAA,EAAK,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAAA,IAEtC;AAEA,IAAA,aAAA,CAAc,IAAA,CAAK,WAAW,SAAS,CAAA;AACvC,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,MAAM,KAAK,IAAA,EAAK;AAAA,EAEpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,UAAA,EAA0B;AAEpC,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EAEtB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAA,GAAyB;AAErB,IAAA,OAAO,CAAC,CAAC,IAAA,CAAK,UAAA;AAAA,EAElB;AAEJ,CAAA;;;AC1rBA,IAAI,QAAA,GAAgC,IAAA;AAW7B,SAAS,gBAAgB,WAAA,EAAoC;AAEhE,EAAA,IAAI,CAAC,QAAA,EAAU;AAEX,IAAA,MAAM,IAAA,GAAO,WAAA,IAAe,OAAA,CAAQ,GAAA,EAAI;AACxC,IAAA,QAAA,GAAW,IAAI,aAAa,IAAI,CAAA;AAAA,EAEpC;AAEA,EAAA,OAAO,QAAA;AAEX;AAWA,eAAsB,UAAU,WAAA,EAA6C;AAEzE,EAAA,MAAM,OAAA,GAAU,gBAAgB,WAAW,CAAA;AAC3C,EAAA,MAAM,QAAQ,IAAA,EAAK;AAEnB,EAAA,OAAO,OAAA;AAEX;ACtCA,IAAM,aAAA,GAAgB,EAAE,IAAA,CAAK,CAAC,YAAY,OAAA,EAAS,QAAA,EAAU,OAAO,CAAC,CAAA;AAKrE,IAAM,gBAAA,GAAmB,EAAE,IAAA,CAAK,CAAC,UAAU,UAAA,EAAY,SAAA,EAAW,mBAAmB,CAAC,CAAA;AAKtF,IAAM,uBAAuB,CAAA,CAAE,IAAA,CAAK,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;AAKvD,IAAM,cAAA,GAAiB,EAAE,IAAA,CAAK,CAAC,UAAU,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,SAAS,CAAC,CAAA;AAK5E,IAAM,UAAA,GAAa,CAAA,CACd,MAAA,EAAO,CACP,GAAA,EAAI,CACJ,GAAA,CAAI,CAAA,EAAG,yBAAyB,CAAA,CAChC,GAAA,CAAI,KAAA,EAAO,4BAA4B,CAAA;AAK5C,IAAM,iBAAiB,CAAA,CAClB,MAAA,EAAO,CACP,KAAA,CAAM,yBAAyB,yCAAyC,CAAA;AAS7E,IAAM,iBAAA,GAAoB,EAAE,MAAA,CAAO;AAAA,EAC/B,KAAK,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,wBAAwB,CAAA;AAAA,EAC/C,IAAA,EAAM,gBAAA;AAAA,EACN,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,QAAA,EAAU,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI;AACtC,CAAC,CAAA;AAKD,IAAM,mBAAA,GAAsB,EAAE,MAAA,CAAO;AAAA,EACjC,OAAA,EAAS,cAAc,QAAA,EAAS;AAAA,EAChC,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,IAAA,EAAM,WAAW,QAAA,EAAS;AAAA,EAC1B,QAAA,EAAU,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC9B,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,QAAA,EAAU,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC9B,GAAA,EAAK,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAC1B,MAAA,EAAQ,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAC7B,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA;AAC3B,CAAC,CAAA;AAKD,IAAM,WAAA,GAAc,EAAE,MAAA,CAAO;AAAA,EACzB,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,MAAA,EAAQ,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK,CAAA;AAAA,EACjC,QAAA,EAAU,oBAAoB,QAAA,EAAS;AAAA,EACvC,OAAA,EAAS,CAAA,CAAE,KAAA,CAAM,iBAAiB,EAAE,QAAA;AACxC,CAAC,CAAA;AAUD,IAAM,eAAA,GAAkB,EACnB,MAAA,CAAO;AAAA,EACJ,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAChC,MAAA,EAAQ,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAC7B,IAAA,EAAM,qBAAqB,QAAA;AAC/B,CAAC,CAAA,CACA,OAAO,CAAC,KAAA,KAAU,OAAO,IAAA,CAAK,KAAK,CAAA,CAAE,MAAA,GAAS,CAAA,EAAG;AAAA,EAC9C,OAAA,EAAS;AACb,CAAC,CAAA;AAKL,IAAM,UAAA,GAAa,EACd,MAAA,CAAO;AAAA,EACJ,KAAA,EAAO,eAAA;AAAA,EACP,SAAS,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAQ,EAAE,QAAA,EAAS;AAAA,EACtC,SAAS,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAQ,EAAE,QAAA;AACjC,CAAC,EACA,MAAA,CAAO,CAAC,SAAS,IAAA,CAAK,OAAA,IAAW,KAAK,OAAA,EAAS;AAAA,EAC5C,OAAA,EAAS;AACb,CAAC,CAAA;AASL,IAAM,iBAAA,GAAoB,EAAE,MAAA,CAAO;AAAA,EAC/B,SAAS,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAQ,EAAE,QAAA,EAAS;AAAA,EACtC,SAAS,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAQ,EAAE,QAAA;AACjC,CAAC,CAAA;AAKD,IAAM,gBAAA,GAAmB,EAAE,MAAA,CAAO;AAAA,EAC9B,GAAA,EAAK,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACzB,OAAA,EAAS,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACxB,CAAC,CAAA;AAKD,IAAM,kBAAA,GAAqB,EAAE,MAAA,CAAO;AAAA,EAChC,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK,CAAA;AAAA,EAClC,QAAQ,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAQ,EAAE,QAAA;AAChC,CAAC,CAAA;AAKD,IAAM,mBAAA,GAAsB,EAAE,MAAA,CAAO;AAAA,EACjC,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA,EACjC,KAAA,EAAO,cAAA,CAAe,OAAA,CAAQ,MAAM,CAAA;AAAA,EACpC,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,kBAAkB,CAAA;AAAA,EAC3C,OAAA,EAAS,cAAA,CAAe,OAAA,CAAQ,MAAM,CAAA;AAAA,EACtC,QAAA,EAAU,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,GAAA,CAAI,CAAC,CAAA,CAAE,OAAA,CAAQ,CAAC;AAC/C,CAAC,CAAA;AASM,IAAM,cAAA,GAAiB,EAAE,MAAA,CAAO;AAAA,EACnC,KAAA,EAAO,kBAAkB,QAAA,EAAS;AAAA,EAClC,KAAA,EAAO,iBAAiB,QAAA,EAAS;AAAA,EACjC,KAAA,EAAO,CAAA,CAAE,KAAA,CAAM,UAAU,EAAE,QAAA,EAAS;AAAA,EACpC,MAAA,EAAQ,EAAE,MAAA,CAAO,CAAA,CAAE,QAAO,EAAG,WAAW,EAAE,QAAA,EAAS;AAAA,EACnD,MAAA,EAAQ,mBAAmB,QAAA,EAAS;AAAA,EACpC,OAAA,EAAS,oBAAoB,QAAA,EAAS;AAAA,EACtC,OAAA,EAAS,CAAA,CAAE,KAAA,CAAM,iBAAiB,EAAE,QAAA;AACxC,CAAC,CAAA;AAwBM,IAAM,uBAAA,GAAN,cAAsC,KAAA,CAAM;AAAA,EAE/C,WAAA,CACI,OAAA,EACgB,KAAA,EACA,MAAA,EAClB;AAEE,IAAA,KAAA,CAAM,OAAO,CAAA;AAJG,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAIhB,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EAEhB;AAEJ,CAAA;AAgDO,SAAS,cAAc,QAAA,EAAuC;AAEjE,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,SAAA,CAAU,QAAQ,CAAA;AAEhD,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AAEjB,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA;AAExC,IAAA,MAAM,IAAI,uBAAA;AAAA,MACN,YAAY,OAAA,IAAW,4BAAA;AAAA,MACvB,UAAA,EAAY,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,IAAK,SAAA;AAAA,MAC9B,OAAO,KAAA,CAAM;AAAA,KACjB;AAAA,EAEJ;AAEA,EAAA,OAAO,MAAA,CAAO,IAAA;AAElB;;;ACtQO,IAAM,oBAAA,GAAoC;AAAA,EAC7C,SAAS,EAAC;AAAA,EACV,SAAS;AACb,CAAA;AAOO,IAAM,mBAAA,GAAkC;AAAA,EAC3C,GAAA,EAAK,OAAA;AAAA,EACL,OAAA,EAAS;AACb,CAAA;AAOO,IAAM,qBAAA,GAAsC;AAAA,EAC/C,OAAA,EAAS,KAAA;AAAA,EACT,QAAQ;AACZ,CAAA;AAKO,IAAM,sBAAA,GAAwC;AAAA,EACjD,OAAA,EAAS,IAAA;AAAA,EACT,KAAA,EAAO,MAAA;AAAA,EACP,IAAA,EAAM,kBAAA;AAAA,EACN,OAAA,EAAS,MAAA;AAAA,EACT,QAAA,EAAU;AACd,CAAA;AAaO,IAAM,gBAAA,GAA6B;AAAA,EACtC,KAAA,EAAO,oBAAA;AAAA,EACP,KAAA,EAAO,mBAAA;AAAA,EAGP,MAAA,EAAQ,qBAAA;AAAA,EACR,OAAA,EAAS;AACb,CAAA;AAiBO,SAAS,qBAAA,GAAkC;AAE9C,EAAA,OAAO;AAAA,IACH,KAAA,EAAO;AAAA,MACH,SAAS,CAAC,GAAI,oBAAA,CAAqB,OAAA,IAAW,EAAG,CAAA;AAAA,MACjD,SAAS,CAAC,GAAI,oBAAA,CAAqB,OAAA,IAAW,EAAG;AAAA,KACrD;AAAA,IACA,KAAA,EAAO,EAAE,GAAG,mBAAA,EAAoB;AAAA,IAChC,OAAO,EAAC;AAAA,IACR,QAAQ,EAAC;AAAA,IACT,MAAA,EAAQ,EAAE,GAAG,qBAAA,EAAuB,MAAA,EAAQ,CAAC,GAAI,qBAAA,CAAsB,MAAA,IAAU,EAAG,CAAA,EAAE;AAAA,IACtF,OAAA,EAAS,EAAE,GAAG,sBAAA;AAAuB,GACzC;AAEJ;AAUO,IAAM,iBAAA,GAAoB,QAAA;;;ACtD1B,SAAS,WAAA,CAAY,OAAkB,MAAA,EAAqC;AAG/E,EAAA,IAAI,MAAM,IAAA,KAAS,MAAA,IAAa,MAAA,CAAO,IAAA,KAAS,MAAM,IAAA,EAAM;AAExD,IAAA,OAAO,KAAA;AAAA,EAEX;AAEA,EAAA,IAAI,MAAM,SAAA,KAAc,MAAA,IAAa,MAAA,CAAO,SAAA,KAAc,MAAM,SAAA,EAAW;AAEvE,IAAA,OAAO,KAAA;AAAA,EAEX;AAEA,EAAA,IAAI,MAAM,MAAA,KAAW,MAAA,IAAa,MAAA,CAAO,MAAA,KAAW,MAAM,MAAA,EAAQ;AAE9D,IAAA,OAAO,KAAA;AAAA,EAEX;AAEA,EAAA,IAAI,MAAM,IAAA,KAAS,MAAA,IAAa,MAAA,CAAO,IAAA,KAAS,MAAM,IAAA,EAAM;AAExD,IAAA,OAAO,KAAA;AAAA,EAEX;AAEA,EAAA,OAAO,IAAA;AAEX;AAkBO,SAAS,YAAA,CAAa,MAAY,MAAA,EAAkD;AAEvF,EAAA,MAAM,OAAA,GAAU,WAAA,CAAY,IAAA,CAAK,KAAA,EAAO,MAAM,CAAA;AAE9C,EAAA,IAAI,CAAC,OAAA,EAAS;AAEV,IAAA,OAAO;AAAA,MACH,OAAA,EAAS,KAAA;AAAA,MACT,SAAS,EAAC;AAAA,MACV,SAAS;AAAC,KACd;AAAA,EAEJ;AAEA,EAAA,OAAO;AAAA,IACH,OAAA,EAAS,IAAA;AAAA,IACT,OAAA,EAAS,IAAA,CAAK,OAAA,IAAW,EAAC;AAAA,IAC1B,OAAA,EAAS,IAAA,CAAK,OAAA,IAAW;AAAC,GAC9B;AAEJ;AAmBO,SAAS,aAAA,CAAc,OAAe,MAAA,EAAmD;AAE5F,EAAA,MAAM,eAAuB,EAAC;AAC9B,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AACnC,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AAEnC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAEtB,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,IAAA,EAAM,MAAM,CAAA;AAExC,IAAA,IAAI,OAAO,OAAA,EAAS;AAEhB,MAAA,YAAA,CAAa,KAAK,IAAI,CAAA;AAGtB,MAAA,KAAA,MAAWC,KAAAA,IAAQ,OAAO,OAAA,EAAS;AAE/B,QAAA,UAAA,CAAW,IAAIA,KAAI,CAAA;AACnB,QAAA,UAAA,CAAW,OAAOA,KAAI,CAAA;AAAA,MAE1B;AAGA,MAAA,KAAA,MAAWA,KAAAA,IAAQ,OAAO,OAAA,EAAS;AAE/B,QAAA,UAAA,CAAW,IAAIA,KAAI,CAAA;AACnB,QAAA,UAAA,CAAW,OAAOA,KAAI,CAAA;AAAA,MAE1B;AAAA,IAEJ;AAAA,EAEJ;AAEA,EAAA,OAAO;AAAA,IACH,YAAA;AAAA,IACA,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA;AAAA,IAC9B,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,UAAU;AAAA,GAClC;AAEJ;AAyBO,SAAS,oBAAA,CACZ,YAAA,EACA,YAAA,EACA,UAAA,EACwC;AAGxC,EAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,YAAY,CAAA;AACvC,EAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,YAAY,CAAA;AAGvC,EAAA,KAAA,MAAWA,KAAAA,IAAQ,WAAW,OAAA,EAAS;AAEnC,IAAA,UAAA,CAAW,IAAIA,KAAI,CAAA;AACnB,IAAA,UAAA,CAAW,OAAOA,KAAI,CAAA;AAAA,EAE1B;AAGA,EAAA,KAAA,MAAWA,KAAAA,IAAQ,WAAW,OAAA,EAAS;AAEnC,IAAA,UAAA,CAAW,IAAIA,KAAI,CAAA;AACnB,IAAA,UAAA,CAAW,OAAOA,KAAI,CAAA;AAAA,EAE1B;AAEA,EAAA,OAAO;AAAA,IACH,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA;AAAA,IAC9B,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,UAAU;AAAA,GAClC;AAEJ;AA4BO,SAAS,sBAAA,CACZ,YAAA,EACA,YAAA,EACA,KAAA,EACA,MAAA,EACwC;AAExC,EAAA,MAAM,UAAA,GAAa,aAAA,CAAc,KAAA,EAAO,MAAM,CAAA;AAE9C,EAAA,OAAO,oBAAA,CAAqB,YAAA,EAAc,YAAA,EAAc,UAAU,CAAA;AAEtE;AC1NO,IAAM,kBAAN,MAAsB;AAAA,EAEzB,YAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA,GAA6B,IAAA;AAAA,EAC7B,OAAA,GAAU,KAAA;AAAA,EAEV,WAAA,CAAY,WAAA,EAAqB,OAAA,GAAkC,EAAC,EAAG;AAEnE,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AACpB,IAAA,IAAA,CAAK,YAAA,GAAe,QAAQ,WAAA,IAAe,iBAAA;AAC3C,IAAA,IAAA,CAAK,aAAA,GAAgB,QAAQ,YAAA,IAAgB,cAAA;AAAA,EAEjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,eAAA,GAA0B;AAE1B,IAAA,OAAOH,IAAAA,CAAK,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,YAAY,CAAA;AAAA,EAEpD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,gBAAA,GAA2B;AAE3B,IAAA,OAAOA,IAAAA,CAAK,IAAA,CAAK,eAAA,EAAiB,IAAA,CAAK,aAAa,CAAA;AAAA,EAExD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,GAA2B;AAE7B,IAAA,MAAM,CAAC,CAAA,EAAG,GAAG,CAAA,GAAI,MAAMC,QAAQ,MAAM,MAAA,CAAO,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAElE,IAAA,OAAO,CAAC,GAAA;AAAA,EAEZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,IAAA,GAA0B;AAE5B,IAAA,MAAMG,WAAAA,GAAa,MAAM,IAAA,CAAK,MAAA,EAAO;AAErC,IAAA,IAAI,CAACA,WAAAA,EAAY;AAEb,MAAA,IAAA,CAAK,YAAY,qBAAA,EAAsB;AACvC,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAEf,MAAA,QAAA,CAAS,KAAK,iBAAA,EAAmB;AAAA,QAC7B,MAAM,IAAA,CAAK,gBAAA;AAAA,QACX,UAAU,IAAA,CAAK,SAAA;AAAA,QACf,QAAA,EAAU;AAAA,OACb,CAAA;AAED,MAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IAEhB;AAGA,IAAA,MAAM,CAAC,OAAA,EAAS,OAAO,CAAA,GAAI,MAAMH,OAAAA,CAAQ,MAAMI,QAAAA,CAAS,IAAA,CAAK,gBAAA,EAAkB,OAAO,CAAC,CAAA;AAEvF,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,OAAA,CAAQ,OAAO,CAAA,CAAE,CAAA;AAAA,IAEtE;AAGA,IAAA,MAAM,CAAC,QAAQ,OAAO,CAAA,GAAI,MAAMJ,OAAAA,CAAQ,MAAMK,KAAA,CAAU,OAAO,CAAC,CAAA;AAEhE,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,OAAA,CAAQ,OAAO,CAAA,CAAE,CAAA;AAAA,IAEvE;AAGA,IAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,EAAW;AAEzC,MAAA,IAAA,CAAK,YAAY,qBAAA,EAAsB;AACvC,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAEf,MAAA,QAAA,CAAS,KAAK,iBAAA,EAAmB;AAAA,QAC7B,MAAM,IAAA,CAAK,gBAAA;AAAA,QACX,UAAU,IAAA,CAAK,SAAA;AAAA,QACf,QAAA,EAAU;AAAA,OACb,CAAA;AAED,MAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IAEhB;AAGA,IAAA,IAAA,CAAK,SAAA,GAAY,cAAc,MAAM,CAAA;AACrC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAEf,IAAA,QAAA,CAAS,KAAK,iBAAA,EAAmB;AAAA,MAC7B,MAAM,IAAA,CAAK,gBAAA;AAAA,MACX,UAAU,IAAA,CAAK,SAAA;AAAA,MACf,QAAA,EAAU;AAAA,KACb,CAAA;AAED,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EAEhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,IAAA,GAAsB;AAExB,IAAA,IAAA,CAAK,aAAA,EAAc;AAGnB,IAAA,MAAM,CAAC,CAAA,EAAG,QAAQ,CAAA,GAAI,MAAML,OAAAA,CAAQ,MAAMM,KAAAA,CAAM,IAAA,CAAK,eAAA,EAAiB,EAAE,SAAA,EAAW,IAAA,EAAM,CAAC,CAAA;AAE1F,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qCAAA,EAAwC,QAAA,CAAS,OAAO,CAAA,CAAE,CAAA;AAAA,IAE9E;AAGA,IAAA,MAAM,IAAA,GAAOC,SAAA,CAAc,IAAA,CAAK,SAAA,EAAW;AAAA,MACvC,MAAA,EAAQ,CAAA;AAAA,MACR,SAAA,EAAW;AAAA,KACd,CAAA;AAGD,IAAA,MAAM,CAAC,EAAA,EAAI,QAAQ,CAAA,GAAI,MAAMP,OAAAA,CAAQ,MAAMQ,SAAAA,CAAU,IAAA,CAAK,gBAAA,EAAkB,IAAA,EAAM,OAAO,CAAC,CAAA;AAE1F,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,QAAA,CAAS,OAAO,CAAA,CAAE,CAAA;AAAA,IAExE;AAEA,IAAA,QAAA,CAAS,KAAK,gBAAA,EAAkB,EAAE,IAAA,EAAM,IAAA,CAAK,kBAAkB,CAAA;AAAA,EAEnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAA,CAAK,KAAA,GAAQ,KAAA,EAAsB;AAErC,IAAA,MAAML,WAAAA,GAAa,MAAM,IAAA,CAAK,MAAA,EAAO;AAErC,IAAA,IAAIA,WAAAA,IAAc,CAAC,KAAA,EAAO;AAEtB,MAAA,MAAM,IAAI,MAAM,4DAA4D,CAAA;AAAA,IAEhF;AAEA,IAAA,IAAA,CAAK,YAAY,qBAAA,EAAsB;AACvC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAEf,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,KAAK,sBAAA,EAAwB;AAAA,MAClC,MAAM,IAAA,CAAK,gBAAA;AAAA,MACX;AAAA,KACH,CAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,QAAA,GAAoB;AAEpB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EAEhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,QAAA,GAAqB;AAErB,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EAEhB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,GAAwB;AAEpB,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAW,KAAA,IAAS,gBAAA,CAAiB,KAAA;AAAA,EAErD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,GAAuB;AAEnB,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAW,KAAA,IAAS,gBAAA,CAAiB,KAAA;AAAA,EAErD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,GAAmB;AAEf,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAW,KAAA,IAAS,EAAC;AAAA,EAErC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAAmC;AAE/B,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAW,MAAA,IAAU,EAAC;AAAA,EAEtC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,IAAA,EAAiC;AAEtC,IAAA,OAAO,IAAA,CAAK,SAAA,EAAU,CAAE,IAAI,CAAA;AAAA,EAEhC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,IAAA,EAAuB;AAE5B,IAAA,OAAO,IAAA,IAAQ,KAAK,SAAA,EAAU;AAAA,EAElC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAA0B;AAEtB,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAW,MAAA,IAAU,gBAAA,CAAiB,MAAA;AAAA,EAEtD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAA4B;AAExB,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAW,OAAA,IAAW,gBAAA,CAAiB,OAAA;AAAA,EAEvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,cAAc,MAAA,EAAmD;AAE7D,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,aAAA,CAAc,OAAO,MAAM,CAAA;AAAA,EAEtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,uBAAuB,MAAA,EAAsE;AAEzF,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,IAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAE5B,IAAA,OAAO,sBAAA;AAAA,MACH,KAAA,CAAM,WAAW,EAAC;AAAA,MAClB,KAAA,CAAM,WAAW,EAAC;AAAA,MAClB,KAAA;AAAA,MACA;AAAA,KACJ;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,oBAAoB,SAAA,EAA4B;AAE5C,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AAErC,IAAA,OAAO,OAAO,MAAA,KAAW,IAAA;AAAA,EAE7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAAmB,SAAA,EAA0E;AAEzF,IAAA,IAAA,CAAK,aAAA,EAAc;AAGnB,IAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,SAAA,CAAW,OAAA,IAAW,EAAC;AAGrD,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AACrC,IAAA,MAAM,YAAA,GAAe,KAAA,EAAO,OAAA,IAAW,EAAC;AAGxC,IAAA,MAAM,SAAA,uBAAgB,GAAA,EAAyB;AAE/C,IAAA,KAAA,MAAW,UAAU,gBAAA,EAAkB;AAEnC,MAAA,IAAI,MAAA,CAAO,aAAa,KAAA,EAAO;AAE3B,QAAA,SAAA,CAAU,GAAA,CAAI,MAAA,CAAO,GAAA,EAAK,MAAM,CAAA;AAAA,MAEpC;AAAA,IAEJ;AAEA,IAAA,KAAA,MAAW,UAAU,YAAA,EAAc;AAE/B,MAAA,IAAI,MAAA,CAAO,aAAa,KAAA,EAAO;AAE3B,QAAA,SAAA,CAAU,GAAA,CAAI,MAAA,CAAO,GAAA,EAAK,MAAM,CAAA;AAAA,MAEpC;AAAA,IAEJ;AAEA,IAAA,OAAO,KAAA,CAAM,KAAK,SAAA,CAAU,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAC9C,KAAK,CAAA,CAAE,GAAA;AAAA,MACP,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,aAAa,CAAA,CAAE;AAAA,KACnB,CAAE,CAAA;AAAA,EAEN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB,SAAA,EAAmD;AAEhE,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AAErC,IAAA,OAAO,KAAA,EAAO,YAAY,EAAC;AAAA,EAE/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAAuB,SAAA,EAA4B;AAE/C,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,gBAAA,CAAiB,SAAS,CAAA;AAEhD,IAAA,OAAO,SAAS,SAAA,KAAc,IAAA;AAAA,EAElC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,SAAA,EAA4B;AAE5C,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,gBAAA,CAAiB,SAAS,CAAA;AAEhD,IAAA,OAAO,SAAS,MAAA,KAAW,IAAA;AAAA,EAE/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAAA,GAA+B;AAE3B,IAAA,OAAO,IAAA,CAAK,SAAA,EAAU,CAAE,OAAA,KAAY,IAAA;AAAA,EAExC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAA,GAA8B;AAE1B,IAAA,MAAM,MAAA,GAAS,KAAK,SAAA,EAAU;AAE9B,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AAEjB,MAAA,OAAO,EAAC;AAAA,IAEZ;AAEA,IAAA,OAAO,MAAA,CAAO,UAAU,EAAC;AAAA,EAE7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,QAAA,CAAS,IAAA,EAAc,KAAA,EAA6B;AAEtD,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAW,MAAA,EAAQ;AAEzB,MAAA,IAAA,CAAK,SAAA,CAAW,SAAS,EAAC;AAAA,IAE9B;AAEA,IAAA,IAAA,CAAK,SAAA,CAAW,MAAA,CAAO,IAAI,CAAA,GAAI,KAAA;AAE/B,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,IAAA,CAAK,oBAAA,EAAsB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAEvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,IAAA,EAAgC;AAE9C,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAI,CAAC,KAAK,SAAA,CAAW,MAAA,IAAU,EAAE,IAAA,IAAQ,IAAA,CAAK,UAAW,MAAA,CAAA,EAAS;AAE9D,MAAA,OAAO,KAAA;AAAA,IAEX;AAEA,IAAA,OAAO,IAAA,CAAK,SAAA,CAAW,MAAA,CAAO,IAAI,CAAA;AAElC,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,IAAA,CAAK,wBAAA,EAA0B,EAAE,IAAA,EAAM,CAAA;AAEhD,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQ,IAAA,EAA2B;AAErC,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAW,KAAA,EAAO;AAExB,MAAA,IAAA,CAAK,SAAA,CAAW,QAAQ,EAAC;AAAA,IAE7B;AAEA,IAAA,IAAA,CAAK,SAAA,CAAW,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAE/B,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,IAAA,CAAK,qBAAA,EAAuB,EAAE,IAAA,EAAM,CAAA;AAAA,EAEjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,KAAA,EAAiC;AAE9C,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAW,KAAA,IAAS,KAAA,GAAQ,KAAK,KAAA,IAAS,IAAA,CAAK,SAAA,CAAW,KAAA,CAAM,MAAA,EAAQ;AAE9E,MAAA,OAAO,KAAA;AAAA,IAEX;AAEA,IAAA,MAAM,CAAC,OAAO,CAAA,GAAI,IAAA,CAAK,UAAW,KAAA,CAAM,MAAA,CAAO,OAAO,CAAC,CAAA;AAEvD,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,KAAK,uBAAA,EAAyB,EAAE,KAAA,EAAO,IAAA,EAAM,SAAU,CAAA;AAEhE,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,KAAA,EAAmC;AAE9C,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAA,CAAK,UAAW,KAAA,GAAQ,KAAA;AAExB,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,IAAA,CAAK,wBAAA,EAA0B,EAAE,KAAA,EAAO,CAAA;AAAA,EAErD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,KAAA,EAAkC;AAE7C,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAA,CAAK,UAAW,KAAA,GAAQ,KAAA;AAExB,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,IAAA,CAAK,wBAAA,EAA0B,EAAE,KAAA,EAAO,CAAA;AAAA,EAErD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,MAAA,EAAqC;AAEjD,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAA,CAAK,UAAW,MAAA,GAAS,MAAA;AAEzB,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,IAAA,CAAK,yBAAA,EAA2B,EAAE,MAAA,EAAQ,CAAA;AAAA,EAEvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,OAAA,EAAuC;AAEpD,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAA,CAAK,UAAW,OAAA,GAAU,OAAA;AAE1B,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,IAAA,CAAK,0BAAA,EAA4B,EAAE,OAAA,EAAS,CAAA;AAAA,EAEzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAAA,GAAqC;AAEjC,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAW,OAAA,IAAW,EAAC;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAmB,MAAA,EAAoC;AAEzD,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAW,OAAA,EAAS;AAE1B,MAAA,IAAA,CAAK,SAAA,CAAW,UAAU,EAAC;AAAA,IAE/B;AAGA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAW,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,KAAQ,MAAA,CAAO,GAAG,CAAA;AAEzE,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,MAAA,CAAO,GAAG,CAAA,gBAAA,CAAkB,CAAA;AAAA,IAErE;AAEA,IAAA,IAAA,CAAK,SAAA,CAAW,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAA;AAEnC,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,KAAK,uBAAA,EAAyB,EAAE,MAAA,EAAQ,KAAA,EAAO,aAAa,CAAA;AAAA,EAEzE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,qBAAA,CAAsB,GAAA,EAAa,MAAA,EAAoC;AAEzE,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAW,OAAA,EAAS;AAE1B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,GAAG,CAAA,WAAA,CAAa,CAAA;AAAA,IAEzD;AAEA,IAAA,MAAM,KAAA,GAAQ,KAAK,SAAA,CAAW,OAAA,CAAQ,UAAU,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,KAAQ,GAAG,CAAA;AAEpE,IAAA,IAAI,UAAU,EAAA,EAAI;AAEd,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,GAAG,CAAA,WAAA,CAAa,CAAA;AAAA,IAEzD;AAEA,IAAA,IAAA,CAAK,SAAA,CAAW,OAAA,CAAQ,KAAK,CAAA,GAAI,MAAA;AAEjC,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,KAAK,yBAAA,EAA2B,EAAE,KAAK,MAAA,EAAQ,KAAA,EAAO,aAAa,CAAA;AAAA,EAEhF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,sBAAsB,GAAA,EAA+B;AAEvD,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAW,OAAA,EAAS;AAE1B,MAAA,OAAO,KAAA;AAAA,IAEX;AAEA,IAAA,MAAM,KAAA,GAAQ,KAAK,SAAA,CAAW,OAAA,CAAQ,UAAU,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,KAAQ,GAAG,CAAA;AAEpE,IAAA,IAAI,UAAU,EAAA,EAAI;AAEd,MAAA,OAAO,KAAA;AAAA,IAEX;AAEA,IAAA,IAAA,CAAK,SAAA,CAAW,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,CAAC,CAAA;AAEvC,IAAA,MAAM,KAAK,IAAA,EAAK;AAEhB,IAAA,QAAA,CAAS,KAAK,yBAAA,EAA2B,EAAE,GAAA,EAAK,KAAA,EAAO,aAAa,CAAA;AAEpE,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cAAA,CAAe,SAAA,EAAmB,MAAA,EAAoC;AAExE,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AAErC,IAAA,IAAI,CAAC,KAAA,EAAO;AAER,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,OAAA,EAAU,SAAS,CAAA,WAAA,CAAa,CAAA;AAAA,IAEpD;AAEA,IAAA,IAAI,CAAC,MAAM,OAAA,EAAS;AAEhB,MAAA,KAAA,CAAM,UAAU,EAAC;AAAA,IAErB;AAGA,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,KAAQ,MAAA,CAAO,GAAG,CAAA;AAE/D,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,OAAO,GAAG,CAAA,2BAAA,EAA8B,SAAS,CAAA,CAAA,CAAG,CAAA;AAAA,IAEnF;AAEA,IAAA,KAAA,CAAM,OAAA,CAAQ,KAAK,MAAM,CAAA;AAEzB,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,SAAA,EAAW,KAAK,CAAA;AAEpC,IAAA,QAAA,CAAS,KAAK,uBAAA,EAAyB,EAAE,QAAQ,KAAA,EAAO,OAAA,EAAS,WAAW,CAAA;AAAA,EAEhF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAA,CAAkB,SAAA,EAAmB,GAAA,EAAa,MAAA,EAAoC;AAExF,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AAErC,IAAA,IAAI,CAAC,KAAA,EAAO;AAER,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,OAAA,EAAU,SAAS,CAAA,WAAA,CAAa,CAAA;AAAA,IAEpD;AAEA,IAAA,IAAI,CAAC,MAAM,OAAA,EAAS;AAEhB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,GAAG,CAAA,sBAAA,EAAyB,SAAS,CAAA,CAAA,CAAG,CAAA;AAAA,IAEvE;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,SAAA,CAAU,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,GAAG,CAAA;AAE1D,IAAA,IAAI,UAAU,EAAA,EAAI;AAEd,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,GAAG,CAAA,sBAAA,EAAyB,SAAS,CAAA,CAAA,CAAG,CAAA;AAAA,IAEvE;AAEA,IAAA,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,MAAA;AAEvB,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,SAAA,EAAW,KAAK,CAAA;AAEpC,IAAA,QAAA,CAAS,IAAA,CAAK,2BAA2B,EAAE,GAAA,EAAK,QAAQ,KAAA,EAAO,OAAA,EAAS,WAAW,CAAA;AAAA,EAEvF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAA,CAAkB,SAAA,EAAmB,GAAA,EAA+B;AAEtE,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AAErC,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,KAAA,CAAM,OAAA,EAAS;AAE1B,MAAA,OAAO,KAAA;AAAA,IAEX;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,SAAA,CAAU,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,GAAG,CAAA;AAE1D,IAAA,IAAI,UAAU,EAAA,EAAI;AAEd,MAAA,OAAO,KAAA;AAAA,IAEX;AAEA,IAAA,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,CAAC,CAAA;AAE7B,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,SAAA,EAAW,KAAK,CAAA;AAEpC,IAAA,QAAA,CAAS,KAAK,yBAAA,EAA2B,EAAE,KAAK,KAAA,EAAO,OAAA,EAAS,WAAW,CAAA;AAE3E,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAA,GAAsB;AAElB,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,IAAW,CAAC,KAAK,SAAA,EAAW;AAElC,MAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,IAEpE;AAAA,EAEJ;AAEJ,CAAA;AAMA,IAAI,uBAAA,GAAkD,IAAA;AAW/C,SAAS,kBAAA,CACZ,aACA,OAAA,EACe;AAEf,EAAA,IAAI,CAAC,uBAAA,EAAyB;AAE1B,IAAA,uBAAA,GAA0B,IAAI,eAAA,CAAgB,WAAA,EAAa,OAAO,CAAA;AAAA,EAEtE;AAEA,EAAA,OAAO,uBAAA;AAEX;ACj7BO,SAAS,eAAA,CAAgB,OAAA,GAA2B,EAAC,EAAa;AAErE,EAAA,IAAI,QAAA;AAGJ,EAAA,IAAI,QAAQ,cAAA,EAAgB;AAExB,IAAA,QAAA,GAAW,mBAAA,CAAoB,OAAA,CAAQ,cAAA,EAAgB,QAAQ,CAAA;AAAA,EAEnE,CAAA,MAAA,IAES,QAAQ,cAAA,EAAgB;AAE7B,IAAA,QAAA,GAAW,6BAAA,CAA8B,QAAQ,cAAc,CAAA;AAAA,EAEnE,CAAA,MAAA,IAES,OAAA,CAAQ,GAAA,CAAI,gBAAgB,CAAA,EAAG;AAEpC,IAAA,QAAA,GAAW,mBAAA,CAAoB,OAAA,CAAQ,GAAA,CAAI,gBAAgB,GAAG,KAAK,CAAA;AAAA,EAEvE,CAAA,MAAA,IAES,CAAC,OAAA,CAAQ,OAAA,EAAS;AAEvB,IAAA,MAAM,cAAc,cAAA,EAAe;AACnC,IAAA,QAAA,GAAW,eAAe,iBAAA,EAAkB;AAAA,EAEhD,CAAA,MAEK;AAED,IAAA,QAAA,GAAW,iBAAA,EAAkB;AAAA,EAEjC;AAEA,EAAA,QAAA,CAAS,KAAK,mBAAA,EAAqB;AAAA,IAC/B,MAAM,QAAA,CAAS,IAAA;AAAA,IACf,OAAO,QAAA,CAAS,KAAA;AAAA,IAChB,QAAQ,QAAA,CAAS;AAAA,GACpB,CAAA;AAED,EAAA,OAAO,QAAA;AAEX;AAOA,SAAS,8BAA8B,MAAA,EAAkC;AAErE,EAAA,OAAO;AAAA,IACH,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,MAAA,EAAQ;AAAA,GACZ;AAEJ;AAcA,SAAS,mBAAA,CAAoB,OAAe,MAAA,EAAkC;AAG1E,EAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAG3B,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,qBAAqB,CAAA;AAEjD,EAAA,IAAI,KAAA,EAAO;AAEP,IAAA,OAAO;AAAA,MACH,IAAA,EAAM,KAAA,CAAM,CAAC,CAAA,CAAG,IAAA,EAAK;AAAA,MACrB,KAAA,EAAO,KAAA,CAAM,CAAC,CAAA,CAAG,IAAA,EAAK;AAAA,MACtB;AAAA,KACJ;AAAA,EAEJ;AAGA,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,OAAA;AAAA,IACN;AAAA,GACJ;AAEJ;AAOA,SAAS,cAAA,GAAkC;AAEvC,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIF,WAAAA;AAAA,IAAY,MAChC,SAAS,sBAAA,EAAwB;AAAA,MAC7B,QAAA,EAAU,MAAA;AAAA,MACV,OAAA,EAAS,GAAA;AAAA,MACT,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,KACjC,EAAE,IAAA;AAAK,GACZ;AAEA,EAAA,IAAI,OAAA,IAAW,CAAC,IAAA,EAAM,OAAO,IAAA;AAE7B,EAAA,MAAM,CAAC,KAAK,CAAA,GAAIA,WAAAA;AAAA,IAAY,MACxB,SAAS,uBAAA,EAAyB;AAAA,MAC9B,QAAA,EAAU,MAAA;AAAA,MACV,OAAA,EAAS,GAAA;AAAA,MACT,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,KACjC,EAAE,IAAA;AAAK,GACZ;AAEA,EAAA,OAAO;AAAA,IACH,IAAA;AAAA,IACA,OAAO,KAAA,IAAS,MAAA;AAAA,IAChB,MAAA,EAAQ;AAAA,GACZ;AAEJ;AAKA,SAAS,iBAAA,GAA8B;AAEnC,EAAA,MAAM,OAAO,QAAA,EAAS;AAEtB,EAAA,OAAO;AAAA,IACH,MAAM,IAAA,CAAK,QAAA;AAAA,IACX,MAAA,EAAQ;AAAA,GACZ;AAEJ;AAcO,SAAS,eAAe,QAAA,EAAoD;AAE/E,EAAA,IAAI,SAAS,KAAA,EAAO;AAEhB,IAAA,OAAO,CAAA,EAAG,QAAA,CAAS,IAAI,CAAA,EAAA,EAAK,SAAS,KAAK,CAAA,CAAA,CAAA;AAAA,EAE9C;AAEA,EAAA,OAAO,QAAA,CAAS,IAAA;AAEpB;AC9KA,IAAM,oBAAN,MAAwB;AAAA,EAEpB,OAAA,uBAAc,GAAA,EAA8B;AAAA,EAC5C,QAAA,uBAAe,GAAA,EAA+B;AAAA,EAC9C,OAAA,GAAU,CAAA;AAAA,EACV,aAAA,GAAgB,KAAA;AAAA,EAChB,YAAA,GAAoC,IAAA;AAAA,EAEpC,WAAA,GAAc;AAGV,IAAA,IAAA,CAAK,YAAA,GAAe,QAAA,CAAS,EAAA,CAAG,cAAA,EAAgB,YAAY;AAExD,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAA,EAAG;AAE5B,QAAA,OAAA,CAAQ,KAAA;AAAA,UACJ,CAAA,mDAAA,EAAsD,KAAK,IAAI,CAAA,YAAA;AAAA,SACnE;AAAA,MAEJ;AAEA,MAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,MAAA,MAAM,KAAK,QAAA,EAAS;AAEpB,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAA,EAAG;AAE5B,QAAA,OAAA,CAAQ,MAAM,4CAA4C,CAAA;AAAA,MAE9D;AAAA,IAEJ,CAAC,CAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAA,CAAM,MAAwB,UAAA,EAA4B;AAEtD,IAAA,MAAM,KAAK,IAAA,CAAK,OAAA,EAAA;AAChB,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,EAAA,EAAI;AAAA,MAClB,IAAA;AAAA,MACA,UAAA;AAAA,MACA,SAAA,sBAAe,IAAA;AAAK,KACvB,CAAA;AAED,IAAA,OAAO,EAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,EAAA,EAAkB;AAEtB,IAAA,IAAA,CAAK,QAAA,CAAS,OAAO,EAAE,CAAA;AAAA,EAE3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAA,CACF,MAAA,EACA,QAAA,EACyB;AAEzB,IAAA,MAAM,MAAM,MAAA,CAAO,IAAA;AAEnB,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,EAAG;AAEvB,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAAA,IAE/B;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,MAAM,CAAA;AAClC,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AAE1B,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,UAAA,EAAmC;AAEjD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA;AACxC,IAAA,IAAI,IAAA,EAAM;AAEN,MAAA,MAAM,GAAG,GAAG,CAAA,GAAI,MAAMD,OAAAA,CAAQ,MAAM,IAAA,CAAK,OAAA,EAAS,CAAA;AAClD,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAO,UAAU,CAAA;AAE9B,MAAA,IAAI,GAAA,EAAK;AAEL,QAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,YAAA,EAAc,KAAA,EAAO,KAAK,CAAA;AAAA,MAE/D,CAAA,MACK;AAED,QAAA,QAAA,CAAS,IAAA,CAAK,kBAAA,EAAoB,EAAE,UAAA,EAAY,CAAA;AAAA,MAEpD;AAAA,IAEJ;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAA,GAA0B;AAE5B,IAAA,MAAM,aAAA,GAAgB,GAAA;AAGtB,IAAA,MAAM,cAAc,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA;AAClD,IAAA,KAAA,MAAW,QAAQ,WAAA,EAAa;AAE5B,MAAA,MAAM,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,IAE/B;AAGA,IAAA,MAAM,iBAAiB,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AACzD,IAAA,KAAA,MAAW,CAAC,EAAA,EAAI,KAAK,CAAA,IAAK,cAAA,EAAgB;AAEtC,MAAA,MAAM,kBAAA,GAAqB,QAAQ,IAAA,CAAK;AAAA,QACpC,KAAA,CAAM,KAAK,OAAA,EAAQ;AAAA,QACnB,IAAI,OAAA,CAAc,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,aAAa,CAAC;AAAA,OACpE,CAAA;AAED,MAAA,MAAM,GAAG,GAAG,IAAI,MAAMA,OAAAA,CAAQ,MAAM,kBAAkB,CAAA;AACtD,MAAA,IAAA,CAAK,QAAA,CAAS,OAAO,EAAE,CAAA;AAEvB,MAAA,IAAI,GAAA,EAAK;AAEL,QAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,YAAA,EAAc,KAAA,EAAO,KAAK,CAAA;AAAA,MAE/D,CAAA,MACK;AAED,QAAA,QAAA,CAAS,KAAK,kBAAA,EAAoB,EAAE,UAAA,EAAY,KAAA,CAAM,YAAY,CAAA;AAAA,MAEtE;AAAA,IAEJ;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,UAAA,EAA6B;AAEnC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA;AAAA,EAEtC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,IAAA,GAAe;AAEf,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,IAAA;AAAA,EAE7C;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,cAAA,GAA0B;AAE1B,IAAA,OAAO,IAAA,CAAK,aAAA;AAAA,EAEhB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAgB;AAEZ,IAAA,IAAI,KAAK,YAAA,EAAc;AAEnB,MAAA,IAAA,CAAK,YAAA,EAAa;AAClB,MAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AAAA,IAExB;AAAA,EAEJ;AAEJ,CAAA;AAGA,IAAIS,SAAAA,GAAqC,IAAA;AAOlC,SAAS,oBAAA,GAA0C;AAEtD,EAAA,IAAI,CAACA,SAAAA,EAAU;AAEX,IAAAA,SAAAA,GAAW,IAAI,iBAAA,EAAkB;AAAA,EAErC;AAEA,EAAA,OAAOA,SAAAA;AAEX;;;ACjPA,eAAe,kBAAkB,OAAA,EAA2C;AAExE,EAAA,QAAQ,OAAA;AAAS,IAEjB,KAAK,QAAA;AACD,MAAA,OAAA,CAAQ,MAAM,OAAO,sBAAsB,CAAA,EAAG,sBAAA;AAAA,IAElD,KAAK,UAAA;AACD,MAAA,OAAA,CAAQ,MAAM,OAAO,wBAAwB,CAAA,EAAG,wBAAA;AAAA,IAEpD,KAAK,OAAA;AACD,MAAA,OAAA,CAAQ,MAAM,OAAO,qBAAqB,CAAA,EAAG,qBAAA;AAAA,IAEjD,KAAK,OAAA;AACD,MAAA,OAAA,CAAQ,MAAM,OAAO,qBAAqB,CAAA,EAAG,qBAAA;AAAA,IAEjD;AACI,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,OAAO,CAAA,CAAE,CAAA;AAAA;AAIzD;AAKA,SAAS,kBAAkB,OAAA,EAA0B;AAEjD,EAAA,MAAM,QAAA,GAAoC;AAAA,IACtC,QAAA,EAAU,gBAAA;AAAA,IACV,KAAA,EAAO,oBAAA;AAAA,IACP,MAAA,EAAQ,4BAAA;AAAA,IACR,KAAA,EAAO;AAAA,GACX;AAEA,EAAA,OAAO,SAAS,OAAO,CAAA;AAE3B;AAsBA,eAAsB,gBAAA,CAClB,MAAA,EACA,UAAA,GAAqB,aAAA,EACI;AAEzB,EAAA,MAAM,CAAC,IAAA,EAAM,GAAG,CAAA,GAAI,MAAMT,OAAAA;AAAA,IAAQ,MAC9B,KAAA;AAAA,MACI,YAAY;AAER,QAAA,MAAM,CAAC,QAAA,EAAU,SAAS,CAAA,GAAI,MAAMA,OAAAA;AAAA,UAAQ,MACxC,iBAAA,CAAkB,MAAA,CAAO,OAAO;AAAA,SACpC;AAEA,QAAA,IAAI,SAAA,EAAW;AAEX,UAAA,MAAM,UAAU,SAAA,CAAU,OAAA;AAC1B,UAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,oBAAoB,CAAA,EAAG;AAExC,YAAA,MAAM,IAAI,KAAA;AAAA,cACN,CAAA,mBAAA,EAAsB,OAAO,OAAO,CAAA;AAAA,CAAA,GAChC,iBAAA,CAAkB,OAAO,OAAO;AAAA,aACxC;AAAA,UAEJ;AACA,UAAA,MAAM,SAAA;AAAA,QAEV;AAEA,QAAA,MAAMU,KAAAA,GAAO,MAAM,QAAA,CAAU,MAAM,CAAA;AAGnC,QAAA,MAAM,GAAA,CAAA,QAAA,CAAA,CAAc,OAAA,CAAQA,KAAAA,CAAK,EAAE,CAAA;AAEnC,QAAA,OAAOA,KAAAA;AAAA,MAEX,CAAA;AAAA,MACA;AAAA,QACI,OAAA,EAAS,CAAA;AAAA,QACT,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,CAAA;AAAA;AAAA,QACT,YAAA,EAAc,GAAA;AAAA,QACd,WAAA,EAAa,CAACC,IAAAA,KAAQ;AAElB,UAAA,MAAM,GAAA,GAAMA,IAAAA,CAAI,OAAA,CAAQ,WAAA,EAAY;AAGpC,UAAA,IAAI,GAAA,CAAI,QAAA,CAAS,gBAAgB,CAAA,EAAG,OAAO,KAAA;AAC3C,UAAA,IAAI,GAAA,CAAI,QAAA,CAAS,UAAU,CAAA,EAAG,OAAO,KAAA;AACrC,UAAA,IAAI,GAAA,CAAI,QAAA,CAAS,gBAAgB,CAAA,EAAG,OAAO,KAAA;AAG3C,UAAA,OACI,GAAA,CAAI,QAAA,CAAS,cAAc,CAAA,IAC3B,IAAI,QAAA,CAAS,WAAW,CAAA,IACxB,GAAA,CAAI,QAAA,CAAS,sBAAsB,CAAA,IACnC,GAAA,CAAI,SAAS,kBAAkB,CAAA;AAAA,QAGvC;AAAA;AACJ;AACJ,GACJ;AAEA,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,QAAA,CAAS,KAAK,kBAAA,EAAoB,EAAE,YAAY,KAAA,EAAO,GAAA,CAAI,SAAS,CAAA;AACpE,IAAA,MAAM,GAAA;AAAA,EAEV;AAGA,EAAA,MAAM,UAAU,oBAAA,EAAqB;AACrC,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,IAAA,EAAO,UAAU,CAAA;AAG/C,EAAA,MAAM,kBAAkB,IAAA,CAAM,OAAA;AAC9B,EAAA,MAAM,iBAAiB,YAA2B;AAE9C,IAAA,OAAA,CAAQ,QAAQ,OAAO,CAAA;AACvB,IAAA,MAAM,eAAA,EAAgB;AACtB,IAAA,QAAA,CAAS,IAAA,CAAK,kBAAA,EAAoB,EAAE,UAAA,EAAY,CAAA;AAAA,EAEpD,CAAA;AAEA,EAAA,MAAM,WAAA,GAAgC;AAAA,IAClC,IAAI,IAAA,CAAM,EAAA;AAAA,IACV,SAAS,IAAA,CAAM,OAAA;AAAA,IACf,OAAA,EAAS;AAAA,GACb;AAEA,EAAA,QAAA,CAAS,KAAK,iBAAA,EAAmB,EAAE,YAAY,OAAA,EAAS,MAAA,CAAO,SAAS,CAAA;AAExE,EAAA,OAAO,WAAA;AAEX;AAMA,IAAM,gBAAA,GAAwD;AAAA,EAC1D,QAAA,EAAU,UAAA;AAAA,EACV,KAAA,EAAO,MAAA;AAAA;AAAA,EACP,MAAA,EAAQ,MAAA;AAAA;AAAA,EACR,KAAA,EAAO;AACX,CAAA;AAyBA,eAAsB,cAAA,CAClB,MAAA,EACA,OAAA,GAAwC,EAAC,EACD;AAExC,EAAA,IAAI,UAAA,GAAa,MAAA;AAGjB,EAAA,IAAI,OAAA,CAAQ,cAAA,IAAkB,MAAA,CAAO,OAAA,KAAY,QAAA,EAAU;AAEvD,IAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,MAAA,CAAO,OAAO,CAAA;AAEhD,IAAA,UAAA,GAAa;AAAA,MACT,GAAG,MAAA;AAAA,MACH,QAAA,EAAU,YAAY,MAAA,CAAO;AAAA,KACjC;AAAA,EAEJ;AAEA,EAAA,MAAM,CAAC,IAAA,EAAM,GAAG,CAAA,GAAI,MAAMX,QAAQ,MAAM,gBAAA,CAAiB,UAAA,EAAY,UAAU,CAAC,CAAA;AAEhF,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,IAAI,OAAA,EAAQ;AAAA,EAE3C;AAEA,EAAA,MAAM,KAAM,OAAA,EAAQ;AAEpB,EAAA,OAAO,EAAE,IAAI,IAAA,EAAK;AAEtB;;;ACpNO,IAAM,YAAA,GAAe,OAAO,MAAA,CAAO;AAAA;AAAA,EAEtC,OAAA,EAAS,mBAAA;AAAA;AAAA,EAGT,MAAA,EAAQ,kBAAA;AAAA;AAAA,EAGR,UAAA,EAAY,sBAAA;AAAA;AAAA,EAGZ,IAAA,EAAM,gBAAA;AAAA;AAAA,EAGN,UAAA,EAAY;AAChB,CAAC,CAAA;;;ACkFM,SAAS,gBAAA,GAAuC;AAEnD,EAAA,OAAO,OAAA,CAAQ,IAAI,cAAc,CAAA;AAErC;ACrGO,IAAM,OAAA,GAAU;AAAA;AAAA,EAGnB,OAAA,EAAS,SAAA;AAAA;AAAA;AAAA,EAGT,OAAA,EAAS,SAAA;AAAA;AAAA,EACT,OAAA,EAAS,SAAA;AAAA;AAAA,EACT,KAAA,EAAO,SAAA;AAAA;AAAA,EACP,IAAA,EAAM,SAAA;AAAA;AAAA,EACN,KAAA,EAAO,SAAA;AAAA;AAAA;AAAA,EAGP,MAAA,EAAQ,SAAA;AAAA;AAAA,EACR,SAAA,EAAW,SAAA;AAAA;AAAA,EACX,KAAA,EAAO,SAAA;AAAA;AAAA,EACP,WAAA,EAAa,SAAA;AAAA;AAAA;AAAA,EAGb,IAAA,EAAM,SAAA;AAAA;AAAA,EACN,OAAA,EAAS,SAAA;AAAA;AAAA,EACT,MAAA,EAAQ,SAAA;AAAA;AAAA,EACR,WAAA,EAAa,SAGjB,CAAA;AAUO,IAAM,KAAA,GAAQ;AAAA;AAAA,EAGjB,OAAA,EAAS,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,OAAO,EAAE,IAAI,CAAA;AAAA;AAAA,EAG1D,OAAA,EAAS,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,OAAO,EAAE,IAAI,CAAA;AAAA,EAC1D,OAAA,EAAS,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,OAAO,EAAE,IAAI,CAAA;AAAA,EAC1D,KAAA,EAAO,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,KAAK,EAAE,IAAI,CAAA;AAAA,EACtD,IAAA,EAAM,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,IAAI,EAAE,IAAI,CAAA;AAAA,EACpD,KAAA,EAAO,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,KAAK,EAAE,IAAI,CAAA;AAAA;AAAA,EAGtD,MAAA,EAAQ,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,MAAM,EAAE,IAAI,CAAA;AAAA,EACxD,SAAA,EAAW,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,SAAS,EAAE,IAAI,CAAA;AAAA,EAC9D,KAAA,EAAO,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,KAAK,EAAE,IAAI,CAAA;AAAA,EACtD,WAAA,EAAa,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,WAAW,EAAE,IAAI,CAAA;AAAA;AAAA,EAGlE,IAAA,EAAM,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,IAAI,EAAE,IAAI,CAAA;AAAA,EACpD,OAAA,EAAS,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,OAAO,EAAE,IAAI,CAAA;AAAA;AAAA,EAG1D,MAAA,EAAQ,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,MAAM,EAAE,IAAI,CAAA;AAAA,EACxD,WAAA,EAAa,CAAC,IAAA,KAAiB,KAAA,CAAM,IAAI,OAAA,CAAQ,WAAW,EAAE,IAAI,CAAA;AAAA;AAAA,EAGlE,MAAM,KAAA,CAAM,IAAA;AAAA,EACZ,KAAK,KAAA,CAAM,GAAA;AAAA,EACX,QAAQ,KAAA,CAAM,MAAA;AAAA,EACd,WAAW,KAAA,CAAM,SAAA;AAAA,EACjB,SAAS,KAAA,CAAM,OAAA;AAAA,EACf,OAAO,KAAA,CAAM;AAEjB,CAAA;CCwE4B;AAAA,EACxB,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,QAAG,CAAA;AAAA,EAC1B,MAAA,EAAQ,KAAA,CAAM,KAAA,CAAM,QAAG,CAAA;AAAA,EACvB,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,QAAG,CAAA;AAAA,EAC1B,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,QAAG,CAAA;AAAA,EAC1B,OAAA,EAAS,KAAA,CAAM,KAAA,CAAM,QAAG,CAAA;AAAA,EACxB,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,QAAG;AAC5B;;;ACrJA,IAAM,aAAA,uBAAoB,GAAA,EAAY;AAStC,SAAS,YAAY,GAAA,EAAqB;AAEtC,EAAA,OAAO,IACF,OAAA,CAAQ,cAAA,EAAgB,CAAC,CAAA,EAAG,CAAA,KAAO,IAAI,CAAA,CAAE,WAAA,EAAY,GAAI,EAAG,EAC5D,OAAA,CAAQ,QAAA,EAAU,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,CAAA;AAEjD;AAKA,SAAS,YAAY,GAAA,EAAqB;AAEtC,EAAA,OAAO,GAAA,CACF,QAAQ,SAAA,EAAW,GAAG,EACtB,OAAA,CAAQ,iBAAA,EAAmB,OAAO,CAAA,CAClC,WAAA,EAAY;AAErB;AAKA,SAAS,YAAY,GAAA,EAAqB;AAEtC,EAAA,OAAO,GAAA,CACF,QAAQ,SAAA,EAAW,GAAG,EACtB,OAAA,CAAQ,iBAAA,EAAmB,OAAO,CAAA,CAClC,WAAA,EAAY;AAErB;AAKA,SAAS,YAAY,GAAA,EAAqB;AAEtC,EAAA,OAAO,GAAA,CACF,OAAA,CAAQ,UAAA,EAAY,GAAG,CAAA,CACvB,OAAA,CAAQ,iBAAA,EAAmB,OAAO,CAAA,CAClC,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,CACxE,KAAK,EAAE,CAAA;AAEhB;AAKA,SAAS,SAAS,GAAA,EAAqB;AAEnC,EAAA,OAAO,GAAA,CAAI,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AAEpC;AAYO,SAAS,gBAAgB,MAAA,EAAwB;AAEpD,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAGxB,IAAA,MAAM,QAAA,GAAW,CAAC,KAAA,EAAO,CAAA,MAAA,EAAS,KAAK,CAAA,CAAE,CAAA;AAEzC,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAG5B,MAAA,aAAA,CAAc,IAAI,OAAO,CAAA;AAGzB,MAAA,aAAA,CAAc,GAAA,CAAI,OAAA,CAAQ,WAAA,EAAa,CAAA;AACvC,MAAA,aAAA,CAAc,GAAA,CAAI,OAAA,CAAQ,WAAA,EAAa,CAAA;AACvC,MAAA,aAAA,CAAc,GAAA,CAAI,WAAA,CAAY,OAAO,CAAC,CAAA;AACtC,MAAA,aAAA,CAAc,GAAA,CAAI,WAAA,CAAY,OAAO,CAAC,CAAA;AACtC,MAAA,aAAA,CAAc,GAAA,CAAI,WAAA,CAAY,OAAO,CAAC,CAAA;AACtC,MAAA,aAAA,CAAc,GAAA,CAAI,WAAA,CAAY,OAAO,CAAC,CAAA;AAGtC,MAAA,aAAA,CAAc,GAAA,CAAI,QAAA,CAAS,OAAO,CAAC,CAAA;AACnC,MAAA,aAAA,CAAc,GAAA,CAAI,QAAA,CAAS,OAAO,CAAA,CAAE,aAAa,CAAA;AACjD,MAAA,aAAA,CAAc,GAAA,CAAI,QAAA,CAAS,OAAO,CAAA,CAAE,aAAa,CAAA;AAAA,IAErD;AAAA,EAEJ;AAEJ;AAGA,eAAA,CAAgB;AAAA,EACZ,UAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA,aAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA;AACJ,CAAC,CAAA;;;AC7ED,IAAI,cAAA,GAAkC,IAAA;AAsB/B,SAASY,gBAAAA,CAAgB,OAAA,GAA2B,EAAC,EAAa;AAGrE,EAAA,IAAI,OAAA,CAAQ,cAAA,IAAkB,OAAA,CAAQ,cAAA,EAAgB;AAElD,IAAA,OAAO,gBAAQ,OAAO,CAAA;AAAA,EAE1B;AAEA,EAAA,IAAI,CAAC,cAAA,EAAgB;AAEjB,IAAA,cAAA,GAAiB,gBAAQ,OAAO,CAAA;AAAA,EAEpC;AAEA,EAAA,OAAO,cAAA;AAEX;AAwBO,SAAS,qBAAqB,MAAA,EAAyC;AAE1E,EAAA,OAAOA,gBAAAA,CAAgB,EAAE,cAAA,EAAgB,MAAA,CAAO,UAAU,CAAA;AAE9D;ACtIO,IAAMC,cAAAA,GAAgBC,EAAE,IAAA,CAAK,CAAC,YAAY,OAAA,EAAS,QAAA,EAAU,OAAO,CAAC,CAAA;AAK5E,IAAM,mBAAmBA,CAAAA,CACpB,MAAA,GACA,GAAA,CAAI,CAAA,EAAG,yBAAyB,CAAA,CAChC,KAAA;AAAA,EACG,gBAAA;AAAA,EACA;AACJ,CAAA;AAKJ,IAAMC,WAAAA,GAAaD,CAAAA,CACd,MAAA,EAAO,CACP,GAAA,EAAI,CACJ,GAAA,CAAI,CAAA,EAAG,yBAAyB,CAAA,CAChC,GAAA,CAAI,KAAA,EAAO,4BAA4B,CAAA;AAK5C,IAAM,UAAA,GAAaA,EAAE,MAAA,CAAO;AAAA,EACxB,GAAA,EAAKA,EAAE,MAAA,EAAO,CAAE,KAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,QAAA,EAAS;AAAA,EACtC,GAAA,EAAKA,EAAE,MAAA,EAAO,CAAE,KAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,QAAA;AACjC,CAAC,CAAA;AAKD,IAAM,SAAA,GAAYA,EAAE,KAAA,CAAM;AAAA,EACtBA,EAAE,OAAA,EAAQ;AAAA,EACVA,EAAE,MAAA,CAAO;AAAA,IACL,kBAAA,EAAoBA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,IACzC,EAAA,EAAIA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,IACxB,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,IAC1B,GAAA,EAAKA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAAS,GAC5B;AACL,CAAC,CAAA;AAQM,IAAM,gBAAA,GAAmBA,EAC3B,MAAA,CAAO;AAAA,EACJ,OAAA,EAASD,cAAAA;AAAA,EACT,IAAA,EAAMC,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,IAAA,EAAMC,YAAW,QAAA,EAAS;AAAA,EAC1B,UAAUD,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,2BAA2B,CAAA;AAAA,EACvD,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC9B,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC9B,GAAA,EAAK,UAAU,QAAA,EAAS;AAAA,EACxB,IAAA,EAAM,WAAW,QAAA;AACrB,CAAC,CAAA,CACA,OAAO,CAAC,IAAA,KAAS,KAAK,OAAA,KAAY,QAAA,IAAY,KAAK,IAAA,EAAM;AAAA,EACtD,OAAA,EAAS,2CAAA;AAAA,EACT,IAAA,EAAM,CAAC,MAAM;AACjB,CAAC,CAAA;AAKL,IAAM,WAAA,GAAcA,EAAE,MAAA,CAAO;AAAA,EACzB,KAAKA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,sBAAsB,CAAA;AAAA,EAC7C,SAASA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,0BAA0B;AACzD,CAAC,CAAA;AAKM,IAAM,YAAA,GAAeA,EAAE,MAAA,CAAO;AAAA,EACjC,IAAA,EAAM,gBAAA;AAAA,EACN,IAAA,EAAMA,EAAE,IAAA,CAAK,CAAC,SAAS,QAAQ,CAAC,CAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,EACjD,MAAA,EAAQA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK,CAAA;AAAA,EACjC,SAAA,EAAWA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK,CAAA;AAAA,EACpC,UAAA,EAAY,gBAAA;AAAA,EACZ,KAAA,EAAO,WAAA;AAAA,EACP,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACzB,CAAC,CAAA;AAKD,IAAM,uBAAA,GAA0BA,EAAE,MAAA,CAAO;AAAA,EACrC,OAAA,EAASD,eAAc,QAAA,EAAS;AAAA,EAChC,IAAA,EAAMC,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,IAAA,EAAMC,YAAW,QAAA,EAAS;AAAA,EAC1B,QAAA,EAAUD,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC9B,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC9B,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC9B,GAAA,EAAK,UAAU,QAAA,EAAS;AAAA,EACxB,IAAA,EAAM,WAAW,QAAA;AACrB,CAAC,CAAA;AAKD,IAAM,kBAAA,GAAqBA,EAAE,MAAA,CAAO;AAAA,EAChC,GAAA,EAAKA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACzB,OAAA,EAASA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACxB,CAAC,CAAA;AAOgCA,EAAE,MAAA,CAAO;AAAA,EACtC,MAAMA,CAAAA,CACD,MAAA,GACA,KAAA,CAAM,gBAAgB,EACtB,QAAA,EAAS;AAAA,EACd,IAAA,EAAMA,EAAE,IAAA,CAAK,CAAC,SAAS,QAAQ,CAAC,EAAE,QAAA,EAAS;AAAA,EAC3C,MAAA,EAAQA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAC7B,SAAA,EAAWA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAChC,UAAA,EAAY,wBAAwB,QAAA,EAAS;AAAA,EAC7C,KAAA,EAAO,mBAAmB,QAAA,EAAS;AAAA,EACnC,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACzB,CAAC;AAO8B,aAAa,MAAA,CAAO;AAAA,EAC/C,IAAA,EAAM,iBAAiB,QAAA;AAC3B,CAAC;AAmBM,IAAM,qBAAA,GAAN,cAAoC,KAAA,CAAM;AAAA,EAE7C,WAAA,CACI,OAAA,EACgB,KAAA,EACA,MAAA,EAClB;AAEE,IAAA,KAAA,CAAM,OAAO,CAAA;AAJG,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAIhB,IAAA,IAAA,CAAK,IAAA,GAAO,uBAAA;AAAA,EAEhB;AAEJ,CAAA;AAqFO,SAAS,YAAY,MAAA,EAAmC;AAE3D,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,SAAA,CAAU,MAAM,CAAA;AAE5C,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AAEjB,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA;AAExC,IAAA,MAAM,IAAI,qBAAA;AAAA,MACN,YAAY,OAAA,IAAW,mBAAA;AAAA,MACvB,UAAA,EAAY,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,IAAK,SAAA;AAAA,MAC9B,OAAO,KAAA,CAAM;AAAA,KACjB;AAAA,EAEJ;AAEA,EAAA,OAAO,MAAA,CAAO,IAAA;AAElB;AChRA,IAAM,aAAA,uBAAoB,GAAA,CAAI;AAAA,EAC1B,cAAA;AAAA;AAAA,EACA,WAAA;AAAA;AAAA,EACA;AAAA;AACJ,CAAC,CAAA;AAED,IAAM,cAAA,GAAiB,CAAC,UAAA,EAAY,OAAA,EAAS,UAAU,OAAO,CAAA;AAEvD,IAAM,EAAE,UAAA,EAAY,SAAA,EAAU,GAAI,gBAAA,CAA8B,QAAQ,GAAA,EAA+B;AAAA,EAC1G,MAAA,EAAQ,CAAC,GAAA,KAAQ,GAAA,CAAI,UAAA,CAAW,QAAQ,CAAA,IAAK,CAAC,aAAA,CAAc,GAAA,CAAI,GAAG,CAAA;AAAA,EACnE,WAAA,EAAa,QAAA;AAAA,EACb,kBAAA,EAAoB,IAAA;AAAA,EACpB,WAAA,EAAa,KAAA;AAAA,EACb,gBAAgB,CAAC,GAAA,KAAQ,IAAI,WAAA,EAAY,CAAE,SAAS,UAAU;AAClE,CAAC,CAAA;AAwBM,SAAS,YAAA,GAA4B;AAExC,EAAA,MAAM,SAAS,UAAA,EAAW;AAG1B,EAAA,IAAI,MAAA,CAAO,YAAY,OAAA,EAAS;AAE5B,IAAA,MAAM,MAAA,GAASD,cAAAA,CAAc,SAAA,CAAU,MAAA,CAAO,WAAW,OAAO,CAAA;AAChE,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AAEjB,MAAA,MAAM,IAAI,KAAA;AAAA,QACN,CAAA,iDAAA,EAAoD,cAAA,CAAe,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OACjF;AAAA,IAEJ;AAAA,EAEJ;AAEA,EAAA,OAAO,MAAA;AAEX;;;AChCO,IAAM,mBAAN,MAAuB;AAAA,EAE1B,QAAA;AAAA,EAEA,YAAY,OAAA,EAA0B;AAElC,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAAA,EAEpB;AAAA;AAAA,EAGA,SAAS,IAAA,EAAc;AAEnB,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,IAAI,CAAA,IAAK,IAAA;AAAA,EAE3C;AAAA;AAAA,EAGA,mBAAmB,UAAA,EAAoB;AAGnC,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,UAAU,CAAA,IAAK,IAAA;AAAA,EAEjD;AAEJ,CAAA;AAKA,IAAM,QAAA,GAAwB;AAAA,EAC1B,IAAA,EAAM,OAAA;AAAA,EACN,MAAA,EAAQ,KAAA;AAAA,EACR,SAAA,EAAW,KAAA;AAAA,EACX,KAAA,EAAO;AAAA,IACH,GAAA,EAAK,OAAA;AAAA,IACL,OAAA,EAAS;AAAA,GACb;AAAA,EACA,UAAA,EAAY;AAAA,IACR,IAAA,EAAM,WAAA;AAAA,IACN,IAAA,EAAM,EAAE,GAAA,EAAK,CAAA,EAAG,KAAK,EAAA;AAAG,GAC5B;AAAA,EACA,GAAA,EAAK;AAAA,IACD,KAAA,EAAO;AAAA;AAEf,CAAA;AA2DO,SAAS,aAAA,CAAc,KAAA,EAAsB,OAAA,GAA0B,EAAC,EAAkB;AAG7F,EAAA,MAAM,aAAa,OAAA,CAAQ,IAAA,IAAQ,gBAAA,EAAiB,IAAK,MAAM,mBAAA,EAAoB;AAEnF,EAAA,IAAI,CAAC,UAAA,EAAY;AAGb,IAAA,MAAMG,aAAY,YAAA,EAAa;AAC/B,IAAA,IAAIA,UAAAA,CAAU,UAAA,EAAY,OAAA,IAAWA,UAAAA,CAAU,YAAY,QAAA,EAAU;AAEjE,MAAA,OAAO,mBAAmBA,UAAAA,EAAW,OAAA,CAAQ,OAAO,OAAA,CAAQ,KAAA,EAAO,QAAQ,QAAQ,CAAA;AAAA,IAEvF;AAEA,IAAA,OAAO,IAAA;AAAA,EAEX;AAGA,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,SAAA,CAAU,UAAU,CAAA;AACzC,EAAA,IAAI,CAAC,MAAA,EAAQ;AAET,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,UAAU,CAAA,WAAA,CAAa,CAAA;AAAA,EAEtD;AAGA,EAAA,MAAM,gBAAgB,gBAAA,CAAiB,UAAA,EAAY,OAAA,CAAQ,KAAA,EAAO,QAAQ,QAAQ,CAAA;AAIlF,EAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,EAAA,IAAI,MAAA,GAAS,MAAM,QAAQ,CAAA;AAE3B,EAAA,IAAI,aAAA,EAAe;AAEf,IAAA,MAAA,GAASC,KAAAA,CAAM,QAAQ,aAAa,CAAA;AAAA,EAExC;AAEA,EAAA,MAAA,GAASA,KAAAA,CAAM,QAAQ,MAAM,CAAA;AAC7B,EAAA,MAAA,GAASA,KAAAA,CAAM,QAAQ,SAAS,CAAA;AAChC,EAAA,MAAA,GAASA,KAAAA,CAAM,MAAA,EAAQ,OAAA,CAAQ,KAAA,IAAS,EAAE,CAAA;AAG1C,EAAA,OAAO,YAAY,MAAM,CAAA;AAE7B;AASA,SAAS,gBAAA,CACL,UAAA,EACA,SAAA,EACA,QAAA,EACoB;AAEpB,EAAA,IAAI,CAAC,UAAU,OAAO,IAAA;AACtB,EAAA,IAAI,WAAW,OAAO,QAAA,CAAS,QAAA,CAAS,SAAS,GAAG,QAAA,IAAY,IAAA;AAEhE,EAAA,OAAO,QAAA,CAAS,kBAAA,CAAmB,UAAU,CAAA,EAAG,QAAA,IAAY,IAAA;AAEhE;AAOA,SAAS,kBAAA,CACL,SAAA,EACA,KAAA,EACA,SAAA,EACA,QAAA,EACM;AAGN,EAAA,MAAM,IAAA,GAAO,SAAA,CAAU,IAAA,IAAQ,KAAA,EAAO,IAAA,IAAQ,SAAA;AAG9C,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,IAAA,EAAM,SAAA,EAAW,QAAQ,CAAA;AAGhE,EAAA,IAAI,MAAA,GAAS,MAAM,QAAQ,CAAA;AAE3B,EAAA,IAAI,aAAA,EAAe;AAEf,IAAA,MAAA,GAASA,KAAAA,CAAM,QAAQ,aAAa,CAAA;AAAA,EAExC;AAEA,EAAA,MAAA,GAASA,KAAAA,CAAM,QAAQ,SAAS,CAAA;AAChC,EAAA,MAAA,GAASA,KAAAA,CAAM,MAAA,EAAQ,KAAA,IAAS,EAAE,CAAA;AAGlC,EAAA,IAAI,CAAC,OAAO,IAAA,EAAM;AAEd,IAAA,MAAA,CAAO,IAAA,GAAO,SAAA;AAAA,EAElB;AAEA,EAAA,OAAO,YAAY,MAAM,CAAA;AAE7B;ACrNA,IAAM,gBAAA,GAAmB,CAAC,YAAA,EAAc,oBAAA,EAAsB,UAAU,CAAA;AAKjE,IAAM,yBAAA,GAAsD;AAAA,EAE/D,MAAM,YAAY,EAAA,EAA+C;AAG7D,IAAA,MAAM,CAAC,MAAA,EAAQ,KAAA,EAAO,UAAA,EAAY,SAAA,EAAW,KAAA,EAAO,OAAA,EAAS,WAAW,CAAA,GACpE,MAAM,OAAA,CAAQ,GAAA,CAAI;AAAA,MACdC,GAAAA;AAAA;AAAA;AAAA,+CAAA,EAGiCA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA,gBAAA,CAAA,CAEzD,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA,+CAAA,EAGiCA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACzD,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA;AAAA,4CAAA,EAI8BA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAA,CAAA,CAOtD,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA;AAAA,4CAAA,EAI8BA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAA,CAAA,CAOtD,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA;AAAA,4CAAA,EAI8BA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAA,CAAA,CAYtD,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA,6CAAA,EAG+BA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACvD,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA;AAAA,6CAAA,EAI+BA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACvD,QAAQ,EAAE;AAAA,KACf,CAAA;AAEL,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,SAAS,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,KAAK,EAAE,CAAA;AAAA,MACjD,KAAA,EAAO,SAAS,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,KAAK,EAAE,CAAA;AAAA,MAC/C,UAAA,EAAY,SAAS,UAAA,CAAW,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,KAAK,EAAE,CAAA;AAAA,MACzD,SAAA,EAAW,SAAS,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,KAAK,EAAE,CAAA;AAAA,MACvD,KAAA,EAAO,SAAS,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,KAAK,EAAE,CAAA;AAAA,MAC/C,OAAA,EAAS,SAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,KAAK,EAAE,CAAA;AAAA,MACnD,WAAA,EAAa,SAAS,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,KAAK,EAAE,CAAA;AAAA,MAC3D,QAAA,EAAU,CAAA;AAAA;AAAA,MACV,KAAA,EAAO,CAAA;AAAA;AAAA,MACP,WAAA,EAAa;AAAA;AAAA,KACjB;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,WAAW,EAAA,EAA8C;AAE3D,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAAA,EA0BcA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAG3D,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,UAAA;AAAA,MACV,QAAQ,GAAA,CAAI,YAAA;AAAA,MACZ,WAAA,EAAa,QAAA,CAAS,GAAA,CAAI,YAAA,EAAc,EAAE,CAAA;AAAA,MAC1C,gBAAA,EAAkB,QAAA,CAAS,GAAA,CAAI,YAAA,EAAc,EAAE,CAAA,GAAI,CAAA,GAC7C,QAAA,CAAS,GAAA,CAAI,YAAA,EAAc,EAAE,CAAA,GAC7B;AAAA,KACV,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,UAAU,EAAA,EAA6C;AAEzD,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAAA,EAiBcA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAE3D,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,UAAA;AAAA,MACV,QAAQ,GAAA,CAAI,YAAA;AAAA,MACZ,WAAA,EAAa,QAAA,CAAS,GAAA,CAAI,YAAA,EAAc,EAAE,CAAA;AAAA,MAC1C,WAAA,EAAa,IAAI,YAAA,KAAiB;AAAA,KACtC,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,eAAe,EAAA,EAAkD;AAGnE,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAAA,EAWSA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAQtD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,OAAA;AAAA,MACV,QAAQ,GAAA,CAAI,OAAA;AAAA,MACZ,cAAA,EAAgB,QAAA,CAAS,GAAA,CAAI,WAAA,EAAa,EAAE;AAAA,KAChD,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,cAAc,EAAA,EAAiD;AAGjE,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAAA,EAaSA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAQtD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,OAAA;AAAA,MACV,QAAQ,GAAA,CAAI,OAAA;AAAA,MACZ,cAAA,EAAgB,QAAA,CAAS,GAAA,CAAI,WAAA,EAAa,EAAE,CAAA;AAAA,MAC5C,YAAY,GAAA,CAAI;AAAA,KACpB,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,UAAU,EAAA,EAA6C;AAKzD,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAAA,EAoBSA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAatD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,OAAA;AAAA,MACV,QAAQ,GAAA,CAAI,OAAA;AAAA,MACZ,IAAA,EAAM,GAAA,CAAI,OAAA,KAAY,GAAA,GAChB,MAAA,GACA,GAAA,CAAI,OAAA,KAAY,GAAA,GACZ,WAAA,GACA,GAAA,CAAI,OAAA,KAAY,GAAA,GACZ,QAAA,GACA,OAAA;AAAA,MACd,YAAY,GAAA,CAAI,WAAA,GAAc,SAAS,GAAA,CAAI,WAAA,EAAa,EAAE,CAAA,GAAI;AAAA,KAClE,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,YAAY,EAAA,EAA8C;AAG5D,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uCAAA,EAyBYA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAEzD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AAE5B,MAAA,MAAM,YAAY,GAAA,CAAI,UAAA;AACtB,MAAA,MAAM,QAAA,GAAW,GAAA,CAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,IAAK,SAAA;AAGpD,MAAA,MAAM,YAAA,GAAe,GAAA,CAAI,QAAA,CAAS,KAAA,CAAM,aAAa,CAAA;AACrD,MAAA,MAAM,UAAU,YAAA,GAAe,CAAC,CAAA,GAC1B,YAAA,CAAa,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,EAAE,IAAA,EAAM,IAC9C,EAAC;AAEP,MAAA,OAAO;AAAA,QACH,MAAM,GAAA,CAAI,SAAA;AAAA,QACV,QAAQ,GAAA,CAAI,UAAA;AAAA,QACZ,WAAW,GAAA,CAAI,SAAA;AAAA,QACf,aAAa,GAAA,CAAI,UAAA;AAAA,QACjB,OAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA,OACJ;AAAA,IAEJ,CAAC,CAAA;AAAA,EAEL,CAAA;AAAA,EAEA,MAAM,gBAAgB,EAAA,EAAmD;AAErE,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wCAAA,EAgCaA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAE1D,QAAQ,EAAE,CAAA;AAGZ,IAAA,MAAM,KAAA,uBAAY,GAAA,EAA+B;AAEjD,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAE3B,MAAA,MAAM,MAAM,CAAA,EAAG,GAAA,CAAI,YAAY,CAAA,CAAA,EAAI,IAAI,eAAe,CAAA,CAAA;AAEtD,MAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,EAAG;AAEjB,QAAA,KAAA,CAAM,IAAI,GAAA,EAAK;AAAA,UACX,MAAM,GAAA,CAAI,eAAA;AAAA,UACV,QAAQ,GAAA,CAAI,YAAA;AAAA,UACZ,WAAW,GAAA,CAAI,UAAA;AAAA,UACf,aAAa,GAAA,CAAI,YAAA;AAAA,UACjB,OAAA,EAAS,CAAC,GAAA,CAAI,WAAW,CAAA;AAAA,UACzB,iBAAiB,GAAA,CAAI,kBAAA;AAAA,UACrB,kBAAkB,GAAA,CAAI,oBAAA;AAAA,UACtB,iBAAA,EAAmB,CAAC,GAAA,CAAI,mBAAmB,CAAA;AAAA,UAC3C,UAAU,GAAA,CAAI,WAAA;AAAA,UACd,UAAU,GAAA,CAAI;AAAA,SACjB,CAAA;AAAA,MAEL,CAAA,MACK;AAED,QAAA,MAAM,EAAA,GAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AACxB,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AAC/B,QAAA,EAAA,CAAG,iBAAA,CAAkB,IAAA,CAAK,GAAA,CAAI,mBAAmB,CAAA;AAAA,MAErD;AAAA,IAEJ;AAEA,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,CAAA;AAAA,EAEpC,CAAA;AAAA,EAEA,MAAM,cAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,QAAA,EACkB;AAG3B,IAAA,MAAM,gBAAgB,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAcD,MAAM;AAAA,6BAAA,EACV,IAAI;AAAA;AAAA,QAAA,CAAA,CAEzB,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,aAAA,CAAc,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAEjC,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,WAAW,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAAA,EAOK,MAAM;AAAA,gCAAA,EACR,IAAI;AAAA,QAAA,CAAA,CAC5B,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,QAAA,CAAS,IAAA,CAAK,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAC,CAAA;AAGjE,IAAA,MAAM,oBAAoB,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA,+BAAA,EAIP,IAAI;AAAA,6BAAA,EACN,MAAM;AAAA,QAAA,CAAA,CAC3B,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,WAAA,GAAc,SAAS,iBAAA,CAAkB,IAAA,CAAK,CAAC,CAAA,EAAG,SAAA,IAAa,KAAK,EAAE,CAAA;AAE5E,IAAA,MAAM,OAAA,GAA0B,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7D,MAAM,GAAA,CAAI,WAAA;AAAA,MACV,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,UAAA,EAAY,IAAI,WAAA,KAAgB,KAAA;AAAA,MAChC,YAAA,EAAc,IAAI,cAAA,IAAkB,MAAA;AAAA,MACpC,YAAA,EAAc,SAAA,CAAU,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA;AAAA,MAC3C,eAAA,EAAiB,QAAA,CAAS,GAAA,CAAI,gBAAA,EAAkB,EAAE;AAAA,KACtD,CAAE,CAAA;AAGF,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,WAAA,CAAY,EAAE,CAAA;AAC5C,IAAA,MAAM,UAAU,UAAA,CAAW,MAAA;AAAA,MACvB,CAAC,GAAA,KAAQ,GAAA,CAAI,SAAA,KAAc,IAAA,IAAQ,IAAI,WAAA,KAAgB;AAAA,KAC3D;AAGA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,eAAA,CAAgB,EAAE,CAAA;AAC5C,IAAA,MAAM,cAAc,MAAA,CAAO,MAAA;AAAA,MACvB,CAAC,EAAA,KAAO,EAAA,CAAG,SAAA,KAAc,IAAA,IAAQ,GAAG,WAAA,KAAgB;AAAA,KACxD;AAEA,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAA;AAAA,MACA,gBAAA,EAAkB,WAAA,GAAc,CAAA,GAAI,WAAA,GAAc;AAAA,KACtD;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,aAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,QAAA,EACiB;AAG1B,IAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA;AAAA;AAAA,iCAAA,EAME,MAAM;AAAA,6BAAA,EACV,IAAI;AAAA,QAAA,CAAA,CACzB,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,UAAA,CAAW,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAE9B,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,gBAAgB,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAcD,MAAM;AAAA,6BAAA,EACV,IAAI;AAAA;AAAA,QAAA,CAAA,CAEzB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAA0B,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7D,MAAM,GAAA,CAAI,WAAA;AAAA,MACV,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,UAAA,EAAY,IAAI,WAAA,KAAgB,KAAA;AAAA,MAChC,YAAA,EAAc,IAAI,cAAA,IAAkB,MAAA;AAAA,MACpC,YAAA,EAAc,KAAA;AAAA,MACd,eAAA,EAAiB,QAAA,CAAS,GAAA,CAAI,gBAAA,EAAkB,EAAE;AAAA,KACtD,CAAE,CAAA;AAEF,IAAA,MAAM,OAAA,GAAU,UAAA,CAAW,IAAA,CAAK,CAAC,CAAA;AAEjC,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAA,EAAY,SAAS,eAAA,IAAmB,MAAA;AAAA,MACxC,WAAA,EAAa,SAAS,YAAA,KAAiB;AAAA,KAC3C;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,kBAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,QAAA,EACsB;AAE/B,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA,8BAAA,EAOG,MAAM;AAAA,4BAAA,EACR,IAAI;AAAA;AAAA,QAAA,CAAA,CAExB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAE7B,IAAA,IAAI,CAAC,OAAA,EAAS;AAEV,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,MAAM,OAAA,CAAQ,GAAA;AAGpB,IAAA,MAAM,eAAe,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAAA,EAcG,MAAM;AAAA,gCAAA,EACV,QAAQA,GAAAA,CAAI,GAAA,CAAI,CAAA,OAAA,EAAU,GAAG,EAAE,CAAC;AAAA;AAAA,QAAA,CAAA,CAExD,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,UAAA,GAAgC,YAAA,CAAa,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAClE,IAAA,EAAM,GAAA,CAAI,cAAA,IAAkB,CAAA,CAAA,EAAI,IAAI,gBAAgB,CAAA,CAAA;AAAA,MACpD,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,MAAM,GAAA,CAAI,cAAA;AAAA,MACV,YAAA,EAAc,IAAI,iBAAA,IAAqB,MAAA;AAAA,MACvC,eAAA,EAAiB,QAAA,CAAS,GAAA,CAAI,gBAAA,EAAkB,EAAE;AAAA,KACtD,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAY,OAAA,CAAQ;AAAA,KACxB;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,iBAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,QAAA,EACqB;AAE9B,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAA,EAcG,MAAM;AAAA,4BAAA,EACR,IAAI;AAAA;AAAA,QAAA,CAAA,CAExB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAE7B,IAAA,IAAI,CAAC,OAAA,EAAS;AAEV,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,MAAM,OAAA,CAAQ,GAAA;AAGpB,IAAA,MAAM,eAAe,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAAA,EAcG,MAAM;AAAA,gCAAA,EACV,IAAA,GAAO,MAAM,GAAG;AAAA;AAAA;AAAA,QAAA,CAAA,CAGxC,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,UAAA,GAAgC,YAAA,CAAa,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAClE,IAAA,EAAM,GAAA,CAAI,cAAA,IAAkB,CAAA,CAAA,EAAI,IAAI,gBAAgB,CAAA,CAAA;AAAA,MACpD,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,MAAM,GAAA,CAAI,cAAA;AAAA,MACV,YAAA,EAAc,IAAI,iBAAA,IAAqB,MAAA;AAAA,MACvC,eAAA,EAAiB,QAAA,CAAS,GAAA,CAAI,gBAAA,EAAkB,EAAE;AAAA,KACtD,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAY,OAAA,CAAQ,WAAA;AAAA,MACpB,YAAY,OAAA,CAAQ,MAAA;AAAA,MACpB,UAAU,OAAA,CAAQ;AAAA,KACtB;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,aAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,QAAA,EACiB;AAE1B,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAA,EAcG,MAAM;AAAA,4BAAA,EACR,IAAI;AAAA;AAAA,QAAA,CAAA,CAExB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAE7B,IAAA,IAAI,CAAC,OAAA,EAAS;AAEV,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,KAAY,GAAA,GAC3B,MAAA,GACA,OAAA,CAAQ,OAAA,KAAY,GAAA,GAChB,WAAA,GACA,OAAA,CAAQ,OAAA,KAAY,GAAA,GAChB,QAAA,GACA,OAAA;AAEd,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI,UAAA;AAEJ,IAAA,IAAI,SAAS,MAAA,EAAQ;AAEjB,MAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA;AAAA;AAAA,kCAAA,EAGD,QAAQ,GAAG,CAAA;AAAA;AAAA,YAAA,CAAA,CAEjC,QAAQ,EAAE,CAAA;AAEZ,MAAA,MAAA,GAAS,WAAW,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,SAAS,CAAA;AAAA,IAEnD,CAAA,MAAA,IACS,SAAS,WAAA,EAAa;AAE3B,MAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mCAAA,EAaA,QAAQ,GAAG,CAAA;AAAA;AAAA;AAAA,YAAA,CAAA,CAGlC,QAAQ,EAAE,CAAA;AAEZ,MAAA,UAAA,GAAa,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QACrC,MAAM,CAAA,CAAE,OAAA;AAAA,QACR,UAAU,CAAA,CAAE,OAAA;AAAA,QACZ,UAAA,EAAY,CAAC,CAAA,CAAE,UAAA;AAAA,QACf,YAAA,EAAc,KAAA;AAAA,QACd,eAAA,EAAiB,QAAA,CAAS,CAAA,CAAE,MAAA,EAAQ,EAAE;AAAA,OAC1C,CAAE,CAAA;AAAA,IAEN;AAEA,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA,QAAA,EAAU,QAAQ,QAAA,IAAY;AAAA,KAClC;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,aAAa,EAAA,EAAgD;AAE/D,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAAA,EAgBcA,GAAAA,CAAI,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAE3D,QAAQ,EAAE,CAAA;AAGZ,IAAA,MAAM,UAAA,uBAAiB,GAAA,EAA4B;AAEnD,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAE3B,MAAA,MAAM,MAAM,CAAA,EAAG,GAAA,CAAI,cAAc,CAAA,CAAA,EAAI,IAAI,YAAY,CAAA,CAAA;AACrD,MAAA,MAAM,QAAA,GAAW,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA;AAEnC,MAAA,IAAI,QAAA,EAAU;AAEV,QAAA,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,kBAAoD,CAAA;AAAA,MAEjF,CAAA,MACK;AAED,QAAA,UAAA,CAAW,IAAI,GAAA,EAAK;AAAA,UAChB,MAAM,GAAA,CAAI,YAAA;AAAA,UACV,QAAQ,GAAA,CAAI,cAAA;AAAA,UACZ,WAAW,GAAA,CAAI,kBAAA;AAAA,UACf,aAAa,GAAA,CAAI,mBAAA;AAAA,UACjB,QAAQ,GAAA,CAAI,aAAA;AAAA,UACZ,MAAA,EAAQ,CAAC,GAAA,CAAI,kBAAoD;AAAA,SACpE,CAAA;AAAA,MAEL;AAAA,IAEJ;AAEA,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,MAAA,EAAQ,CAAA;AAAA,EAEzC,CAAA;AAAA,EAEA,MAAM,UAAU,EAAA,EAA6C;AAEzD,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAgBnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,KAAK,GAAA,CAAI,GAAA;AAAA,MACT,UAAU,GAAA,CAAI,QAAA;AAAA,MACd,UAAA,EAAY,IAAI,QAAA,IAAY,MAAA;AAAA,MAC5B,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,SAAS,GAAA,CAAI;AAAA,KACjB,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,gBAAgB,EAAA,EAAmD;AAErE,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAqBnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,KAAK,GAAA,CAAI,GAAA;AAAA,MACT,UAAU,GAAA,CAAI,OAAA;AAAA,MACd,UAAU,GAAA,CAAI,OAAA;AAAA,MACd,eAAA,EAAiB,IAAI,gBAAA,IAAoB,MAAA;AAAA,MACzC,aAAA,EAAe,IAAI,WAAA,IAAe,MAAA;AAAA,MAClC,cAAc,GAAA,CAAI,aAAA;AAAA,MAClB,OAAO,GAAA,CAAI;AAAA,KACf,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,gBAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,QAAA,EACoB;AAE7B,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAcM,IAAI;AAAA,iCAAA,EACJ,MAAM;AAAA,QAAA,CAAA,CAC/B,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAE1B,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,SAAS,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA,KAAM,EAAE,kBAAkB,CAAA;AAC1D,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAEzB,IAAA,OAAO;AAAA,MACH,MAAM,GAAA,CAAI,YAAA;AAAA,MACV,MAAA;AAAA,MACA,WAAW,GAAA,CAAI,kBAAA;AAAA,MACf,WAAA,EAAa,MAAA;AAAA,MACb,QAAQ,GAAA,CAAI,aAAA;AAAA,MACZ,MAAA;AAAA,MACA,YAAY,GAAA,CAAI,gBAAA;AAAA,MAChB,SAAA,EAAW;AAAA;AAAA,KACf;AAAA,EAEJ;AAEJ,CAAA;ACz9BO,IAAM,sBAAA,GAAmD;AAAA,EAE5D,MAAM,YAAY,EAAA,EAA+C;AAG7D,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAErC,IAAA,IAAI,CAAC,MAAA,EAAQ;AAET,MAAA,OAAO;AAAA,QACH,MAAA,EAAQ,CAAA;AAAA,QACR,KAAA,EAAO,CAAA;AAAA,QACP,UAAA,EAAY,CAAA;AAAA,QACZ,SAAA,EAAW,CAAA;AAAA,QACX,KAAA,EAAO,CAAA;AAAA,QACP,OAAA,EAAS,CAAA;AAAA,QACT,WAAA,EAAa,CAAA;AAAA,QACb,QAAA,EAAU,CAAA;AAAA,QACV,KAAA,EAAO,CAAA;AAAA,QACP,WAAA,EAAa;AAAA,OACjB;AAAA,IAEJ;AAEA,IAAA,MAAM,CAAC,MAAA,EAAQ,KAAA,EAAO,UAAA,EAAY,SAAA,EAAW,SAAS,WAAW,CAAA,GAC7D,MAAM,OAAA,CAAQ,GAAA,CAAI;AAAA,MACdA,GAAAA;AAAA;AAAA;AAAA,yCAAA,EAG2B,MAAM;AAAA;AAAA,gBAAA,CAAA,CAE/B,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA,yCAAA,EAG2B,MAAM;AAAA,gBAAA,CAAA,CAC/B,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA,2CAAA,EAG6B,MAAM;AAAA;AAAA,gBAAA,CAAA,CAEjC,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA,2CAAA,EAG6B,MAAM;AAAA;AAAA,gBAAA,CAAA,CAEjC,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA,yCAAA,EAG2B,MAAM;AAAA,gBAAA,CAAA,CAC/B,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA,8CAAA,EAGgC,MAAM;AAAA;AAAA,gBAAA,CAAA,CAEpC,QAAQ,EAAE;AAAA,KACf,CAAA;AAEL,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,QAAA,CAAS,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,GAAG,CAAA,EAAG,EAAE,CAAA;AAAA,MACzD,KAAA,EAAO,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,GAAG,CAAA,EAAG,EAAE,CAAA;AAAA,MACvD,UAAA,EAAY,QAAA,CAAS,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,GAAG,CAAA,EAAG,EAAE,CAAA;AAAA,MACjE,SAAA,EAAW,QAAA,CAAS,MAAA,CAAO,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,GAAG,CAAA,EAAG,EAAE,CAAA;AAAA,MAC/D,KAAA,EAAO,CAAA;AAAA;AAAA,MACP,OAAA,EAAS,QAAA,CAAS,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,GAAG,CAAA,EAAG,EAAE,CAAA;AAAA,MAC3D,WAAA,EAAa,QAAA,CAAS,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,IAAS,GAAG,CAAA,EAAG,EAAE,CAAA;AAAA,MACnE,QAAA,EAAU,CAAA;AAAA;AAAA,MACV,KAAA,EAAO,CAAA;AAAA;AAAA,MACP,WAAA,EAAa;AAAA;AAAA,KACjB;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,WAAW,EAAA,EAA8C;AAE3D,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAErC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mCAAA,EAiBQ,MAAM;AAAA;AAAA;AAAA,QAAA,CAAA,CAGjC,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,UAAA;AAAA,MACV,QAAQ,GAAA,CAAI,YAAA;AAAA,MACZ,aAAa,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,YAAY,GAAG,EAAE,CAAA;AAAA,MAClD,gBAAA,EAAkB,IAAI,UAAA,GAChB,QAAA,CAAS,OAAO,GAAA,CAAI,UAAU,CAAA,EAAG,EAAE,CAAA,GACnC;AAAA,KACV,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,UAAU,EAAA,EAA6C;AAEzD,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAErC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mCAAA,EAiBQ,MAAM;AAAA;AAAA,QAAA,CAAA,CAEjC,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,UAAA;AAAA,MACV,QAAQ,GAAA,CAAI,YAAA;AAAA,MACZ,aAAa,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,YAAY,GAAG,EAAE,CAAA;AAAA,MAClD,WAAA,EAAa,IAAI,YAAA,KAAiB;AAAA,KACtC,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,eAAe,EAAA,EAAkD;AAEnE,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAErC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qCAAA,EAgBU,MAAM;AAAA;AAAA;AAAA,QAAA,CAAA,CAGnC,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,YAAA;AAAA,MACV,QAAQ,GAAA,CAAI,cAAA;AAAA,MACZ,gBAAgB,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,WAAW,GAAG,EAAE;AAAA,KACxD,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,cAAc,EAAA,EAAiD;AAEjE,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAErC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qCAAA,EAkBU,MAAM;AAAA;AAAA;AAAA,QAAA,CAAA,CAGnC,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,YAAA;AAAA,MACV,QAAQ,GAAA,CAAI,cAAA;AAAA,MACZ,gBAAgB,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,WAAW,GAAG,EAAE,CAAA;AAAA,MACpD,YAAY,GAAA,CAAI;AAAA,KACpB,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,UAAU,GAAA,EAA8C;AAG1D,IAAA,OAAO,EAAC;AAAA,EAEZ,CAAA;AAAA,EAEA,MAAM,YAAY,EAAA,EAA8C;AAE5D,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAErC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAcM,MAAM;AAAA;AAAA,QAAA,CAAA,CAE/B,QAAQ,EAAE,CAAA;AAGZ,IAAA,MAAM,QAAA,uBAAe,GAAA,EAA0B;AAE/C,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAE3B,MAAA,MAAM,MAAM,CAAA,EAAG,GAAA,CAAI,UAAU,CAAA,CAAA,EAAI,IAAI,UAAU,CAAA,CAAA;AAE/C,MAAA,IAAI,CAAC,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA,EAAG;AAEpB,QAAA,QAAA,CAAS,IAAI,GAAA,EAAK;AAAA,UACd,MAAM,GAAA,CAAI,UAAA;AAAA,UACV,MAAA,EAAQ,MAAA;AAAA,UACR,WAAW,GAAA,CAAI,UAAA;AAAA,UACf,WAAA,EAAa,MAAA;AAAA,UACb,OAAA,EAAS,CAAC,GAAA,CAAI,WAAW,CAAA;AAAA,UACzB,QAAA,EAAU,IAAI,UAAA,KAAe,CAAA;AAAA,UAC7B,SAAA,EAAW,IAAI,UAAA,KAAe;AAAA,SACjC,CAAA;AAAA,MAEL,CAAA,MACK;AAED,QAAA,QAAA,CAAS,IAAI,GAAG,CAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,IAAI,WAAW,CAAA;AAAA,MAEnD;AAAA,IAEJ;AAEA,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,MAAA,EAAQ,CAAA;AAAA,EAEvC,CAAA;AAAA,EAEA,MAAM,gBAAgB,EAAA,EAAmD;AAErE,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAErC,IAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0CAAA,EAqBe,MAAM;AAAA;AAAA;AAAA,QAAA,CAAA,CAGxC,QAAQ,EAAE,CAAA;AAGZ,IAAA,MAAM,KAAA,uBAAY,GAAA,EAA+B;AAEjD,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAE3B,MAAA,MAAM,MAAM,CAAA,EAAG,GAAA,CAAI,UAAU,CAAA,CAAA,EAAI,IAAI,eAAe,CAAA,CAAA;AAEpD,MAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,EAAG;AAEjB,QAAA,KAAA,CAAM,IAAI,GAAA,EAAK;AAAA,UACX,MAAM,GAAA,CAAI,eAAA;AAAA,UACV,MAAA,EAAQ,MAAA;AAAA,UACR,WAAW,GAAA,CAAI,UAAA;AAAA,UACf,WAAA,EAAa,MAAA;AAAA,UACb,OAAA,EAAS,CAAC,GAAA,CAAI,WAAW,CAAA;AAAA,UACzB,iBAAiB,GAAA,CAAI,qBAAA;AAAA,UACrB,gBAAA,EAAkB,MAAA;AAAA,UAClB,iBAAA,EAAmB,CAAC,GAAA,CAAI,sBAAsB,CAAA;AAAA,UAC9C,UAAU,GAAA,CAAI,WAAA;AAAA,UACd,UAAU,GAAA,CAAI;AAAA,SACjB,CAAA;AAAA,MAEL,CAAA,MACK;AAED,QAAA,MAAM,EAAA,GAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AACxB,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AAC/B,QAAA,EAAA,CAAG,iBAAA,CAAkB,IAAA,CAAK,GAAA,CAAI,sBAAsB,CAAA;AAAA,MAExD;AAAA,IAEJ;AAEA,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,CAAA;AAAA,EAEpC,CAAA;AAAA,EAEA,MAAM,cAAA,CACF,EAAA,EACA,IAAA,EACA,MAAA,EAC2B;AAE3B,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,MAAA,IAAU,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAE/C,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAGpB,IAAA,MAAM,gBAAgB,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAgBD,MAAM;AAAA,6BAAA,EACV,IAAI;AAAA;AAAA,QAAA,CAAA,CAEzB,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,aAAA,CAAc,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAEjC,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,OAAA,GAA0B,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7D,MAAM,GAAA,CAAI,WAAA;AAAA,MACV,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,UAAA,EAAY,IAAI,WAAA,KAAgB,KAAA;AAAA,MAChC,YAAA,EAAc,IAAI,cAAA,IAAkB,MAAA;AAAA,MACpC,YAAA,EAAc,IAAI,UAAA,KAAe,KAAA;AAAA,MACjC,iBAAiB,GAAA,CAAI;AAAA,KACzB,CAAE,CAAA;AAGF,IAAA,MAAM,YAAY,MAAMA,GAAAA;AAAA;AAAA;AAAA,iCAAA,EAGG,MAAM;AAAA,6BAAA,EACV,IAAI;AAAA,QAAA,CAAA,CACzB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,WAAA,GAAc,SAAA,CAAU,IAAA,CAAK,CAAC,GAAG,UAAA,GACjC,QAAA,CAAS,MAAA,CAAO,SAAA,CAAU,KAAK,CAAC,CAAA,CAAE,UAAU,CAAA,EAAG,EAAE,CAAA,GACjD,MAAA;AAGN,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,WAAA,CAAY,EAAE,CAAA;AAC5C,IAAA,MAAM,UAAU,UAAA,CAAW,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,CAAI,cAAc,IAAI,CAAA;AAGjE,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,eAAA,CAAgB,EAAE,CAAA;AAC5C,IAAA,MAAM,cAAc,MAAA,CAAO,MAAA,CAAO,CAAC,EAAA,KAAO,EAAA,CAAG,cAAc,IAAI,CAAA;AAE/D,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAA;AAAA,MACA,gBAAA,EAAkB;AAAA,KACtB;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,aAAA,CACF,EAAA,EACA,IAAA,EACA,MAAA,EAC0B;AAE1B,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,MAAA,IAAU,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAE/C,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAGpB,IAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA;AAAA;AAAA,iCAAA,EAME,MAAM;AAAA,6BAAA,EACV,IAAI;AAAA,QAAA,CAAA,CACzB,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,UAAA,CAAW,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAE9B,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,gBAAgB,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAcD,MAAM;AAAA,6BAAA,EACV,IAAI;AAAA;AAAA,QAAA,CAAA,CAEzB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAA0B,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7D,MAAM,GAAA,CAAI,WAAA;AAAA,MACV,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,UAAA,EAAY,IAAI,WAAA,KAAgB,KAAA;AAAA,MAChC,YAAA,EAAc,IAAI,cAAA,IAAkB,MAAA;AAAA,MACpC,YAAA,EAAc,KAAA;AAAA,MACd,iBAAiB,GAAA,CAAI;AAAA,KACzB,CAAE,CAAA;AAEF,IAAA,MAAM,OAAA,GAAU,UAAA,CAAW,IAAA,CAAK,CAAC,CAAA;AAEjC,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA;AAAA,MACA,UAAA,EAAY,SAAS,eAAA,IAAmB,MAAA;AAAA,MACxC,WAAA,EAAa,SAAS,YAAA,KAAiB;AAAA,KAC3C;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,kBAAA,CACF,EAAA,EACA,IAAA,EACA,MAAA,EAC+B;AAE/B,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,MAAA,IAAU,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAE/C,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA,mCAAA,EAMQ,MAAM;AAAA,+BAAA,EACV,IAAI;AAAA;AAAA,QAAA,CAAA,CAE3B,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAE7B,IAAA,IAAI,CAAC,OAAA,EAAS;AAEV,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,eAAe,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAAA,EAYG,MAAM;AAAA,gCAAA,EACV,QAAQ,aAAa;AAAA;AAAA;AAAA,QAAA,CAAA,CAG7C,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,UAAA,GAAgC,YAAA,CAAa,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAClE,IAAA,EAAM,GAAA,CAAI,cAAA,IAAkB,CAAA,KAAA,EAAQ,IAAI,gBAAgB,CAAA,CAAA;AAAA,MACxD,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,IAAA,EAAO,IAAI,cAAA,IAAkB,IAAA;AAAA,MAC7B,iBAAiB,GAAA,CAAI;AAAA,KACzB,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA,EAAQ,MAAA;AAAA,MACR,UAAA;AAAA,MACA,UAAA,EAAY,QAAQ,kBAAA,IAAsB;AAAA,KAC9C;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,iBAAA,CACF,EAAA,EACA,IAAA,EACA,MAAA,EAC8B;AAE9B,IAAA,MAAM,YAAA,GAAe,MAAMA,GAAAA,CAAAA,uBAAAA,CAAAA,CAA6C,OAAA,CAAQ,EAAE,CAAA;AAClF,IAAA,MAAM,MAAA,GAAS,MAAA,IAAU,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,EAAG,EAAA;AAE/C,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA,mCAAA,EAOQ,MAAM;AAAA,+BAAA,EACV,IAAI;AAAA;AAAA,QAAA,CAAA,CAE3B,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAE7B,IAAA,IAAI,CAAC,OAAA,EAAS;AAEV,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,eAAe,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAAA,EAYG,MAAM;AAAA,gCAAA,EACV,QAAQ,aAAa;AAAA;AAAA;AAAA,QAAA,CAAA,CAG7C,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,UAAA,GAAgC,YAAA,CAAa,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAClE,IAAA,EAAM,GAAA,CAAI,cAAA,IAAkB,CAAA,KAAA,EAAQ,IAAI,gBAAgB,CAAA,CAAA;AAAA,MACxD,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,IAAA,EAAO,IAAI,cAAA,IAAkB,IAAA;AAAA,MAC7B,iBAAiB,GAAA,CAAI;AAAA,KACzB,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA,EAAQ,MAAA;AAAA,MACR,UAAA;AAAA,MACA,YAAY,OAAA,CAAQ,SAAA;AAAA,MACpB,UAAA,EAAY,QAAQ,kBAAA,IAAsB;AAAA,KAC9C;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,aAAA,CACF,GAAA,EACA,KAAA,EACA,OAAA,EAC0B;AAG1B,IAAA,OAAO,IAAA;AAAA,EAEX,CAAA;AAAA,EAEA,MAAM,aAAa,EAAA,EAAgD;AAE/D,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAgBnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,YAAA;AAAA,MACV,QAAQ,GAAA,CAAI,cAAA;AAAA,MACZ,WAAW,GAAA,CAAI,kBAAA;AAAA,MACf,aAAa,GAAA,CAAI,cAAA;AAAA,MACjB,QAAQ,GAAA,CAAI,aAAA;AAAA,MACZ,MAAA,EAAQ,CAAC,GAAA,CAAI,kBAAoD;AAAA,KACrE,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,UAAU,EAAA,EAA6C;AAIzD,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMlB,OAAAA;AAAA,MAAQ,MAChCkB,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAA,CAAA,CAgBE,QAAQ,EAAE;AAAA,KAChB;AAGA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,OAAO,EAAC;AAAA,IAEZ;AAEA,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,KAAK,GAAA,CAAI,eAAA;AAAA,MACT,UAAU,GAAA,CAAI,WAAA;AAAA,MACd,UAAA,EAAY,IAAI,WAAA,IAAe,MAAA;AAAA,MAC/B,MAAM,GAAA,CAAI,SAAA;AAAA,MACV,OAAA,EAAS,IAAI,WAAA,KAAgB;AAAA,KACjC,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,gBAAgB,EAAA,EAAmD;AAErE,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAmBnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,KAAK,GAAA,CAAI,EAAA;AAAA,MACT,UAAU,GAAA,CAAI,IAAA;AAAA,MACd,UAAU,GAAA,CAAI,EAAA;AAAA,MACd,eAAe,GAAA,CAAI,IAAA;AAAA,MACnB,KAAA,EAAO,IAAI,KAAA,IAAS;AAAA,KACxB,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,gBAAA,CACF,EAAA,EACA,IAAA,EACA,MAAA,EAC6B;AAE7B,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAcM,IAAI;AAAA;AAAA,QAAA,CAAA,CAE7B,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAE1B,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAEzB,IAAA,OAAO;AAAA,MACH,MAAM,GAAA,CAAI,YAAA;AAAA,MACV,QAAQ,MAAA,IAAU,MAAA;AAAA,MAClB,WAAW,GAAA,CAAI,kBAAA;AAAA,MACf,WAAA,EAAa,MAAA;AAAA,MACb,QAAQ,GAAA,CAAI,aAAA;AAAA,MACZ,MAAA,EAAQ,CAAC,GAAA,CAAI,kBAAkB,CAAA;AAAA,MAC/B,YAAY,GAAA,CAAI,gBAAA;AAAA,MAChB,SAAA,EAAW;AAAA,KACf;AAAA,EAEJ;AAEJ,CAAA;AC3yBA,IAAMC,iBAAAA,GAAmB,CAAC,KAAA,EAAO,oBAAA,EAAsB,OAAO,CAAA;AAKvD,IAAM,sBAAA,GAAmD;AAAA,EAE5D,MAAM,YAAY,EAAA,EAA+C;AAE7D,IAAA,MAAM,CAAC,MAAA,EAAQ,KAAA,EAAO,UAAA,EAAY,SAAA,EAAW,KAAA,EAAO,OAAA,EAAS,WAAW,CAAA,GACpE,MAAM,OAAA,CAAQ,GAAA,CAAI;AAAA,MACdD,GAAAA;AAAA;AAAA;AAAA;AAAA,yCAAA,EAI2BA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACnD,QAAQ,EAAE,CAAA;AAAA,MAEZD,GAAAA;AAAA;AAAA;AAAA;AAAA,yCAAA,EAI2BA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACnD,QAAQ,EAAE,CAAA;AAAA,MAEZD,GAAAA;AAAA;AAAA;AAAA;AAAA,yCAAA,EAI2BA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACnD,QAAQ,EAAE,CAAA;AAAA,MAEZD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uCAAA,EAKyBA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACjD,QAAQ,EAAE,CAAA;AAAA,MAEZD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uCAAA,EAKyBA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACjD,QAAQ,EAAE,CAAA;AAAA,MAEZD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uCAAA,EAMyBA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACjD,QAAQ,EAAE,CAAA;AAAA,MAEZD,GAAAA;AAAA;AAAA;AAAA;AAAA,yCAAA,EAI2BA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA,gBAAA,CAAA,CACnD,QAAQ,EAAE;AAAA,KACf,CAAA;AAEL,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MACjC,KAAA,EAAO,KAAA,CAAM,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MAC/B,UAAA,EAAY,UAAA,CAAW,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MACzC,SAAA,EAAW,SAAA,CAAU,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MACvC,KAAA,EAAO,KAAA,CAAM,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MAC/B,OAAA,EAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MACnC,WAAA,EAAa,WAAA,CAAY,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MAC3C,QAAA,EAAU,CAAA;AAAA;AAAA,MACV,KAAA,EAAO,CAAA;AAAA;AAAA,MACP,WAAA,EAAa;AAAA;AAAA,KACjB;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,WAAW,EAAA,EAA8C;AAE3D,IAAA,MAAM,SAAS,MAAMD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAkBMA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAEnD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,UAAA;AAAA,MACV,QAAQ,GAAA,CAAI,WAAA;AAAA,MACZ,aAAa,GAAA,CAAI,YAAA;AAAA,MACjB,gBAAA,EAAkB,GAAA,CAAI,SAAA,GAAY,CAAA,GAAI,IAAI,SAAA,GAAY;AAAA,KAC1D,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,UAAU,EAAA,EAA6C;AAEzD,IAAA,MAAM,SAAS,MAAMD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAeMA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAEnD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,SAAA;AAAA,MACV,QAAQ,GAAA,CAAI,WAAA;AAAA,MACZ,aAAa,GAAA,CAAI,YAAA;AAAA,MACjB,WAAA,EAAa;AAAA;AAAA,KACjB,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,eAAe,EAAA,EAAkD;AAEnE,IAAA,MAAM,SAAS,MAAMD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAgBMA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAEnD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,SAAA;AAAA,MACV,QAAQ,GAAA,CAAI,WAAA;AAAA,MACZ,gBAAgB,GAAA,CAAI;AAAA,KACxB,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,cAAc,EAAA,EAAiD;AAEjE,IAAA,MAAM,SAAS,MAAMD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAAA,EAwBIA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAEjD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,SAAA;AAAA,MACV,QAAQ,GAAA,CAAI,WAAA;AAAA,MACZ,gBAAgB,GAAA,CAAI,WAAA;AAAA,MACpB,YAAY,GAAA,CAAI;AAAA,KACpB,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,UAAU,EAAA,EAA6C;AAEzD,IAAA,MAAM,SAAS,MAAMD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAAA,EAYIA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAEjD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,SAAA;AAAA,MACV,QAAQ,GAAA,CAAI,WAAA;AAAA,MACZ,IAAA,EAAM,GAAA,CAAI,aAAA,GAAgB,WAAA,GAAc;AAAA,KAC5C,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,YAAY,EAAA,EAA8C;AAE5D,IAAA,MAAM,SAAS,MAAMD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAAA,EAqBIA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAGjD,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,MAAM,GAAA,CAAI,UAAA;AAAA,MACV,QAAQ,GAAA,CAAI,WAAA;AAAA,MACZ,WAAW,GAAA,CAAI,UAAA;AAAA,MACf,aAAa,GAAA,CAAI,WAAA;AAAA,MACjB,OAAA,EAAS,GAAA,CAAI,YAAA,CAAa,KAAA,CAAM,IAAI,CAAA;AAAA,MACpC,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,WAAW,GAAA,CAAI;AAAA,KACnB,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,gBAAgB,EAAA,EAAmD;AAErE,IAAA,MAAM,SAAS,MAAMD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAuCMA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAEnD,QAAQ,EAAE,CAAA;AAGZ,IAAA,MAAM,KAAA,uBAAY,GAAA,EAA+B;AAEjD,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAE3B,MAAA,MAAM,MAAM,CAAA,EAAG,GAAA,CAAI,WAAW,CAAA,CAAA,EAAI,IAAI,OAAO,CAAA,CAAA;AAE7C,MAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,EAAG;AAEjB,QAAA,KAAA,CAAM,IAAI,GAAA,EAAK;AAAA,UACX,MAAM,GAAA,CAAI,OAAA;AAAA,UACV,QAAQ,GAAA,CAAI,WAAA;AAAA,UACZ,WAAW,GAAA,CAAI,UAAA;AAAA,UACf,aAAa,GAAA,CAAI,WAAA;AAAA,UACjB,OAAA,EAAS,CAAC,GAAA,CAAI,WAAW,CAAA;AAAA,UACzB,iBAAiB,GAAA,CAAI,SAAA;AAAA,UACrB,kBAAkB,GAAA,CAAI,UAAA;AAAA,UACtB,iBAAA,EAAmB,CAAC,GAAA,CAAI,UAAU,CAAA;AAAA,UAClC,UAAU,GAAA,CAAI,aAAA;AAAA,UACd,UAAU,GAAA,CAAI;AAAA,SACjB,CAAA;AAAA,MAEL,CAAA,MACK;AAED,QAAA,MAAM,EAAA,GAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AACxB,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AAC/B,QAAA,EAAA,CAAG,iBAAA,CAAkB,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA;AAAA,MAE5C;AAAA,IAEJ;AAEA,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,CAAA;AAAA,EAEpC,CAAA;AAAA,EAEA,MAAM,cAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,KAAA,EACkB;AAG3B,IAAA,MAAM,gBAAgB,MAAMD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAA,EAkBP,IAAI;AAAA,yBAAA,EACN,MAAM;AAAA;AAAA,QAAA,CAAA,CAEvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,aAAA,CAAc,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAEjC,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,WAAW,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAA,EAQJ,IAAI;AAAA,yBAAA,EACJ,MAAM;AAAA,QAAA,CAAA,CACvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,QAAA,CAAS,IAAA,CAAK,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAC,CAAA;AAGjE,IAAA,MAAM,YAAY,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAA,EAML,IAAI;AAAA,yBAAA,EACJ,MAAM;AAAA,QAAA,CAAA,CACvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAA0B,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7D,MAAM,GAAA,CAAI,WAAA;AAAA,MACV,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,YAAY,GAAA,CAAI,WAAA;AAAA,MAChB,YAAA,EAAc,IAAI,cAAA,IAAkB,MAAA;AAAA,MACpC,YAAA,EAAc,SAAA,CAAU,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA;AAAA,MAC3C,iBAAiB,GAAA,CAAI;AAAA,KACzB,CAAE,CAAA;AAGF,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,WAAA,CAAY,EAAE,CAAA;AAC5C,IAAA,MAAM,UAAU,UAAA,CAAW,MAAA;AAAA,MACvB,CAAC,GAAA,KAAQ,GAAA,CAAI,SAAA,KAAc,IAAA,IAAQ,IAAI,WAAA,KAAgB;AAAA,KAC3D;AAGA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,eAAA,CAAgB,EAAE,CAAA;AAC5C,IAAA,MAAM,cAAc,MAAA,CAAO,MAAA;AAAA,MACvB,CAAC,EAAA,KAAO,EAAA,CAAG,SAAA,KAAc,IAAA,IAAQ,GAAG,WAAA,KAAgB;AAAA,KACxD;AAEA,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAA;AAAA,MACA,gBAAA,EAAkB,SAAA,CAAU,IAAA,CAAK,CAAC,GAAG,SAAA,IAAa;AAAA,KACtD;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,aAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,KAAA,EACiB;AAG1B,IAAA,MAAM,YAAY,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA,2BAAA,EAIH,IAAI;AAAA,yBAAA,EACN,MAAM;AAAA,QAAA,CAAA,CACvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,SAAA,CAAU,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAE7B,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,gBAAgB,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAA,EAcP,IAAI;AAAA,yBAAA,EACN,MAAM;AAAA;AAAA,QAAA,CAAA,CAEvB,QAAQ,EAAE,CAAA;AAGZ,IAAA,MAAM,YAAY,MAAMA,GAAAA;AAAA,+CAAA,EACiB,MAAA,GAAS,MAAM,IAAI,CAAA;AAAA,QAAA,CAAA,CAC1D,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAA0B,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7D,MAAM,GAAA,CAAI,WAAA;AAAA,MACV,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,YAAY,GAAA,CAAI,WAAA;AAAA,MAChB,YAAA,EAAc,KAAA;AAAA,MACd,iBAAiB,GAAA,CAAI;AAAA,KACzB,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAA,EAAY,SAAA,CAAU,IAAA,CAAK,CAAC,GAAG,UAAA,IAAc,MAAA;AAAA,MAC7C,WAAA,EAAa;AAAA,KACjB;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,kBAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,KAAA,EACsB;AAG/B,IAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA,2BAAA,EAIJ,IAAI;AAAA,yBAAA,EACN,MAAM;AAAA,QAAA,CAAA,CACvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAAU,UAAA,CAAW,IAAA,CAAK,CAAC,CAAA;AAEjC,IAAA,IAAI,CAAC,OAAA,EAAS;AAEV,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,eAAe,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAA,EAgBN,IAAI;AAAA,yBAAA,EACN,MAAM;AAAA;AAAA;AAAA,QAAA,CAAA,CAGvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,UAAA,GAAgC,YAAA,CAAa,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAClE,IAAA,EAAM,GAAA,CAAI,cAAA,CAAe,OAAA,CAAQ,MAAM,EAAE,CAAA;AAAA,MACzC,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,IAAA,EAAM,GAAA,CAAI,SAAA,GAAY,KAAA,GAAQ,IAAA;AAAA,MAC9B,iBAAiB,GAAA,CAAI;AAAA,KACzB,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA,EAAY,QAAQ,UAAA,IAAc;AAAA,KACtC;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,iBAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,KAAA,EACqB;AAG9B,IAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAA,EASJ,IAAI;AAAA,yBAAA,EACN,MAAM;AAAA;AAAA,QAAA,CAAA,CAEvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAAU,UAAA,CAAW,IAAA,CAAK,CAAC,CAAA;AAEjC,IAAA,IAAI,CAAC,OAAA,EAAS;AAEV,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,eAAe,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAA,EAYN,IAAI;AAAA,yBAAA,EACN,MAAM;AAAA;AAAA;AAAA,QAAA,CAAA,CAGvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,UAAA,GAAgC,YAAA,CAAa,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAClE,IAAA,EAAM,GAAA,CAAI,cAAA,CAAe,OAAA,CAAQ,MAAM,EAAE,CAAA;AAAA,MACzC,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,IAAA,EAAM,IAAA;AAAA,MACN,iBAAiB,GAAA,CAAI;AAAA,KACzB,CAAE,CAAA;AAEF,IAAA,MAAM,UAAA,GAAa,QAAQ,SAAA,KAAc,IAAA,GACnC,WACA,OAAA,CAAQ,SAAA,KAAc,OAClB,cAAA,GACA,OAAA;AAEV,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA,EAAY,QAAQ,UAAA,IAAc;AAAA,KACtC;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,aAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,KAAA,EACiB;AAE1B,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAA,EASA,IAAI;AAAA,yBAAA,EACN,MAAM;AAAA;AAAA,QAAA,CAAA,CAEvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAEzB,IAAA,IAAI,CAAC,GAAA,EAAK;AAEN,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,IAAI,UAAA;AAEJ,IAAA,IAAI,IAAI,aAAA,EAAe;AAGnB,MAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gCAAA,EAcH,IAAI;AAAA,6BAAA,EACP,MAAM;AAAA;AAAA,YAAA,CAAA,CAEvB,QAAQ,EAAE,CAAA;AAEZ,MAAA,UAAA,GAAa,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QACrC,MAAM,CAAA,CAAE,WAAA;AAAA,QACR,UAAU,CAAA,CAAE,SAAA;AAAA,QACZ,YAAY,CAAA,CAAE,WAAA;AAAA,QACd,YAAA,EAAc,KAAA;AAAA,QACd,iBAAiB,CAAA,CAAE;AAAA,OACvB,CAAE,CAAA;AAAA,IAEN;AAEA,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA,EAAM,GAAA,CAAI,aAAA,GAAgB,WAAA,GAAc,QAAA;AAAA,MACxC,UAAA;AAAA,MACA,QAAA,EAAU,IAAI,SAAA,IAAa;AAAA,KAC/B;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,aAAa,EAAA,EAAgD;AAE/D,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAA,EAmBMA,GAAAA,CAAI,IAAA,CAAKC,iBAAgB,CAAC,CAAA;AAAA;AAAA,QAAA,CAAA,CAEnD,QAAQ,EAAE,CAAA;AAGZ,IAAA,MAAM,UAAA,uBAAiB,GAAA,EAA4B;AAEnD,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAE3B,MAAA,MAAM,MAAM,CAAA,EAAG,GAAA,CAAI,WAAW,CAAA,CAAA,EAAI,IAAI,YAAY,CAAA,CAAA;AAClD,MAAA,MAAM,QAAQ,GAAA,CAAI,SAAA;AAClB,MAAA,MAAM,QAAA,GAAW,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA;AAEnC,MAAA,IAAI,QAAA,EAAU;AAEV,QAAA,IAAI,CAAC,QAAA,CAAS,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAElC,UAAA,QAAA,CAAS,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,QAE9B;AAAA,MAEJ,CAAA,MACK;AAED,QAAA,UAAA,CAAW,IAAI,GAAA,EAAK;AAAA,UAChB,MAAM,GAAA,CAAI,YAAA;AAAA,UACV,QAAQ,GAAA,CAAI,WAAA;AAAA,UACZ,WAAW,GAAA,CAAI,UAAA;AAAA,UACf,aAAa,GAAA,CAAI,WAAA;AAAA,UACjB,MAAA,EAAQ,GAAA,CAAI,qBAAA,GAAwB,YAAA,GAAe,OAAA;AAAA,UACnD,MAAA,EAAQ,CAAC,KAAK;AAAA,SACjB,CAAA;AAAA,MAEL;AAAA,IAEJ;AAEA,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,MAAA,EAAQ,CAAA;AAAA,EAEzC,CAAA;AAAA,EAEA,MAAM,UAAU,EAAA,EAA6C;AAEzD,IAAA,MAAM,SAAS,MAAMD,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAgBnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,KAAK,GAAA,CAAI,kBAAA;AAAA,MACT,UAAU,GAAA,CAAI,aAAA;AAAA,MACd,UAAA,EAAY,IAAI,oBAAA,IAAwB,MAAA;AAAA,MACxC,MAAM,GAAA,CAAI,YAAA;AAAA,MACV,OAAA,EAAS,IAAI,cAAA,KAAmB;AAAA,KACpC,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,gBAAgB,EAAA,EAAmD;AAErE,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAmBnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC7B,KAAK,GAAA,CAAI,UAAA;AAAA,MACT,UAAU,GAAA,CAAI,UAAA;AAAA,MACd,QAAA,EAAU,SAAA;AAAA,MACV,eAAA,EAAiB,IAAI,YAAA,IAAgB,MAAA;AAAA,MACrC,aAAA,EAAe,IAAI,SAAA,IAAa,MAAA;AAAA,MAChC,cAAc,GAAA,CAAI,UAAA;AAAA,MAClB,OAAO,GAAA,CAAI;AAAA,KACf,CAAE,CAAA;AAAA,EAEN,CAAA;AAAA,EAEA,MAAM,gBAAA,CACF,EAAA,EACA,IAAA,EACA,SAAS,KAAA,EACoB;AAE7B,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAA,EAmBA,IAAI;AAAA,yBAAA,EACN,MAAM;AAAA,QAAA,CAAA,CACvB,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAE1B,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,MAAA,GAAS,CAAC,GAAG,IAAI,GAAA,CAAI,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAC,CAAC,CAAA;AAC/D,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAEzB,IAAA,OAAO;AAAA,MACH,MAAM,GAAA,CAAI,YAAA;AAAA,MACV,MAAA;AAAA,MACA,WAAW,GAAA,CAAI,UAAA;AAAA,MACf,WAAA,EAAa,MAAA;AAAA,MACb,MAAA,EAAQ,GAAA,CAAI,qBAAA,GAAwB,YAAA,GAAe,OAAA;AAAA,MACnD,MAAA;AAAA,MACA,YAAY,GAAA,CAAI,UAAA;AAAA,MAChB,SAAA,EAAW,CAAC,GAAA,CAAI;AAAA,KACpB;AAAA,EAEJ;AAEJ,CAAA;ACh4BO,IAAM,uBAAA,GAAoD;AAAA,EAE7D,MAAM,YAAY,EAAA,EAA+C;AAE7D,IAAA,MAAM,CAAC,MAAA,EAAQ,KAAA,EAAO,OAAO,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MAC/CA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAA,CAAA,CAKE,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA;AAAA,YAAA,CAAA,CAIE,QAAQ,EAAE,CAAA;AAAA,MAEZA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAA,CAAA,CAKE,QAAQ,EAAE;AAAA,KACf,CAAA;AAGD,IAAA,MAAM,eAAe,MAAMA,GAAAA;AAAA;AAAA,QAAA,CAAA,CAEzB,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,OAAA,GAAU,CAAA;AAEd,IAAA,KAAA,MAAW,KAAA,IAAS,aAAa,IAAA,EAAM;AAEnC,MAAA,MAAM,MAAM,MAAMA,GAAAA;AAAA,wCAAA,EACYA,IAAI,GAAA,CAAI,CAAA,CAAA,EAAI,KAAA,CAAM,IAAI,GAAG,CAAC,CAAA;AAAA,YAAA,CAAA,CACtD,QAAQ,EAAE,CAAA;AAGZ,MAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AACnD,MAAA,OAAA,IAAW,SAAA,CAAU,IAAA;AAAA,IAEzB;AAEA,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MACjC,KAAA,EAAO,KAAA,CAAM,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MAC/B,UAAA,EAAY,CAAA;AAAA;AAAA,MACZ,SAAA,EAAW,CAAA;AAAA;AAAA,MACX,KAAA,EAAO,CAAA;AAAA;AAAA,MACP,OAAA,EAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,GAAG,KAAA,IAAS,CAAA;AAAA,MACnC,WAAA,EAAa,OAAA;AAAA,MACb,QAAA,EAAU,CAAA;AAAA;AAAA,MACV,KAAA,EAAO,CAAA;AAAA;AAAA,MACP,WAAA,EAAa;AAAA;AAAA,KACjB;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,WAAW,EAAA,EAA8C;AAE3D,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAMnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,SAAyB,EAAC;AAEhC,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAG3B,MAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA,kCAAA,EACDA,IAAI,GAAA,CAAI,CAAA,CAAA,EAAI,GAAA,CAAI,IAAI,GAAG,CAAC,CAAA;AAAA,YAAA,CAAA,CAC9C,QAAQ,EAAE,CAAA;AAGZ,MAAA,MAAM,cAAc,MAAMA,GAAAA;AAAA,8CAAA,EACUA,IAAI,GAAA,CAAI,CAAA,CAAA,EAAI,GAAA,CAAI,IAAI,GAAG,CAAC;AAAA,YAAA,CAAA,CAC1D,QAAQ,EAAE,CAAA;AAEZ,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACR,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,WAAA,EAAa,WAAW,IAAA,CAAK,MAAA;AAAA,QAC7B,gBAAA,EAAkB,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,EAAG;AAAA,OAC1C,CAAA;AAAA,IAEL;AAEA,IAAA,OAAO,MAAA;AAAA,EAEX,CAAA;AAAA,EAEA,MAAM,UAAU,EAAA,EAA6C;AAEzD,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAKnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,QAAuB,EAAC;AAE9B,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAG3B,MAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA,kCAAA,EACDA,IAAI,GAAA,CAAI,CAAA,CAAA,EAAI,GAAA,CAAI,IAAI,GAAG,CAAC,CAAA;AAAA,YAAA,CAAA,CAC9C,QAAQ,EAAE,CAAA;AAEZ,MAAA,KAAA,CAAM,IAAA,CAAK;AAAA,QACP,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,WAAA,EAAa,WAAW,IAAA,CAAK,MAAA;AAAA,QAC7B,WAAA,EAAa;AAAA;AAAA,OAChB,CAAA;AAAA,IAEL;AAEA,IAAA,OAAO,KAAA;AAAA,EAEX,CAAA;AAAA,EAEA,MAAM,eAAe,GAAA,EAAmD;AAGpE,IAAA,OAAO,EAAC;AAAA,EAEZ,CAAA;AAAA,EAEA,MAAM,cAAc,GAAA,EAAkD;AAGlE,IAAA,OAAO,EAAC;AAAA,EAEZ,CAAA;AAAA,EAEA,MAAM,UAAU,GAAA,EAA8C;AAG1D,IAAA,OAAO,EAAC;AAAA,EAEZ,CAAA;AAAA,EAEA,MAAM,YAAY,EAAA,EAA8C;AAE5D,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAUnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,UAA0B,EAAC;AAEjC,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAG3B,MAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA,kCAAA,EAKDA,IAAI,GAAA,CAAI,CAAA,CAAA,EAAI,GAAA,CAAI,IAAI,GAAG,CAAC,CAAA;AAAA,YAAA,CAAA,CAC9C,QAAQ,EAAE,CAAA;AAEZ,MAAA,MAAM,UAAU,UAAA,CAAW,IAAA,CAAK,IAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AACjD,MAAA,MAAM,WAAW,GAAA,CAAI,GAAA,EAAK,aAAY,CAAE,QAAA,CAAS,QAAQ,CAAA,IAAK,KAAA;AAC9D,MAAA,MAAM,SAAA,GAAY,GAAA,CAAI,IAAA,CAAK,UAAA,CAAW,mBAAmB,CAAA;AAEzD,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACT,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,WAAW,GAAA,CAAI,QAAA;AAAA,QACf,OAAA;AAAA,QACA,UAAU,QAAA,IAAY,SAAA;AAAA,QACtB;AAAA,OACH,CAAA;AAAA,IAEL;AAEA,IAAA,OAAO,OAAA;AAAA,EAEX,CAAA;AAAA,EAEA,MAAM,gBAAgB,EAAA,EAAmD;AAErE,IAAA,MAAM,eAAe,MAAMA,GAAAA;AAAA;AAAA,QAAA,CAAA,CAEzB,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,cAAmC,EAAC;AAE1C,IAAA,KAAA,MAAW,KAAA,IAAS,aAAa,IAAA,EAAM;AAEnC,MAAA,MAAM,YAAY,MAAMA,GAAAA;AAAA,wCAAA,EASMA,IAAI,GAAA,CAAI,CAAA,CAAA,EAAI,KAAA,CAAM,IAAI,GAAG,CAAC,CAAA;AAAA,YAAA,CAAA,CACtD,QAAQ,EAAE,CAAA;AAGZ,MAAA,MAAM,KAAA,uBAAY,GAAA,EAA+B;AAEjD,MAAA,KAAA,MAAW,GAAA,IAAO,UAAU,IAAA,EAAM;AAE9B,QAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,EAAG;AAEpB,UAAA,KAAA,CAAM,GAAA,CAAI,IAAI,EAAA,EAAI;AAAA,YACd,MAAM,CAAA,GAAA,EAAM,KAAA,CAAM,IAAI,CAAA,CAAA,EAAI,IAAI,EAAE,CAAA,CAAA;AAAA,YAChC,WAAW,KAAA,CAAM,IAAA;AAAA,YACjB,OAAA,EAAS,CAAC,GAAA,CAAI,IAAI,CAAA;AAAA,YAClB,iBAAiB,GAAA,CAAI,KAAA;AAAA,YACrB,iBAAA,EAAmB,CAAC,GAAA,CAAI,EAAE,CAAA;AAAA,YAC1B,UAAU,GAAA,CAAI,SAAA;AAAA,YACd,UAAU,GAAA,CAAI;AAAA,WACjB,CAAA;AAAA,QAEL,CAAA,MACK;AAED,UAAA,MAAM,EAAA,GAAK,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA;AAC3B,UAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AACxB,UAAA,EAAA,CAAG,iBAAA,CAAkB,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA;AAAA,QAEpC;AAAA,MAEJ;AAEA,MAAA,WAAA,CAAY,IAAA,CAAK,GAAG,KAAA,CAAM,MAAA,EAAQ,CAAA;AAAA,IAEtC;AAEA,IAAA,OAAO,WAAA;AAAA,EAEX,CAAA;AAAA,EAEA,MAAM,cAAA,CACF,EAAA,EACA,IAAA,EACA,OAAA,EAC2B;AAG3B,IAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA,2EAAA,EAC4C,IAAI;AAAA,QAAA,CAAA,CACvE,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,UAAA,CAAW,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAE9B,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA,8BAAA,EAQDA,GAAAA,CAAI,GAAA,CAAI,CAAA,CAAA,EAAI,IAAI,GAAG,CAAC,CAAA;AAAA,QAAA,CAAA,CAC1C,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAA0B,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC1D,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,QAAA,EAAU,IAAI,IAAA,IAAQ,KAAA;AAAA,MACtB,UAAA,EAAY,IAAI,OAAA,KAAY,CAAA;AAAA,MAC5B,YAAA,EAAc,IAAI,UAAA,IAAc,MAAA;AAAA,MAChC,YAAA,EAAc,IAAI,EAAA,GAAK,CAAA;AAAA,MACvB,eAAA,EAAiB,IAAI,GAAA,GAAM;AAAA,KAC/B,CAAE,CAAA;AAGF,IAAA,MAAM,cAAc,MAAMA,GAAAA;AAAA,0CAAA,EACUA,GAAAA,CAAI,GAAA,CAAI,CAAA,CAAA,EAAI,IAAI,GAAG,CAAC;AAAA,QAAA,CAAA,CACtD,QAAQ,EAAE,CAAA;AAGZ,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,WAAA,CAAY,EAAE,CAAA;AAC5C,IAAA,MAAM,UAAU,UAAA,CAAW,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,CAAI,cAAc,IAAI,CAAA;AAGjE,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,eAAA,CAAgB,EAAE,CAAA;AAC5C,IAAA,MAAM,cAAc,MAAA,CAAO,MAAA,CAAO,CAAC,EAAA,KAAO,EAAA,CAAG,cAAc,IAAI,CAAA;AAE/D,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAA;AAAA,MACA,gBAAA,EAAkB,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,EAAG;AAAA,KAC3C;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,aAAA,CACF,EAAA,EACA,IAAA,EACA,OAAA,EAC0B;AAG1B,IAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA,yEAAA,EAC0C,IAAI;AAAA,QAAA,CAAA,CACrE,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAAU,UAAA,CAAW,IAAA,CAAK,CAAC,CAAA;AAEjC,IAAA,IAAI,CAAC,OAAA,EAAS;AAEV,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,aAAa,MAAMA,GAAAA;AAAA,8BAAA,EAODA,GAAAA,CAAI,GAAA,CAAI,CAAA,CAAA,EAAI,IAAI,GAAG,CAAC,CAAA;AAAA,QAAA,CAAA,CAC1C,QAAQ,EAAE,CAAA;AAEZ,IAAA,MAAM,OAAA,GAA0B,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,MAC1D,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,QAAA,EAAU,IAAI,IAAA,IAAQ,KAAA;AAAA,MACtB,UAAA,EAAY,IAAI,OAAA,KAAY,CAAA;AAAA,MAC5B,YAAA,EAAc,IAAI,UAAA,IAAc,MAAA;AAAA,MAChC,YAAA,EAAc,KAAA;AAAA,MACd,eAAA,EAAiB,IAAI,GAAA,GAAM;AAAA,KAC/B,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACH,IAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAA,EAAY,QAAQ,GAAA,IAAO,MAAA;AAAA,MAC3B,WAAA,EAAa;AAAA,KACjB;AAAA,EAEJ,CAAA;AAAA,EAEA,MAAM,kBAAA,CACF,GAAA,EACA,KAAA,EACA,OAAA,EAC+B;AAG/B,IAAA,OAAO,IAAA;AAAA,EAEX,CAAA;AAAA,EAEA,MAAM,iBAAA,CACF,GAAA,EACA,KAAA,EACA,OAAA,EAC8B;AAG9B,IAAA,OAAO,IAAA;AAAA,EAEX,CAAA;AAAA,EAEA,MAAM,aAAA,CACF,GAAA,EACA,KAAA,EACA,OAAA,EAC0B;AAG1B,IAAA,OAAO,IAAA;AAAA,EAEX,CAAA;AAAA,EAEA,MAAM,aAAa,EAAA,EAAgD;AAE/D,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CASnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AAG5B,MAAA,MAAM,QAAA,GAAW,GAAA,CAAI,GAAA,CAAI,WAAA,EAAY;AACrC,MAAA,IAAI,MAAA,GAA4C,OAAA;AAEhD,MAAA,IAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,EAAG;AAE7B,QAAA,MAAA,GAAS,QAAA;AAAA,MAEb,CAAA,MAAA,IACS,QAAA,CAAS,QAAA,CAAS,YAAY,CAAA,EAAG;AAEtC,QAAA,MAAA,GAAS,YAAA;AAAA,MAEb;AAEA,MAAA,MAAM,SAA6C,EAAC;AAEpD,MAAA,IAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,EAAG;AAE7B,QAAA,MAAA,CAAO,KAAK,QAAQ,CAAA;AAAA,MAExB;AAEA,MAAA,IAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,EAAG;AAE7B,QAAA,MAAA,CAAO,KAAK,QAAQ,CAAA;AAAA,MAExB;AAEA,MAAA,IAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,EAAG;AAE7B,QAAA,MAAA,CAAO,KAAK,QAAQ,CAAA;AAAA,MAExB;AAEA,MAAA,OAAO;AAAA,QACH,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,WAAW,GAAA,CAAI,QAAA;AAAA,QACf,MAAA;AAAA,QACA,QAAQ,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,MAAA,GAAS,CAAC,QAAQ;AAAA,OAClD;AAAA,IAEJ,CAAC,CAAA;AAAA,EAEL,CAAA;AAAA,EAEA,MAAM,UAAU,GAAA,EAA8C;AAG1D,IAAA,OAAO,EAAC;AAAA,EAEZ,CAAA;AAAA,EAEA,MAAM,gBAAgB,GAAA,EAAoD;AAGtE,IAAA,OAAO,EAAC;AAAA,EAEZ,CAAA;AAAA,EAEA,MAAM,gBAAA,CACF,EAAA,EACA,IAAA,EAC6B;AAE7B,IAAA,MAAM,SAAS,MAAMA,GAAAA;AAAA;AAAA;AAAA;AAAA,uBAAA,EAQJ,IAAI;AAAA,QAAA,CAAA,CACnB,QAAQ,EAAE,CAAA;AAEZ,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAE1B,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAEzB,IAAA,MAAM,QAAA,GAAW,GAAA,CAAI,GAAA,CAAI,WAAA,EAAY;AACrC,IAAA,IAAI,MAAA,GAAS,OAAA;AAEb,IAAA,IAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,EAAG;AAE7B,MAAA,MAAA,GAAS,QAAA;AAAA,IAEb,CAAA,MAAA,IACS,QAAA,CAAS,QAAA,CAAS,YAAY,CAAA,EAAG;AAEtC,MAAA,MAAA,GAAS,YAAA;AAAA,IAEb;AAEA,IAAA,MAAM,SAAmB,EAAC;AAE1B,IAAA,IAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,EAAG;AAE7B,MAAA,MAAA,CAAO,KAAK,QAAQ,CAAA;AAAA,IAExB;AAEA,IAAA,IAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,EAAG;AAE7B,MAAA,MAAA,CAAO,KAAK,QAAQ,CAAA;AAAA,IAExB;AAEA,IAAA,IAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,EAAG;AAE7B,MAAA,MAAA,CAAO,KAAK,QAAQ,CAAA;AAAA,IAExB;AAEA,IAAA,OAAO;AAAA,MACH,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,WAAW,GAAA,CAAI,QAAA;AAAA,MACf,MAAA;AAAA,MACA,QAAQ,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,MAAA,GAAS,CAAC,QAAQ,CAAA;AAAA,MAC9C,YAAY,GAAA,CAAI,GAAA;AAAA,MAChB,SAAA,EAAW;AAAA;AAAA,KACf;AAAA,EAEJ;AAEJ,CAAA;;;AC9iBA,IAAM,iBAAA,GAA+D;AAAA,EACjE,QAAA,EAAU,yBAAA;AAAA,EACV,KAAA,EAAO,sBAAA;AAAA,EACP,KAAA,EAAO,sBAAA;AAAA,EACP,MAAA,EAAQ;AACZ,CAAA;AAcO,SAAS,qBAAqB,OAAA,EAA4C;AAE7E,EAAA,OAAO,kBAAkB,OAAO,CAAA;AAEpC;;;ACMA,SAAS,aAAa,IAAA,EAA0C;AAE5D,EAAA,OAAO,IAAA,EAAM,UAAA,CAAW,UAAU,CAAA,IAAK,KAAA;AAE3C;AAgBA,eAAsB,aAAA,CAClB,EAAA,EACA,OAAA,EACA,OAAA,GAA0B,EAAC,EACH;AAExB,EAAA,MAAM,GAAA,GAAM,qBAAqB,OAAO,CAAA;AAGxC,EAAA,IAAI,CAAC,QAAQ,kBAAA,EAAoB;AAE7B,IAAA,MAAM,CAAC,MAAA,EAAQ,KAAA,EAAO,UAAA,EAAY,WAAW,KAAA,EAAO,OAAA,EAAS,WAAA,EAAa,QAAA,EAAU,KAAA,EAAO,WAAW,CAAA,GAClG,MAAM,QAAQ,GAAA,CAAI;AAAA,MACd,GAAA,CAAI,WAAW,EAAE,CAAA;AAAA,MACjB,GAAA,CAAI,UAAU,EAAE,CAAA;AAAA,MAChB,GAAA,CAAI,eAAe,EAAE,CAAA;AAAA,MACrB,GAAA,CAAI,cAAc,EAAE,CAAA;AAAA,MACpB,GAAA,CAAI,UAAU,EAAE,CAAA;AAAA,MAChB,GAAA,CAAI,YAAY,EAAE,CAAA;AAAA,MAClB,GAAA,CAAI,gBAAgB,EAAE,CAAA;AAAA,MACtB,GAAA,CAAI,aAAa,EAAE,CAAA;AAAA,MACnB,GAAA,CAAI,UAAU,EAAE,CAAA;AAAA,MAChB,GAAA,CAAI,gBAAgB,EAAE;AAAA,KACzB,CAAA;AAEL,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,YAAA,CAAa,CAAA,CAAE,IAAI,CAAC,CAAA,CAAE,MAAA;AAAA,MACpD,OAAO,KAAA,CAAM,MAAA;AAAA,MACb,YAAY,UAAA,CAAW,MAAA;AAAA,MACvB,WAAW,SAAA,CAAU,MAAA;AAAA,MACrB,OAAO,KAAA,CAAM,MAAA;AAAA,MACb,OAAA,EAAS,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,YAAA,CAAa,CAAA,CAAE,SAAS,CAAC,CAAA,CAAE,MAAA;AAAA,MAC3D,WAAA,EAAa,WAAA,CAAY,MAAA,CAAO,CAAC,EAAA,KAAO,CAAC,YAAA,CAAa,EAAA,CAAG,SAAS,CAAC,CAAA,CAAE,MAAA;AAAA,MACrE,QAAA,EAAU,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,YAAA,CAAa,CAAA,CAAE,SAAS,CAAC,CAAA,CAAE,MAAA;AAAA,MAC7D,OAAO,KAAA,CAAM,MAAA;AAAA,MACb,aAAa,WAAA,CAAY;AAAA,KAC7B;AAAA,EAEJ;AAEA,EAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMlB,QAAQ,MAAM,GAAA,CAAI,WAAA,CAAY,EAAE,CAAC,CAAA;AAE7D,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,SAAA,EAAW,KAAA,EAAO,KAAK,CAAA;AACxD,IAAA,MAAM,GAAA;AAAA,EAEV;AAEA,EAAA,OAAO,MAAA;AAEX;AAmCA,eAAsB,UAClB,EAAA,EACA,OAAA,EACA,QAAA,EACA,OAAA,GAA0B,EAAC,EACF;AAEzB,EAAA,MAAM,GAAA,GAAM,qBAAqB,OAAO,CAAA;AAExC,EAAA,MAAM,SAAA,GAA6D;AAAA,IAC/D,MAAA,EAAQ,MAAM,GAAA,CAAI,UAAA,CAAW,EAAE,CAAA;AAAA,IAC/B,KAAA,EAAO,MAAM,GAAA,CAAI,SAAA,CAAU,EAAE,CAAA;AAAA,IAC7B,UAAA,EAAY,MAAM,GAAA,CAAI,cAAA,CAAe,EAAE,CAAA;AAAA,IACvC,SAAA,EAAW,MAAM,GAAA,CAAI,aAAA,CAAc,EAAE,CAAA;AAAA,IACrC,KAAA,EAAO,MAAM,GAAA,CAAI,SAAA,CAAU,EAAE,CAAA;AAAA,IAC7B,OAAA,EAAS,MAAM,GAAA,CAAI,WAAA,CAAY,EAAE,CAAA;AAAA,IACjC,WAAA,EAAa,MAAM,GAAA,CAAI,eAAA,CAAgB,EAAE,CAAA;AAAA,IACzC,QAAA,EAAU,MAAM,GAAA,CAAI,YAAA,CAAa,EAAE,CAAA;AAAA,IACnC,KAAA,EAAO,MAAM,GAAA,CAAI,SAAA,CAAU,EAAE,CAAA;AAAA,IAC7B,WAAA,EAAa,MAAM,GAAA,CAAI,eAAA,CAAgB,EAAE;AAAA,GAC7C;AAEA,EAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,QAAQ,MAAM,SAAA,CAAU,QAAQ,CAAA,EAAG,CAAA;AAE/D,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,SAAA,EAAW,KAAA,EAAO,KAAK,CAAA;AACxD,IAAA,MAAM,GAAA;AAAA,EAEV;AAGA,EAAA,IAAI,CAAC,QAAQ,kBAAA,EAAoB;AAE7B,IAAA,IAAI,aAAa,QAAA,EAAU;AAEvB,MAAA,OAAQ,MAAA,CAA0B,MAAA;AAAA,QAC9B,CAAC,CAAA,KAAM,CAAC,YAAA,CAAa,EAAE,IAAI;AAAA,OAC/B;AAAA,IAEJ;AAEA,IAAA,IAAI,aAAa,SAAA,EAAW;AAExB,MAAA,OAAQ,MAAA,CAA0B,MAAA;AAAA,QAC9B,CAAC,CAAA,KAAM,CAAC,YAAA,CAAa,EAAE,SAAS;AAAA,OACpC;AAAA,IAEJ;AAEA,IAAA,IAAI,aAAa,aAAA,EAAe;AAE5B,MAAA,OAAQ,MAAA,CAA+B,MAAA;AAAA,QACnC,CAAC,EAAA,KAAO,CAAC,YAAA,CAAa,GAAG,SAAS;AAAA,OACtC;AAAA,IAEJ;AAEA,IAAA,IAAI,aAAa,UAAA,EAAY;AAEzB,MAAA,OAAQ,MAAA,CAA4B,MAAA;AAAA,QAChC,CAAC,CAAA,KAAM,CAAC,YAAA,CAAa,EAAE,SAAS;AAAA,OACpC;AAAA,IAEJ;AAAA,EAEJ;AAEA,EAAA,OAAO,MAAA;AAEX;AAuCA,eAAsB,WAAA,CAClB,EAAA,EACA,OAAA,EACA,QAAA,EACA,MACA,MAAA,EACgC;AAEhC,EAAA,MAAM,GAAA,GAAM,qBAAqB,OAAO,CAAA;AAExC,EAAA,MAAM,SAAA,GAA4D;AAAA,IAC9D,QAAQ,MAAM,GAAA,CAAI,cAAA,CAAe,EAAA,EAAI,MAAM,MAAM,CAAA;AAAA,IACjD,OAAO,MAAM,GAAA,CAAI,aAAA,CAAc,EAAA,EAAI,MAAM,MAAM,CAAA;AAAA,IAC/C,YAAY,MAAM,GAAA,CAAI,kBAAA,CAAmB,EAAA,EAAI,MAAM,MAAM,CAAA;AAAA,IACzD,WAAW,MAAM,GAAA,CAAI,iBAAA,CAAkB,EAAA,EAAI,MAAM,MAAM,CAAA;AAAA,IACvD,OAAO,MAAM,GAAA,CAAI,aAAA,CAAc,EAAA,EAAI,MAAM,MAAM,CAAA;AAAA,IAC/C,UAAU,MAAM,GAAA,CAAI,gBAAA,CAAiB,EAAA,EAAI,MAAM,MAAM;AAAA,GACzD;AAEA,EAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,QAAQ,MAAM,SAAA,CAAU,QAAQ,CAAA,EAAG,CAAA;AAE/D,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,QAAQ,SAAA,EAAW,KAAA,EAAO,KAAK,CAAA;AACxD,IAAA,MAAM,GAAA;AAAA,EAEV;AAEA,EAAA,OAAO,MAAA;AAEX;;;ACzRA,SAAS,MAAM,IAAA,EAAsB;AAEjC,EAAA,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAA;AAEvC;AAKA,SAAS,aAAA,CAAc,MAAc,MAAA,EAAyB;AAE1D,EAAA,IAAI,MAAA,IAAU,WAAW,QAAA,EAAU;AAE/B,IAAA,OAAO,GAAG,KAAA,CAAM,MAAM,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,IAAI,CAAC,CAAA,CAAA;AAAA,EAE1C;AAEA,EAAA,OAAO,MAAM,IAAI,CAAA;AAErB;AAKO,IAAM,0BAAA,GAAwD;AAAA,EAEjE,uBAAA,GAAkC;AAG9B,IAAA,OAAO,0CAAA;AAAA,EAEX,CAAA;AAAA,EAEA,sBAAA,GAAiC;AAE7B,IAAA,OAAO,yCAAA;AAAA,EAEX,CAAA;AAAA,EAEA,aAAA,CAAc,SAAA,EAAmB,MAAA,EAAiB,eAAA,GAAkB,IAAA,EAAc;AAE9E,IAAA,MAAM,QAAA,GAAW,aAAA,CAAc,SAAA,EAAW,MAAM,CAAA;AAChD,IAAA,MAAM,OAAA,GAAU,kBAAkB,mBAAA,GAAsB,EAAA;AAGxD,IAAA,OAAO,CAAA,eAAA,EAAkB,QAAQ,CAAA,EAAG,OAAO,CAAA,QAAA,CAAA;AAAA,EAE/C,CAAA;AAAA,EAEA,SAAA,CAAU,WAAmB,MAAA,EAAyB;AAElD,IAAA,OAAO,CAAA,qBAAA,EAAwB,aAAA,CAAc,SAAA,EAAW,MAAM,CAAC,CAAA,QAAA,CAAA;AAAA,EAEnE,CAAA;AAAA,EAEA,QAAA,CAAS,UAAkB,MAAA,EAAyB;AAEhD,IAAA,OAAO,CAAA,oBAAA,EAAuB,aAAA,CAAc,QAAA,EAAU,MAAM,CAAC,CAAA,QAAA,CAAA;AAAA,EAEjE,CAAA;AAAA,EAEA,YAAA,CAAa,MAAc,MAAA,EAAyB;AAGhD,IAAA,OAAO,CAAA,wBAAA,EAA2B,aAAA,CAAc,IAAA,EAAM,MAAM,CAAC,CAAA,QAAA,CAAA;AAAA,EAEjE,CAAA;AAAA,EAEA,aAAA,CAAc,MAAc,MAAA,EAAyB;AAGjD,IAAA,OAAO,CAAA,yBAAA,EAA4B,aAAA,CAAc,IAAA,EAAM,MAAM,CAAC,CAAA,QAAA,CAAA;AAAA,EAElE,CAAA;AAAA,EAEA,QAAA,CAAS,UAAkB,MAAA,EAAyB;AAEhD,IAAA,OAAO,CAAA,oBAAA,EAAuB,aAAA,CAAc,QAAA,EAAU,MAAM,CAAC,CAAA,QAAA,CAAA;AAAA,EAEjE,CAAA;AAAA,EAEA,cAAA,CAAe,cAAA,EAAwB,SAAA,EAAmB,MAAA,EAAyB;AAE/E,IAAA,OAAO,CAAA,YAAA,EAAe,cAAc,SAAA,EAAW,MAAM,CAAC,CAAA,2BAAA,EAA8B,KAAA,CAAM,cAAc,CAAC,CAAA,CAAA;AAAA,EAE7G;AAEJ,CAAA;;;ACvFA,SAASoB,OAAM,IAAA,EAAsB;AAEjC,EAAA,OAAO,CAAA,EAAA,EAAK,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,EAAA,CAAA;AAExC;AAMA,SAASC,cAAAA,CAAc,MAAc,MAAA,EAAyB;AAE1D,EAAA,IAAI,MAAA,EAAQ;AAER,IAAA,OAAO,GAAGD,MAAAA,CAAM,MAAM,CAAC,CAAA,CAAA,EAAIA,MAAAA,CAAM,IAAI,CAAC,CAAA,CAAA;AAAA,EAE1C;AAEA,EAAA,OAAOA,OAAM,IAAI,CAAA;AAErB;AAKO,IAAM,uBAAA,GAAqD;AAAA,EAE9D,uBAAA,GAAkC;AAE9B,IAAA,OAAO,4BAAA;AAAA,EAEX,CAAA;AAAA,EAEA,sBAAA,GAAiC;AAE7B,IAAA,OAAO,4BAAA;AAAA,EAEX,CAAA;AAAA,EAEA,aAAA,CAAc,SAAA,EAAmB,MAAA,EAAiB,gBAAA,GAAmB,IAAA,EAAc;AAG/E,IAAA,OAAO,CAAA,eAAA,EAAkBC,cAAAA,CAAc,SAAA,EAAW,MAAM,CAAC,CAAA,CAAA;AAAA,EAE7D,CAAA;AAAA,EAEA,SAAA,CAAU,WAAmB,MAAA,EAAyB;AAElD,IAAA,OAAO,CAAA,qBAAA,EAAwBA,cAAAA,CAAc,SAAA,EAAW,MAAM,CAAC,CAAA,CAAA;AAAA,EAEnE,CAAA;AAAA,EAEA,QAAA,CAAS,UAAkB,MAAA,EAAyB;AAEhD,IAAA,OAAO,CAAA,oBAAA,EAAuBA,cAAAA,CAAc,QAAA,EAAU,MAAM,CAAC,CAAA,CAAA;AAAA,EAEjE,CAAA;AAAA,EAEA,YAAA,CAAa,MAAc,MAAA,EAAyB;AAGhD,IAAA,OAAO,CAAA,wBAAA,EAA2BA,cAAAA,CAAc,IAAA,EAAM,MAAM,CAAC,CAAA,CAAA;AAAA,EAEjE,CAAA;AAAA,EAEA,aAAA,CAAc,MAAc,MAAA,EAAyB;AAGjD,IAAA,OAAO,CAAA,yBAAA,EAA4BA,cAAAA,CAAc,IAAA,EAAM,MAAM,CAAC,CAAA,CAAA;AAAA,EAElE,CAAA;AAAA,EAEA,QAAA,CAAS,WAAmB,OAAA,EAA0B;AAGlD,IAAA,OAAO,wCAAA;AAAA,EAEX,CAAA;AAAA,EAEA,cAAA,CAAe,cAAA,EAAwB,SAAA,EAAmB,MAAA,EAAyB;AAE/E,IAAA,OAAO,CAAA,YAAA,EAAeA,eAAc,SAAA,EAAW,MAAM,CAAC,CAAA,kBAAA,EAAqBD,MAAAA,CAAM,cAAc,CAAC,CAAA,CAAA;AAAA,EAEpG;AAEJ,CAAA;;;ACrFA,SAASA,OAAM,IAAA,EAAsB;AAEjC,EAAA,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAC,CAAA,CAAA,CAAA;AAExC;AAKA,SAASC,cAAAA,CAAc,MAAc,MAAA,EAAyB;AAE1D,EAAA,IAAI,MAAA,IAAU,WAAW,KAAA,EAAO;AAE5B,IAAA,OAAO,GAAGD,MAAAA,CAAM,MAAM,CAAC,CAAA,CAAA,EAAIA,MAAAA,CAAM,IAAI,CAAC,CAAA,CAAA;AAAA,EAE1C;AAEA,EAAA,OAAOA,OAAM,IAAI,CAAA;AAErB;AAQO,IAAM,uBAAA,GAAqD;AAAA,EAE9D,uBAAA,GAAkC;AAI9B,IAAA,OAAO,+DAAA;AAAA,EAEX,CAAA;AAAA,EAEA,sBAAA,GAAiC;AAE7B,IAAA,OAAO,6DAAA;AAAA,EAEX,CAAA;AAAA,EAEA,aAAA,CAAc,SAAA,EAAmB,MAAA,EAAiB,eAAA,GAAkB,IAAA,EAAc;AAI9E,IAAA,MAAM,SAAA,GAAYC,cAAAA,CAAc,SAAA,EAAW,MAAM,CAAA;AACjD,IAAA,MAAM,UAAA,GAAa,eAAe,SAAS,CAAA,CAAA;AAG3C,IAAA,IAAI,eAAA,EAAiB;AAIjB,MAAA,MAAM,QAAA,GAAW,UAAU,MAAA,KAAW,KAAA,GAChC,GAAG,MAAM,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,GACtB,SAAA;AAGN,MAAA,OAAO,CAAA,EAAG,UAAU,CAAA,gFAAA,EAAmF,SAAS,wBAAwB,QAAQ,CAAA,aAAA,CAAA;AAAA,IAEpJ;AAEA,IAAA,OAAO,UAAA;AAAA,EAEX,CAAA;AAAA,EAEA,SAAA,CAAU,WAAmB,MAAA,EAAyB;AAElD,IAAA,OAAO,CAAA,qBAAA,EAAwBA,cAAAA,CAAc,SAAA,EAAW,MAAM,CAAC,CAAA,CAAA;AAAA,EAEnE,CAAA;AAAA,EAEA,QAAA,CAAS,UAAkB,MAAA,EAAyB;AAEhD,IAAA,OAAO,CAAA,oBAAA,EAAuBA,cAAAA,CAAc,QAAA,EAAU,MAAM,CAAC,CAAA,CAAA;AAAA,EAEjE,CAAA;AAAA,EAEA,YAAA,CAAa,MAAc,MAAA,EAAyB;AAGhD,IAAA,OAAO,CAAA,wBAAA,EAA2BA,cAAAA,CAAc,IAAA,EAAM,MAAM,CAAC,CAAA,CAAA;AAAA,EAEjE,CAAA;AAAA,EAEA,aAAA,CAAc,MAAc,MAAA,EAAyB;AAGjD,IAAA,OAAO,CAAA,yBAAA,EAA4BA,cAAAA,CAAc,IAAA,EAAM,MAAM,CAAC,CAAA,CAAA;AAAA,EAElE,CAAA;AAAA,EAEA,QAAA,CAAS,UAAkB,MAAA,EAAyB;AAEhD,IAAA,OAAO,CAAA,oBAAA,EAAuBA,cAAAA,CAAc,QAAA,EAAU,MAAM,CAAC,CAAA,CAAA;AAAA,EAEjE,CAAA;AAAA,EAEA,cAAA,CAAe,cAAA,EAAwB,SAAA,EAAmB,MAAA,EAAyB;AAE/E,IAAA,OAAO,CAAA,YAAA,EAAeA,eAAc,SAAA,EAAW,MAAM,CAAC,CAAA,iBAAA,EAAoBD,MAAAA,CAAM,cAAc,CAAC,CAAA,CAAA;AAAA,EAEnG;AAEJ,CAAA;;;AC1GA,SAASA,OAAM,IAAA,EAAsB;AAEjC,EAAA,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAA;AAEvC;AAWO,IAAM,wBAAA,GAAsD;AAAA,EAE/D,uBAAA,GAAkC;AAE9B,IAAA,OAAO,2BAAA;AAAA,EAEX,CAAA;AAAA,EAEA,sBAAA,GAAiC;AAE7B,IAAA,OAAO,0BAAA;AAAA,EAEX,CAAA;AAAA,EAEA,aAAA,CAAc,SAAA,EAAmB,OAAA,EAAkB,gBAAA,GAAmB,KAAA,EAAe;AAKjF,IAAA,OAAO,CAAA,YAAA,EAAeA,MAAAA,CAAM,SAAS,CAAC,CAAA,CAAA;AAAA,EAE1C,CAAA;AAAA,EAEA,SAAA,CAAU,WAAmB,OAAA,EAA0B;AAEnD,IAAA,OAAO,CAAA,qBAAA,EAAwBA,MAAAA,CAAM,SAAS,CAAC,CAAA,CAAA;AAAA,EAEnD,CAAA;AAAA,EAEA,QAAA,CAAS,UAAkB,OAAA,EAA0B;AAEjD,IAAA,OAAO,CAAA,oBAAA,EAAuBA,MAAAA,CAAM,QAAQ,CAAC,CAAA,CAAA;AAAA,EAEjD,CAAA;AAAA,EAEA,YAAA,CAAa,OAAe,OAAA,EAA0B;AAGlD,IAAA,OAAO,mDAAA;AAAA,EAEX,CAAA;AAAA,EAEA,aAAA,CAAc,OAAe,OAAA,EAA0B;AAGnD,IAAA,OAAO,8CAAA;AAAA,EAEX,CAAA;AAAA,EAEA,QAAA,CAAS,WAAmB,OAAA,EAA0B;AAGlD,IAAA,OAAO,yCAAA;AAAA,EAEX,CAAA;AAAA,EAEA,cAAA,CAAe,eAAA,EAAyB,UAAA,EAAoB,OAAA,EAA0B;AAIlF,IAAA,OAAO,+DAAA;AAAA,EAEX;AAEJ,CAAA;;;ACjEO,SAAS,sBAAsB,OAAA,EAA6C;AAE/E,EAAA,QAAQ,OAAA;AAAS,IAEjB,KAAK,UAAA;AACD,MAAA,OAAO,0BAAA;AAAA,IAEX,KAAK,OAAA;AACD,MAAA,OAAO,uBAAA;AAAA,IAEX,KAAK,OAAA;AACD,MAAA,OAAO,uBAAA;AAAA,IAEX,KAAK,QAAA;AACD,MAAA,OAAO,wBAAA;AAAA,IAEX,SAAS;AAEL,MAAA,MAAM,eAAA,GAAyB,OAAA;AAC/B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,eAAe,CAAA,CAAE,CAAA;AAAA,IAEzD;AAAA;AAIJ;AC4gBO,IAAM,qBAAA,GAAN,cAAoC,KAAA,CAAM;AAAA,EAI7C,WAAA,CACoB,YACA,KAAA,EAClB;AAEE,IAAA,KAAA,CAAM,CAAA,gBAAA,EAAmB,UAAU,CAAA,GAAA,EAAM,KAAK,CAAA,CAAE,CAAA;AAJhC,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAKpB;AAAA,EATkB,IAAA,GAAO,uBAAA;AAW7B,CAAA;AAKO,IAAM,mBAAA,GAAN,cAAkC,KAAA,CAAM;AAAA,EAI3C,YAA4B,UAAA,EAAoB;AAE5C,IAAA,KAAA,CAAM,CAAA,kBAAA,EAAqB,UAAU,CAAA,CAAE,CAAA;AAFf,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA,EAI5B;AAAA,EANkB,IAAA,GAAO,qBAAA;AAQ7B,CAAA;AAuBO,IAAM,qBAAA,GAAN,cAAoC,KAAA,CAAM;AAAA,EAI7C,YAA4B,UAAA,EAAoB;AAE5C,IAAA,KAAA,CAAM,CAAA,eAAA,EAAkB,UAAU,CAAA,cAAA,CAAgB,CAAA;AAF1B,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA,EAI5B;AAAA,EANkB,IAAA,GAAO,uBAAA;AAQ7B,CAAA;AAKO,IAAM,mBAAA,GAAN,cAAkC,KAAA,CAAM;AAAA,EAI3C,YAA4B,UAAA,EAAoB;AAE5C,IAAA,KAAA,CAAM,CAAA,QAAA,EAAW,UAAU,CAAA,wCAAA,CAA0C,CAAA;AAF7C,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA,EAI5B;AAAA,EANkB,IAAA,GAAO,qBAAA;AAQ7B,CAAA;AAKO,IAAM,sBAAA,GAAN,cAAqC,KAAA,CAAM;AAAA,EAI9C,WAAA,CACoB,cACA,WAAA,EAClB;AAEE,IAAA,KAAA,CAAM,CAAA,UAAA,EAAa,YAAY,CAAA,2BAAA,EAA8B,WAAW,CAAA,CAAE,CAAA;AAJ1D,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAAA,EAKpB;AAAA,EATkB,IAAA,GAAO,wBAAA;AAW7B,CAAA;ACpnBA,IAAM,cAAA,GAAiB,CAAC,MAAA,EAAQ,WAAW,CAAA;AAG3C,IAAM,kBAAA,GAAqB,MAAA;AAG3B,IAAM,iBAAA,GAAoB,4BAAA;AA6B1B,eAAsB,WAAA,CAAY,YAAoB,MAAA,EAAkC;AAGpF,EAAA,MAAM,CAAC,YAAY,OAAO,CAAA,GAAI,MAAMpB,OAAAA,CAAQ,MAAMsB,IAAAA,CAAK,UAAU,CAAC,CAAA;AAElE,EAAA,IAAI,OAAA,IAAW,CAAC,UAAA,EAAY,WAAA,EAAY,EAAG;AAEvC,IAAA,MAAM,IAAI,mBAAA,CAAoBpB,KAAA,CAAK,QAAA,CAAS,UAAU,CAAC,CAAA;AAAA,EAE3D;AAGA,EAAA,MAAM,IAAA,GAAOA,KAAA,CAAK,QAAA,CAAS,UAAU,CAAA;AACrC,EAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAY,GAAI,UAAU,IAAI,CAAA;AAG5C,EAAA,MAAM,UAAA,GAAaA,KAAA,CAAK,IAAA,CAAK,UAAA,EAAY,QAAQ,CAAA;AACjD,EAAA,MAAM,CAAC,WAAA,EAAa,SAAS,CAAA,GAAI,MAAMF,QAAQ,MAAM,UAAA,CAAW,UAAA,EAAY,MAAM,CAAC,CAAA;AAEnF,EAAA,IAAI,SAAA,IAAa,CAAC,eAAA,CAAgB,SAAS,CAAA,EAAG;AAE1C,IAAA,MAAM,SAAA;AAAA,EAEV;AAGA,EAAA,MAAM,UAAA,GAAaE,KAAA,CAAK,IAAA,CAAK,UAAA,EAAY,QAAQ,CAAA;AACjD,EAAA,MAAM,CAAC,WAAA,EAAa,SAAS,CAAA,GAAI,MAAMF,QAAQ,MAAM,UAAA,CAAW,UAAA,EAAY,MAAM,CAAC,CAAA;AAEnF,EAAA,IAAI,SAAA,IAAa,CAAC,eAAA,CAAgB,SAAS,CAAA,EAAG;AAE1C,IAAA,MAAM,SAAA;AAAA,EAEV;AAGA,EAAA,MAAM,aAAA,GAAgBE,KAAA,CAAK,IAAA,CAAK,UAAA,EAAY,cAAc,CAAA;AAC1D,EAAA,MAAM,YAAA,GAAe,MAAM,UAAA,CAAW,aAAa,CAAA;AAGnD,EAAA,IAAA,CAAK,CAAC,eAAe,WAAA,CAAY,MAAA,KAAW,OAAO,CAAC,WAAA,IAAe,WAAA,CAAY,MAAA,KAAW,CAAA,CAAA,EAAI;AAE1F,IAAA,MAAM,IAAI,qBAAA;AAAA,MACN,IAAA;AAAA,MACA;AAAA,KACJ;AAAA,EAEJ;AAEA,EAAA,OAAO;AAAA,IACH,IAAA;AAAA,IACA,IAAA,EAAM,UAAA;AAAA,IACN,IAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA,EAAa,eAAe,EAAC;AAAA,IAC7B,WAAA,EAAa,eAAe,EAAC;AAAA,IAC7B;AAAA,GACJ;AAEJ;AAsBA,eAAsB,eAAA,CAClB,YACA,MAAA,EACiB;AAGjB,EAAA,MAAM,CAAC,MAAM,CAAA,GAAI,MAAMF,QAAQ,MAAMsB,IAAAA,CAAK,UAAU,CAAC,CAAA;AAErD,EAAA,IAAI,CAAC,MAAA,EAAQ;AAET,IAAA,OAAO,EAAC;AAAA,EAEZ;AAGA,EAAA,MAAM,CAAC,OAAA,EAAS,OAAO,CAAA,GAAI,MAAMtB,OAAAA,CAAQ,MAAMuB,OAAAA,CAAQ,UAAA,EAAY,EAAE,aAAA,EAAe,IAAA,EAAM,CAAC,CAAA;AAE3F,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,OAAA;AAAA,MACP,OAAA,EAAS,EAAE,UAAA,EAAY,SAAA,EAAW,UAAA;AAAW,KAChD,CAAA;AAED,IAAA,OAAO,EAAC;AAAA,EAEZ;AAGA,EAAA,MAAM,UAAU,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,CAAA;AAGrD,EAAA,MAAM,UAAoB,EAAC;AAE3B,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAE1B,IAAA,MAAM,UAAA,GAAarB,KAAA,CAAK,IAAA,CAAK,UAAA,EAAY,OAAO,IAAI,CAAA;AAEpD,IAAA,MAAM,CAAC,MAAA,EAAQ,QAAQ,CAAA,GAAI,MAAMF,QAAQ,MAAM,WAAA,CAAY,UAAA,EAAY,MAAM,CAAC,CAAA;AAE9E,IAAA,IAAI,QAAA,EAAU;AAGV,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,QAAA;AAAA,QACP,SAAS,EAAE,MAAA,EAAQ,MAAA,CAAO,IAAA,EAAM,WAAW,OAAA;AAAQ,OACtD,CAAA;AAED,MAAA;AAAA,IAEJ;AAEA,IAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AAAA,EAEvB;AAGA,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAI,CAAC,CAAA;AAE9D;AA2BA,eAAsB,eAAA,CAAgB,cAAsB,MAAA,EAAmC;AAG3F,EAAA,MAAM,CAAC,OAAA,EAAS,OAAO,CAAA,GAAI,MAAMA,QAAQ,MAAMI,QAAAA,CAAS,YAAA,EAAc,OAAO,CAAC,CAAA;AAE9E,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,MAAM,IAAI,MAAM,CAAA,yBAAA,EAA4B,YAAY,IAAI,EAAE,KAAA,EAAO,SAAS,CAAA;AAAA,EAElF;AAGA,EAAA,MAAM,KAAA,GAAQ,QACT,KAAA,CAAM,IAAI,EACV,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,IAAA,EAAM,CAAA,CACzB,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,IAAQ,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAC,CAAA;AAEnD,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AAEpB,IAAA,MAAM,IAAI,qBAAA;AAAA,MACNF,KAAA,CAAK,SAASA,KAAA,CAAK,OAAA,CAAQA,MAAK,OAAA,CAAQ,YAAY,CAAC,CAAC,CAAA;AAAA,MACtD,CAAA,qBAAA,EAAwBA,KAAA,CAAK,QAAA,CAAS,YAAY,CAAC,CAAA;AAAA,KACvD;AAAA,EAEJ;AAGA,EAAA,MAAM,gBAA0B,EAAC;AAEjC,EAAA,KAAA,MAAW,gBAAgB,KAAA,EAAO;AAE9B,IAAA,MAAM,YAAA,GAAeA,KAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,YAAY,CAAA;AAGnD,IAAA,MAAM,CAAC,MAAM,CAAA,GAAI,MAAMF,OAAAA,CAAQ,MAAMwB,MAAAA,CAAO,YAAA,EAAcC,SAAA,CAAY,IAAI,CAAC,CAAA;AAE3E,IAAA,IAAI,WAAW,MAAA,EAAW;AAEtB,MAAA,aAAA,CAAc,KAAK,YAAY,CAAA;AAAA,IAEnC,CAAA,MACK;AAED,MAAA,MAAM,IAAI,sBAAA,CAAuB,YAAA,EAAc,YAAY,CAAA;AAAA,IAE/D;AAAA,EAEJ;AAGA,EAAA,OAAO,cAAc,IAAA,EAAK;AAE9B;AAYO,SAAS,eAAe,MAAA,EAAsB;AAGjD,EAAA,MAAM,kBAAkB,MAAA,CAAO,WAAA,CAAY,IAAI,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAChE,EAAA,MAAM,gBAAA,GAAmB,eAAe,eAAe,CAAA;AAEvD,EAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAE7B,IAAA,MAAM,IAAI,qBAAA;AAAA,MACN,MAAA,CAAO,IAAA;AAAA,MACP,CAAA,4BAAA,EAA+B,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,KAC9D;AAAA,EAEJ;AAGA,EAAA,MAAM,kBAAkB,MAAA,CAAO,WAAA,CAAY,IAAI,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAChE,EAAA,MAAM,gBAAA,GAAmB,eAAe,eAAe,CAAA;AAEvD,EAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAE7B,IAAA,MAAM,IAAI,qBAAA;AAAA,MACN,MAAA,CAAO,IAAA;AAAA,MACP,CAAA,4BAAA,EAA+B,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,KAC9D;AAAA,EAEJ;AAEJ;AAKO,SAAS,eAAe,MAAA,EAAyB;AAEpD,EAAA,OAAO,MAAA,CAAO,YAAY,MAAA,GAAS,CAAA;AAEvC;AASA,SAAS,UAAU,IAAA,EAA0D;AAEzE,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,iBAAiB,CAAA;AAE1C,EAAA,IAAI,SAAS,KAAA,CAAM,CAAC,CAAA,IAAK,KAAA,CAAM,CAAC,CAAA,EAAG;AAE/B,IAAA,MAAM,OAAA,GAAU,MAAM,CAAC,CAAA;AACvB,IAAA,MAAM,WAAA,GAAc,MAAM,CAAC,CAAA;AAC3B,IAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,OAAO,CAAA;AAG7B,IAAA,IAAI,CAAC,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,CAAA,EAAG;AAExB,MAAA,OAAO,EAAE,MAAM,WAAA,EAAY;AAAA,IAE/B;AAAA,EAEJ;AAGA,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,WAAA,EAAa,IAAA,EAAK;AAE3C;AAKA,eAAe,UAAA,CAAW,YAAoB,MAAA,EAAwC;AAGlF,EAAA,MAAM,CAAC,OAAA,EAAS,GAAG,CAAA,GAAI,MAAMzB,OAAAA,CAAQ,MAAMuB,OAAAA,CAAQ,UAAA,EAAY,EAAE,aAAA,EAAe,IAAA,EAAM,CAAC,CAAA;AAEvF,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,MAAM,GAAA;AAAA,EAEV;AAEA,EAAA,MAAM,QAAsB,EAAC;AAE7B,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAEzB,IAAA,IAAI,CAAC,KAAA,CAAM,MAAA,EAAO,EAAG;AAErB,IAAA,MAAM,WAAW,KAAA,CAAM,IAAA;AACvB,IAAA,MAAM,QAAA,GAAWrB,KAAA,CAAK,IAAA,CAAK,UAAA,EAAY,QAAQ,CAAA;AAG/C,IAAA,MAAM,IAAA,GAAO,YAAY,QAAQ,CAAA;AAEjC,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,MAAM,IAAA,GAAmB;AAAA,MACrB,QAAA;AAAA,MACA,IAAA,EAAM,QAAA;AAAA,MACN;AAAA,KACJ;AAGA,IAAA,IAAI,IAAA,KAAS,SAAS,MAAA,EAAQ;AAE1B,MAAA,MAAM,CAAC,aAAA,EAAe,UAAU,CAAA,GAAI,MAAMF,OAAAA;AAAA,QAAQ,MAC9C,eAAA,CAAgB,QAAA,EAAU,MAAM;AAAA,OACpC;AAEA,MAAA,IAAI,UAAA,EAAY;AAEZ,QAAA,MAAM,UAAA;AAAA,MAEV;AAEA,MAAA,IAAA,CAAK,aAAA,GAAgB,aAAA;AAAA,IAEzB;AAEA,IAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,EAEnB;AAGA,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,QAAA,CAAS,aAAA,CAAc,CAAA,CAAE,QAAQ,CAAC,CAAA;AAEpE;AAKA,SAAS,YAAY,QAAA,EAAyC;AAE1D,EAAA,IAAI,QAAA,CAAS,QAAA,CAAS,kBAAkB,CAAA,EAAG;AAEvC,IAAA,OAAO,KAAA;AAAA,EAEX;AAEA,EAAA,KAAA,MAAW,OAAO,cAAA,EAAgB;AAE9B,IAAA,IAAI,QAAA,CAAS,QAAA,CAAS,GAAG,CAAA,EAAG;AAExB,MAAA,OAAO,KAAA;AAAA,IAEX;AAAA,EAEJ;AAEA,EAAA,OAAO,IAAA;AAEX;AAKA,eAAe,WAAW,QAAA,EAAoC;AAE1D,EAAA,MAAM,GAAG,GAAG,CAAA,GAAI,MAAMA,OAAAA,CAAQ,MAAMwB,MAAAA,CAAO,QAAA,EAAUC,SAAA,CAAY,IAAI,CAAC,CAAA;AAEtE,EAAA,OAAO,GAAA,KAAQ,IAAA;AAEnB;AAKA,SAAS,gBAAgB,GAAA,EAAqB;AAE1C,EAAA,OAAQ,IAA8B,IAAA,KAAS,QAAA;AAEnD;AAKA,SAAS,eAAe,KAAA,EAA2B;AAE/C,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AAEnC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAEtB,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AAEhB,MAAA,UAAA,CAAW,IAAI,IAAI,CAAA;AAAA,IAEvB;AAEA,IAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AAAA,EAEjB;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,UAAU,CAAA;AAEhC;AC6CA,eAAsB,aAAa,MAAA,EAA+B;AAE9D,EAAA,MAAM,GAAG,KAAK,CAAA,GAAI,MAAMzB,QAAQ,MAAM,EAAA,CAAG,MAAA,CAAO,IAAA,EAAM,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,CAAC,CAAA;AAEvF,EAAA,IAAI,KAAA,EAAO;AAEP,IAAA,MAAM,IAAI,MAAM,CAAA,yBAAA,EAA4B,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,EAAE,KAAA,EAAO,KAAA,EAAO,CAAA;AAAA,EAE/E;AAEJ;AC/dO,IAAM,gBAAN,MAAoB;AAAA,EAEd,GAAA;AAAA,EACA,WAAA;AAAA,EAET,WAAA,CAAY,IAA2B,UAAA,EAAoB;AAEvD,IAAA,IAAA,CAAK,GAAA,GAAM,EAAA;AACX,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AAAA,EAEvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,UAAU,IAAA,EAA4C;AAExD,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,WAAW,YAAA,CAAa,MAAM,EAC9B,MAAA,CAAO;AAAA,QACJ,MAAA;AAAA,QACA,QAAA;AAAA,QACA,aAAA;AAAA,QACA,aAAA;AAAA,QACA,eAAA;AAAA,QACA;AAAA,OACH,CAAA,CACA,KAAA,CAAM,MAAA,EAAQ,GAAA,EAAK,IAAI,CAAA,CACvB,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,QAAQ,CAAA,CAClC,MAAM,WAAA,EAAa,GAAA,EAAK,QAAQ,CAAA,CAChC,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,IAAA,CAAK,WAAW,CAAA,CAC1C,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA,CACpB,KAAA,CAAM,CAAC,EACP,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,YAAA;AAAa,OAC5C,CAAA;AAED,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,IAAI,CAAC,MAAA,EAAQ;AAET,MAAA,OAAO,IAAA;AAAA,IAEX;AAGA,IAAA,MAAM,CAAC,YAAY,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MACjC,KAAK,GAAA,CACA,UAAA,CAAW,aAAa,MAAM,CAAA,CAC9B,OAAO,CAAC,aAAa,CAAC,CAAA,CACtB,KAAA,CAAM,QAAQ,GAAA,EAAK,IAAI,EACvB,KAAA,CAAM,aAAA,EAAe,KAAK,QAAQ,CAAA,CAClC,MAAM,WAAA,EAAa,GAAA,EAAK,QAAQ,CAAA,CAChC,KAAA,CAAM,UAAU,GAAA,EAAK,SAAS,EAC9B,KAAA,CAAM,aAAA,EAAe,KAAK,IAAA,CAAK,WAAW,EAC1C,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA,CACpB,KAAA,CAAM,CAAC,CAAA,CACP,gBAAA;AAAiB,KAC1B;AAEA,IAAA,OAAO;AAAA,MACH,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,WAAW,MAAA,CAAO,WAAA;AAAA,MAClB,WAAW,MAAA,CAAO,WAAA;AAAA,MAClB,UAAA,EAAY,cAAc,WAAA,IAAe,IAAA;AAAA,MACzC,YAAA,EAAc,OAAO,aAAA,IAAiB;AAAA,KAC1C;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cAAA,GAAqD;AAEvD,IAAA,MAAM,QAAA,uBAAe,GAAA,EAA0B;AAG/C,IAAA,MAAM,CAAC,OAAA,EAAS,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MACjC,IAAA,CAAK,GAAA,CACA,UAAA,CAAW,YAAA,CAAa,MAAM,CAAA,CAC9B,MAAA,CAAO,CAAC,IAAA,EAAM,QAAQ,QAAA,EAAU,aAAA,EAAe,aAAA,EAAe,eAAe,CAAC,CAAA,CAC9E,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,QAAQ,CAAA,CAClC,KAAA,CAAM,WAAA,EAAa,GAAA,EAAK,QAAQ,CAAA,CAChC,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,KAAK,WAAW,CAAA,CAC1C,QAAQ,IAAA,EAAM,MAAM,EACpB,OAAA;AAAQ,KACjB;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,SAAA,EAAW,kBAAA;AAAmB,OAC5C,CAAA;AAED,MAAA,OAAO,QAAA;AAAA,IAEX;AAGA,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAE1B,MAAA,IAAI,CAAC,QAAA,CAAS,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA,EAAG;AAE5B,QAAA,QAAA,CAAS,GAAA,CAAI,OAAO,IAAA,EAAM;AAAA,UACtB,MAAM,MAAA,CAAO,IAAA;AAAA,UACb,QAAQ,MAAA,CAAO,MAAA;AAAA,UACf,WAAW,MAAA,CAAO,WAAA;AAAA,UAClB,WAAW,MAAA,CAAO,WAAA;AAAA,UAClB,UAAA,EAAY,IAAA;AAAA;AAAA,UACZ,YAAA,EAAc,OAAO,aAAA,IAAiB;AAAA,SACzC,CAAA;AAAA,MAEL;AAAA,IAEJ;AAGA,IAAA,MAAM,CAAC,OAAO,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAC5B,IAAA,CAAK,GAAA,CACA,UAAA,CAAW,YAAA,CAAa,MAAM,CAAA,CAC9B,MAAA,CAAO,CAAC,MAAA,EAAQ,aAAa,CAAC,CAAA,CAC9B,MAAM,aAAA,EAAe,GAAA,EAAK,QAAQ,CAAA,CAClC,KAAA,CAAM,WAAA,EAAa,GAAA,EAAK,QAAQ,CAAA,CAChC,KAAA,CAAM,QAAA,EAAU,GAAA,EAAK,SAAS,CAAA,CAC9B,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,KAAK,WAAW,CAAA,CAC1C,QAAQ,IAAA,EAAM,MAAM,EACpB,OAAA;AAAQ,KACjB;AAEA,IAAA,IAAI,OAAA,EAAS;AAGT,MAAA,MAAM,WAAA,uBAAkB,GAAA,EAAY;AAEpC,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAE1B,QAAA,IAAI,CAAC,WAAA,CAAY,GAAA,CAAI,MAAA,CAAO,IAAI,KAAK,QAAA,CAAS,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA,EAAG;AAE5D,UAAA,MAAM,MAAA,GAAS,QAAA,CAAS,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA;AACvC,UAAA,MAAA,CAAO,aAAa,MAAA,CAAO,WAAA;AAC3B,UAAA,WAAA,CAAY,GAAA,CAAI,OAAO,IAAI,CAAA;AAAA,QAE/B;AAAA,MAEJ;AAAA,IAEJ;AAEA,IAAA,OAAO,QAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,QAAA,CAAS,IAAA,EAAc,QAAA,EAAkB,KAAA,EAAyC;AAGpF,IAAA,IAAI,KAAA,EAAO;AAEP,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAQ;AAAA,IAE7C;AAGA,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,WAAW,YAAA,CAAa,MAAM,EAC9B,MAAA,CAAO,CAAC,QAAA,EAAU,UAAU,CAAC,CAAA,CAC7B,KAAA,CAAM,QAAQ,GAAA,EAAK,IAAI,EACvB,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,QAAQ,EAClC,KAAA,CAAM,WAAA,EAAa,KAAK,QAAQ,CAAA,CAChC,MAAM,aAAA,EAAe,GAAA,EAAK,KAAK,WAAW,CAAA,CAC1C,QAAQ,IAAA,EAAM,MAAM,EACpB,KAAA,CAAM,CAAC,EACP,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,iBAAA;AAAkB,OACjD,CAAA;AAGD,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAM;AAAA,IAE3C;AAGA,IAAA,IAAI,CAAC,MAAA,EAAQ;AAET,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAM;AAAA,IAE3C;AAGA,IAAA,IAAI,MAAA,CAAO,WAAW,QAAA,EAAU;AAE5B,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,QAAA;AAAA,QACR,kBAAkB,MAAA,CAAO,QAAA;AAAA,QACzB,gBAAgB,MAAA,CAAO;AAAA,OAC3B;AAAA,IAEJ;AAGA,IAAA,IAAI,MAAA,CAAO,WAAW,UAAA,EAAY;AAE9B,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,UAAA;AAAA,QACR,kBAAkB,MAAA,CAAO,QAAA;AAAA,QACzB,gBAAgB,MAAA,CAAO;AAAA,OAC3B;AAAA,IAEJ;AAGA,IAAA,IAAI,MAAA,CAAO,WAAW,OAAA,EAAS;AAE3B,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,OAAA;AAAA,QACR,kBAAkB,MAAA,CAAO,QAAA;AAAA,QACzB,gBAAgB,MAAA,CAAO;AAAA,OAC3B;AAAA,IAEJ;AAGA,IAAA,IAAI,MAAA,CAAO,aAAa,QAAA,EAAU;AAE9B,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,SAAA;AAAA,QACR,kBAAkB,MAAA,CAAO,QAAA;AAAA,QACzB,gBAAgB,MAAA,CAAO;AAAA,OAC3B;AAAA,IAEJ;AAGA,IAAA,OAAO;AAAA,MACH,QAAA,EAAU,KAAA;AAAA,MACV,UAAA,EAAY,iBAAA;AAAA,MACZ,kBAAkB,MAAA,CAAO,QAAA;AAAA,MACzB,gBAAgB,MAAA,CAAO;AAAA,KAC3B;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,gBAAgB0B,KAAAA,EAIF;AAEhB,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAM1B,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,WAAW,YAAA,CAAa,MAAM,EAC9B,MAAA,CAAO;AAAA,QACJ,MAAM0B,KAAAA,CAAK,IAAA;AAAA,QACX,WAAA,EAAa,QAAA;AAAA,QACb,WAAWA,KAAAA,CAAK,SAAA;AAAA,QAChB,MAAA,EAAQ,SAAA;AAAA,QACR,aAAa,IAAA,CAAK,WAAA;AAAA,QAClB,aAAaA,KAAAA,CAAK;AAAA,OACrB,CAAA,CACA,SAAA,CAAU,IAAI,EACd,uBAAA;AAAwB,KACjC;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,MAAM,IAAI,KAAA,CAAM,0CAAA,EAA4C,EAAE,KAAA,EAAO,KAAK,CAAA;AAAA,IAE9E;AAKA,IAAA,IAAI,KAAK,MAAA,EAAQ,EAAA;AAEjB,IAAA,IAAI,EAAA,KAAO,IAAA,IAAQ,EAAA,KAAO,MAAA,EAAW;AAEjC,MAAA,MAAM,CAAC,YAAA,EAAc,SAAS,CAAA,GAAI,MAAM1B,OAAAA;AAAA,QAAQ,MAC5CkB,GAAAA,CAAAA,gCAAAA,CAAAA,CAAsD,OAAA,CAAQ,IAAA,CAAK,GAAG;AAAA,OAC1E;AAEA,MAAA,IAAI,aAAa,CAAC,YAAA,EAAc,IAAA,GAAO,CAAC,GAAG,EAAA,EAAI;AAE3C,QAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,MAE3D;AAEA,MAAA,EAAA,GAAK,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,CAAE,EAAA;AAAA,IAE9B;AAEA,IAAA,IAAI,OAAO,OAAO,QAAA,IAAY,CAAC,OAAO,QAAA,CAAS,EAAE,CAAA,IAAK,EAAA,IAAM,CAAA,EAAG;AAE3D,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,EAAE,CAAA,CAAE,CAAA;AAAA,IAE1D;AAEA,IAAA,OAAO,EAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAA,CACF,WAAA,EACA,KAAA,EAKsB;AAEtB,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE/B,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAC7B,SAAA,EAAW,WAAA;AAAA,MACX,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,WAAW,CAAA,CAAE,QAAA;AAAA,MACb,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,MAAA,EAAQ;AAAA,KACZ,CAAE,CAAA;AAEF,IAAA,MAAM,GAAG,GAAG,CAAA,GAAI,MAAMlB,OAAAA;AAAA,MAAQ,MAC1B,IAAA,CAAK,GAAA,CAAI,UAAA,CAAW,YAAA,CAAa,UAAU,CAAA,CAAE,MAAA,CAAO,MAAM,CAAA,CAAE,OAAA;AAAQ,KACxE;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,MAAM,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE9D,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,qBAAA;AAAsB,OAC5D,CAAA;AAED,MAAA,OAAO,kCAAkC,MAAM,CAAA,CAAA;AAAA,IAEnD;AAEA,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,mBAAA,CACF,WAAA,EACA,UACA,MAAA,EACA,UAAA,EACA,cACA,UAAA,EACsB;AAEtB,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,YAAY,YAAA,CAAa,UAAU,EACnC,GAAA,CAAI;AAAA,QACD,MAAA;AAAA,QACA,WAAA,EAAa,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA;AAAA,QAClC,eAAe,YAAA,IAAgB,EAAA;AAAA,QAC/B,aAAa,UAAA,IAAc;AAAA,OAC9B,CAAA,CACA,KAAA,CAAM,WAAA,EAAa,GAAA,EAAK,WAAW,CAAA,CACnC,KAAA,CAAM,UAAA,EAAY,GAAA,EAAK,QAAQ,CAAA,CAC/B,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,MAAM,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE9D,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,QAAA,EAAU,SAAA,EAAW,uBAAA;AAAwB,OAC3D,CAAA;AAED,MAAA,OAAO,CAAA,gCAAA,EAAmC,QAAQ,CAAA,EAAA,EAAK,MAAM,CAAA,CAAA;AAAA,IAEjE;AAGA,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,EAAQ,cAAA,IAAkB,CAAC,CAAA;AAErD,IAAA,IAAI,eAAe,CAAA,EAAG;AAElB,MAAA,MAAM,MAAA,GAAS,CAAA,8BAAA,EAAiC,QAAQ,CAAA,eAAA,EAAkB,WAAW,CAAA,CAAA,CAAA;AAErF,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,IAAI,KAAA,CAAM,MAAM,CAAA;AAAA,QACvB,OAAA,EAAS,EAAE,WAAA,EAAa,QAAA,EAAU,WAAW,uBAAA;AAAwB,OACxE,CAAA;AAED,MAAA,OAAO,MAAA;AAAA,IAEX;AAEA,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,kBAAA,CAAmB,WAAA,EAAqB,MAAA,EAAwC;AAElF,IAAA,MAAM,GAAG,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAC1B,IAAA,CAAK,GAAA,CACA,YAAY,YAAA,CAAa,UAAU,EACnC,GAAA,CAAI;AAAA,QACD,MAAA,EAAQ,SAAA;AAAA,QACR,WAAA,EAAa;AAAA,OAChB,CAAA,CACA,KAAA,CAAM,WAAA,EAAa,GAAA,EAAK,WAAW,CAAA,CACnC,KAAA,CAAM,QAAA,EAAU,GAAA,EAAK,SAAS,CAAA,CAC9B,OAAA;AAAQ,KACjB;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,sBAAA;AAAuB,OAC7D,CAAA;AAED,MAAA,OAAO,mCAAmC,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,IAE9F;AAEA,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,iBAAA,CACF,WAAA,EACA,MAAA,EACA,QAAA,EACA,YACA,YAAA,EACsB;AAGtB,IAAA,MAAM,iBAAiB,YAAA,GAAe,YAAA,CAAa,KAAA,CAAM,CAAA,EAAG,GAAI,CAAA,GAAI,EAAA;AAEpE,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,YAAY,YAAA,CAAa,MAAM,EAC/B,GAAA,CAAI;AAAA,QACD,MAAA;AAAA,QACA,QAAA;AAAA,QACA,WAAA,EAAa,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA;AAAA,QAClC,aAAA,EAAe;AAAA,OAClB,CAAA,CACA,KAAA,CAAM,MAAM,GAAA,EAAK,WAAW,EAC5B,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,MAAM,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE9D,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,oBAAA;AAAqB,OAC3D,CAAA;AAGD,MAAA,OAAO,CAAA,6BAAA,EAAgC,WAAW,CAAA,EAAA,EAAK,MAAM,CAAA,CAAA;AAAA,IAEjE;AAGA,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,EAAQ,cAAA,IAAkB,CAAC,CAAA;AAErD,IAAA,IAAI,eAAe,CAAA,EAAG;AAElB,MAAA,MAAM,MAAA,GAAS,qCAAqC,WAAW,CAAA,CAAA;AAE/D,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,IAAI,KAAA,CAAM,MAAM,CAAA;AAAA,QACvB,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,oBAAA;AAAqB,OAC3D,CAAA;AAED,MAAA,OAAO,MAAA;AAAA,IAEX;AAEA,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,WAAA,CAAY,UAAA,EAAoB,MAAA,EAAkC;AAEpE,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,WAAW,YAAA,CAAa,MAAM,EAC9B,MAAA,CAAO;AAAA,QACJ,IAAA,EAAM,WAAA;AAAA,QACN,WAAA,EAAa,QAAA;AAAA,QACb,SAAA,EAAW,QAAA;AAAA,QACX,MAAA,EAAQ,SAAA;AAAA,QACR,aAAa,IAAA,CAAK,WAAA;AAAA,QAClB,WAAA,EAAa,UAAA;AAAA,QACb,eAAe,MAAA,IAAU,EAAA;AAAA,QACzB,WAAA,EAAa,CAAA;AAAA,QACb,QAAA,EAAU;AAAA,OACb,CAAA,CACA,SAAA,CAAU,IAAI,EACd,uBAAA;AAAwB,KACjC;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,SAAA,EAAW,cAAA;AAAe,OACxC,CAAA;AAED,MAAA,OAAO,CAAA;AAAA,IAEX;AAEA,IAAA,OAAO,MAAA,CAAO,EAAA;AAAA,EAElB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cAAc,IAAA,EAA6B;AAG7C,IAAA,MAAM,CAAC,UAAA,EAAY,QAAQ,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MACzC,IAAA,CAAK,GAAA,CACA,UAAA,CAAW,YAAA,CAAa,MAAM,CAAA,CAC9B,MAAA,CAAO,CAAC,IAAI,CAAC,CAAA,CACb,KAAA,CAAM,MAAA,EAAQ,GAAA,EAAK,IAAI,CAAA,CACvB,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,QAAQ,CAAA,CAClC,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,IAAA,CAAK,WAAW,CAAA,CAC1C,OAAA;AAAQ,KACjB;AAEA,IAAA,IAAI,QAAA,IAAY,CAAC,UAAA,IAAc,UAAA,CAAW,WAAW,CAAA,EAAG;AAEpD,MAAA;AAAA,IAEJ;AAEA,IAAA,MAAM,eAAe,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,EAAE,CAAA;AAG/C,IAAA,MAAM,GAAG,OAAO,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAC9B,IAAA,CAAK,GAAA,CACA,UAAA,CAAW,YAAA,CAAa,UAAU,CAAA,CAClC,KAAA,CAAM,WAAA,EAAa,IAAA,EAAM,YAAY,CAAA,CACrC,OAAA;AAAQ,KACjB;AAEA,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,OAAA;AAAA,QACP,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,mBAAA;AAAoB,OACnD,CAAA;AAAA,IAEL;AAGA,IAAA,MAAM,GAAG,SAAS,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CAAI,UAAA,CAAW,YAAA,CAAa,MAAM,CAAA,CAAE,KAAA,CAAM,IAAA,EAAM,IAAA,EAAM,YAAY,CAAA,CAAE,OAAA;AAAQ,KACrF;AAEA,IAAA,IAAI,SAAA,EAAW;AAEX,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,SAAA;AAAA,QACP,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,eAAA;AAAgB,OAC/C,CAAA;AAAA,IAEL;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,UAAA,CAAW,IAAA,EAAe,KAAA,EAAgD;AAE5E,IAAA,IAAI,QAAQ,IAAA,CAAK,GAAA,CACZ,WAAW,YAAA,CAAa,MAAM,EAC9B,MAAA,CAAO;AAAA,MACJ,IAAA;AAAA,MACA,MAAA;AAAA,MACA,WAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAA;AAAA,MACA,aAAA;AAAA,MACA,aAAA;AAAA,MACA,eAAA;AAAA,MACA;AAAA,KACH,CAAA,CACA,KAAA,CAAM,aAAA,EAAe,KAAK,QAAQ,CAAA,CAClC,KAAA,CAAM,aAAA,EAAe,KAAK,IAAA,CAAK,WAAW,CAAA,CAC1C,OAAA,CAAQ,MAAM,MAAM,CAAA;AAEzB,IAAA,IAAI,IAAA,EAAM;AAEN,MAAA,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,MAAA,EAAQ,GAAA,EAAK,IAAI,CAAA;AAAA,IAEzC;AAEA,IAAA,IAAI,KAAA,EAAO;AAEP,MAAA,KAAA,GAAQ,KAAA,CAAM,MAAM,KAAK,CAAA;AAAA,IAE7B;AAEA,IAAA,MAAM,CAAC,SAAS,GAAG,CAAA,GAAI,MAAMA,OAAAA,CAAQ,MAAM,KAAA,CAAM,OAAA,EAAS,CAAA;AAE1D,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,aAAA;AAAc,OAC7C,CAAA;AAED,MAAA,OAAO,EAAC;AAAA,IAEZ;AAEA,IAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACvB,IAAI,CAAA,CAAE,EAAA;AAAA,MACN,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,WAAW,CAAA,CAAE,SAAA;AAAA,MACb,QAAQ,CAAA,CAAE,MAAA;AAAA,MACV,YAAY,CAAA,CAAE,WAAA;AAAA,MACd,YAAY,CAAA,CAAE,WAAA;AAAA,MACd,YAAY,CAAA,CAAE,WAAA;AAAA,MACd,YAAA,EAAc,EAAE,aAAA,IAAiB,IAAA;AAAA,MACjC,UAAU,CAAA,CAAE;AAAA,KAChB,CAAE,CAAA;AAAA,EAEN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,iBAAA,CACF,WAAA,EACA,KAAA,EAC+B;AAE/B,IAAA,IAAI,QAAQ,IAAA,CAAK,GAAA,CACZ,WAAW,YAAA,CAAa,MAAM,EAC9B,MAAA,CAAO;AAAA,MACJ,IAAA;AAAA,MACA,MAAA;AAAA,MACA,aAAA;AAAA,MACA,WAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAA;AAAA,MACA,aAAA;AAAA,MACA,aAAA;AAAA,MACA,eAAA;AAAA,MACA;AAAA,KACH,CAAA,CACA,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,KAAK,WAAW,CAAA,CAC1C,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA;AAGzB,IAAA,IAAI,WAAA,IAAe,WAAA,CAAY,MAAA,GAAS,CAAA,EAAG;AAEvC,MAAA,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,aAAA,EAAe,IAAA,EAAM,WAAW,CAAA;AAAA,IAExD;AAEA,IAAA,IAAI,KAAA,EAAO;AAEP,MAAA,KAAA,GAAQ,KAAA,CAAM,MAAM,KAAK,CAAA;AAAA,IAE7B;AAEA,IAAA,MAAM,CAAC,SAAS,GAAG,CAAA,GAAI,MAAMA,OAAAA,CAAQ,MAAM,KAAA,CAAM,OAAA,EAAS,CAAA;AAE1D,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,SAAA,EAAW,qBAAA;AAAsB,OAC/C,CAAA;AAED,MAAA,OAAO,EAAC;AAAA,IAEZ;AAEA,IAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACvB,IAAI,CAAA,CAAE,EAAA;AAAA,MACN,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,YAAY,CAAA,CAAE,WAAA;AAAA,MACd,WAAW,CAAA,CAAE,SAAA;AAAA,MACb,QAAQ,CAAA,CAAE,MAAA;AAAA,MACV,YAAY,CAAA,CAAE,WAAA;AAAA,MACd,YAAY,CAAA,CAAE,WAAA;AAAA,MACd,YAAY,CAAA,CAAE,WAAA;AAAA,MACd,YAAA,EAAc,EAAE,aAAA,IAAiB,IAAA;AAAA,MACjC,UAAU,CAAA,CAAE;AAAA,KAChB,CAAE,CAAA;AAAA,EAEN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,mBAAmB,KAAA,EAAiD;AAEtE,IAAA,OAAO,KAAK,iBAAA,CAAkB,CAAC,OAAA,EAAS,KAAK,GAAG,KAAK,CAAA;AAAA,EAEzD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAAA,EAAmD;AAEpE,IAAA,MAAM,CAAC,OAAA,EAAS,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MACjC,IAAA,CAAK,GAAA,CACA,WAAW,YAAA,CAAa,UAAU,EAClC,MAAA,CAAO;AAAA,QACJ,IAAA;AAAA,QACA,WAAA;AAAA,QACA,UAAA;AAAA,QACA,WAAA;AAAA,QACA,UAAA;AAAA,QACA,QAAA;AAAA,QACA,aAAA;AAAA,QACA,eAAA;AAAA,QACA;AAAA,OACH,CAAA,CACA,KAAA,CAAM,WAAA,EAAa,GAAA,EAAK,WAAW,CAAA,CACnC,OAAA,CAAQ,IAAA,EAAM,KAAK,CAAA,CACnB,OAAA;AAAQ,KACjB;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,kBAAA;AAAmB,OACzD,CAAA;AAED,MAAA,OAAO,EAAC;AAAA,IAEZ;AAEA,IAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACvB,IAAI,CAAA,CAAE,EAAA;AAAA,MACN,UAAU,CAAA,CAAE,SAAA;AAAA,MACZ,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,UAAU,CAAA,CAAE,SAAA;AAAA,MACZ,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,QAAQ,CAAA,CAAE,MAAA;AAAA,MACV,UAAA,EAAY,EAAE,WAAA,IAAe,IAAA;AAAA,MAC7B,YAAA,EAAc,EAAE,aAAA,IAAiB,IAAA;AAAA,MACjC,YAAY,CAAA,CAAE;AAAA,KAClB,CAAE,CAAA;AAAA,EAEN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YAAY,SAAA,EAA2C;AAEzD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,cAAA,EAAe;AAC3C,IAAA,MAAM,WAAqB,EAAC;AAE5B,IAAA,KAAA,MAAW,CAAC,IAAI,CAAA,IAAK,QAAA,EAAU;AAE3B,MAAA,IAAI,CAAC,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,EAAG;AAEtB,QAAA,QAAA,CAAS,KAAK,IAAI,CAAA;AAAA,MAEtB;AAAA,IAEJ;AAEA,IAAA,OAAO,QAAA;AAAA,EAEX;AAEJ,CAAA;ACx6BO,IAAM,UAAN,MAAc;AAAA,EAER,GAAA;AAAA,EACA,WAAA;AAAA,EAET,WAAA,CAAY,IAA2B,UAAA,EAAoB;AAEvD,IAAA,IAAA,CAAK,GAAA,GAAM,EAAA;AACX,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AAAA,EAEvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,QAAA,CAAS,QAAA,EAAkB,QAAA,EAAkB,KAAA,EAAyC;AAGxF,IAAA,IAAI,KAAA,EAAO;AAEP,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAQ;AAAA,IAE7C;AAIA,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,UAAA,CAAW,YAAA,CAAa,UAAU,CAAA,CAClC,SAAA;AAAA,QACG,YAAA,CAAa,MAAA;AAAA,QACb,CAAA,EAAG,aAAa,MAAM,CAAA,GAAA,CAAA;AAAA,QACtB,CAAA,EAAG,aAAa,UAAU,CAAA,UAAA;AAAA,OAC9B,CACC,MAAA,CAAO,CAAC,EAAA,KAAO;AAAA,QACZ,EAAA,CAAG,IAAI,CAAA,EAAG,YAAA,CAAa,UAAU,CAAA,SAAA,CAAW,CAAA,CAAE,GAAG,UAAU,CAAA;AAAA,QAC3D,EAAA,CAAG,IAAI,CAAA,EAAG,YAAA,CAAa,UAAU,CAAA,OAAA,CAAS,CAAA,CAAE,GAAG,aAAa,CAAA;AAAA,QAC5D,EAAA,CAAG,IAAI,CAAA,EAAG,YAAA,CAAa,MAAM,CAAA,OAAA,CAAS,CAAA,CAAE,GAAG,eAAe;AAAA,OAC7D,CAAA,CACA,KAAA,CAAM,CAAA,EAAG,YAAA,CAAa,UAAU,CAAA,SAAA,CAAA,EAAa,GAAA,EAAK,QAAQ,CAAA,CAC1D,KAAA,CAAM,CAAA,EAAG,YAAA,CAAa,MAAM,CAAA,YAAA,CAAA,EAAgB,GAAA,EAAK,IAAA,CAAK,WAAW,CAAA,CACjE,OAAA,CAAQ,CAAA,EAAG,YAAA,CAAa,UAAU,CAAA,GAAA,CAAA,EAAO,MAAM,CAAA,CAC/C,KAAA,CAAM,CAAC,EACP,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,QAAA,EAAU,SAAA,EAAW,iBAAA;AAAkB,OACrD,CAAA;AAGD,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAM;AAAA,IAE3C;AAGA,IAAA,IAAI,CAAC,MAAA,EAAQ;AAET,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAM;AAAA,IAE3C;AAGA,IAAA,IAAI,MAAA,CAAO,gBAAgB,QAAA,EAAU;AAEjC,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,QAAA;AAAA,QACR,kBAAkB,MAAA,CAAO;AAAA,OAC7B;AAAA,IAEJ;AAIA,IAAA,IAAI,MAAA,CAAO,WAAA,KAAgB,SAAA,IAAa,MAAA,CAAO,gBAAgB,SAAA,EAAW;AAEtE,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAM;AAAA,IAE3C;AAGA,IAAA,IAAI,MAAA,CAAO,kBAAkB,OAAA,EAAS;AAElC,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,OAAA;AAAA,QACR,kBAAkB,MAAA,CAAO;AAAA,OAC7B;AAAA,IAEJ;AAGA,IAAA,IAAI,MAAA,CAAO,aAAa,QAAA,EAAU;AAE9B,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,SAAA;AAAA,QACR,kBAAkB,MAAA,CAAO;AAAA,OAC7B;AAAA,IAEJ;AAGA,IAAA,OAAO;AAAA,MACH,QAAA,EAAU,KAAA;AAAA,MACV,UAAA,EAAY,WAAA;AAAA,MACZ,kBAAkB,MAAA,CAAO;AAAA,KAC7B;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,gBAAgB0B,KAAAA,EAA4C;AAG9D,IAAA,MAAM,SAAA,GAAuBA,MAAK,SAAA,IAAa,QAAA;AAI/C,IAAA,MAAM,WAAA,GAAc,SAAA,KAAc,QAAA,GAAW,QAAA,GAAW,QAAA;AAExD,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAM1B,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,WAAW,YAAA,CAAa,MAAM,EAC9B,MAAA,CAAO;AAAA,QACJ,MAAM0B,KAAAA,CAAK,IAAA;AAAA,QACX,aAAaA,KAAAA,CAAK,UAAA;AAAA,QAClB,SAAA,EAAW,WAAA;AAAA,QACX,MAAA,EAAQ,SAAA;AAAA,QACR,aAAaA,KAAAA,CAAK,UAAA;AAAA,QAClB,aAAaA,KAAAA,CAAK;AAAA,OACrB,CAAA,CACA,SAAA,CAAU,IAAI,EACd,uBAAA;AAAwB,KACjC;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,MAAM,IAAI,KAAA,CAAM,mCAAA,EAAqC,EAAE,KAAA,EAAO,KAAK,CAAA;AAAA,IAEvE;AAKA,IAAA,IAAI,KAAK,MAAA,EAAQ,EAAA;AAEjB,IAAA,IAAI,EAAA,KAAO,IAAA,IAAQ,EAAA,KAAO,MAAA,EAAW;AAEjC,MAAA,MAAM,CAAC,YAAA,EAAc,SAAS,CAAA,GAAI,MAAM1B,OAAAA;AAAA,QAAQ,MAC5CkB,GAAAA,CAAAA,gCAAAA,CAAAA,CAAsD,OAAA,CAAQ,IAAA,CAAK,GAAG;AAAA,OAC1E;AAEA,MAAA,IAAI,aAAa,CAAC,YAAA,EAAc,IAAA,GAAO,CAAC,GAAG,EAAA,EAAI;AAE3C,QAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,MAE3D;AAEA,MAAA,EAAA,GAAK,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,CAAE,EAAA;AAAA,IAE9B;AAEA,IAAA,IAAI,OAAO,OAAO,QAAA,IAAY,CAAC,OAAO,QAAA,CAAS,EAAE,CAAA,IAAK,EAAA,IAAM,CAAA,EAAG;AAE3D,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,EAAE,CAAA,CAAE,CAAA;AAAA,IAE1D;AAEA,IAAA,OAAO,EAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBAAgBQ,KAAAA,EAA0C;AAE5D,IAAA,MAAM,GAAG,GAAG,CAAA,GAAI,MAAM1B,OAAAA;AAAA,MAAQ,MAC1B,IAAA,CAAK,GAAA,CACA,WAAW,YAAA,CAAa,UAAU,EAClC,MAAA,CAAO;AAAA,QACJ,WAAW0B,KAAAA,CAAK,QAAA;AAAA,QAChB,UAAUA,KAAAA,CAAK,QAAA;AAAA,QACf,SAAA,EAAW,KAAA;AAAA,QACX,UAAUA,KAAAA,CAAK,QAAA;AAAA,QACf,QAAQA,KAAAA,CAAK,MAAA;AAAA,QACb,WAAA,EAAaA,MAAK,UAAA,IAAc,EAAA;AAAA,QAChC,aAAA,EAAeA,MAAK,YAAA,IAAgB,EAAA;AAAA,QACpC,WAAA,EAAa,IAAA,CAAK,KAAA,CAAMA,KAAAA,CAAK,cAAc,CAAC;AAAA,OAC/C,EACA,OAAA;AAAQ,KACjB;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,SAAS,EAAE,QAAA,EAAUA,KAAAA,CAAK,QAAA,EAAU,WAAW,kBAAA;AAAmB,OACrE,CAAA;AAAA,IAEL;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,iBAAA,CACF,WAAA,EACA,MAAA,EACA,UAAA,EACA,UACA,YAAA,EACsB;AAGtB,IAAA,MAAM,iBAAiB,YAAA,GAAe,YAAA,CAAa,KAAA,CAAM,CAAA,EAAG,GAAI,CAAA,GAAI,EAAA;AAEpE,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAM1B,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,YAAY,YAAA,CAAa,MAAM,EAC/B,GAAA,CAAI;AAAA,QACD,MAAA;AAAA,QACA,WAAA,EAAa,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA;AAAA,QAClC,UAAU,QAAA,IAAY,EAAA;AAAA,QACtB,aAAA,EAAe;AAAA,OAClB,CAAA,CACA,KAAA,CAAM,MAAM,GAAA,EAAK,WAAW,EAC5B,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,MAAM,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE9D,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,oBAAA;AAAqB,OAC3D,CAAA;AAED,MAAA,OAAO,CAAA,6BAAA,EAAgC,WAAW,CAAA,EAAA,EAAK,MAAM,CAAA,CAAA;AAAA,IAEjE;AAGA,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,EAAQ,cAAA,IAAkB,CAAC,CAAA;AAErD,IAAA,IAAI,eAAe,CAAA,EAAG;AAElB,MAAA,MAAM,MAAA,GAAS,qCAAqC,WAAW,CAAA,CAAA;AAE/D,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,IAAI,KAAA,CAAM,MAAM,CAAA;AAAA,QACvB,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,oBAAA;AAAqB,OAC3D,CAAA;AAED,MAAA,OAAO,MAAA;AAAA,IAEX;AAEA,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,iBAAA,CACF,WAAA,EACA,KAAA,EAKsB;AAEtB,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE/B,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAC7B,SAAA,EAAW,WAAA;AAAA,MACX,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,WAAW,CAAA,CAAE,QAAA;AAAA,MACb,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,MAAA,EAAQ;AAAA,KACZ,CAAE,CAAA;AAEF,IAAA,MAAM,GAAG,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAC1B,IAAA,CAAK,GAAA,CAAI,UAAA,CAAW,YAAA,CAAa,UAAU,CAAA,CAAE,MAAA,CAAO,MAAM,CAAA,CAAE,OAAA;AAAQ,KACxE;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,MAAM,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE9D,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,qBAAA;AAAsB,OAC5D,CAAA;AAED,MAAA,OAAO,kCAAkC,MAAM,CAAA,CAAA;AAAA,IAEnD;AAEA,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,mBAAA,CACF,WAAA,EACA,UACA,MAAA,EACA,UAAA,EACA,cACA,UAAA,EACsB;AAEtB,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,YAAY,YAAA,CAAa,UAAU,EACnC,GAAA,CAAI;AAAA,QACD,MAAA;AAAA,QACA,WAAA,EAAa,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA;AAAA,QAClC,eAAe,YAAA,IAAgB,EAAA;AAAA,QAC/B,aAAa,UAAA,IAAc;AAAA,OAC9B,CAAA,CACA,KAAA,CAAM,WAAA,EAAa,GAAA,EAAK,WAAW,CAAA,CACnC,KAAA,CAAM,UAAA,EAAY,GAAA,EAAK,QAAQ,CAAA,CAC/B,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,MAAM,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE9D,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,QAAA,EAAU,SAAA,EAAW,uBAAA;AAAwB,OAC3D,CAAA;AAED,MAAA,OAAO,CAAA,gCAAA,EAAmC,QAAQ,CAAA,EAAA,EAAK,MAAM,CAAA,CAAA;AAAA,IAEjE;AAGA,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,EAAQ,cAAA,IAAkB,CAAC,CAAA;AAErD,IAAA,IAAI,eAAe,CAAA,EAAG;AAElB,MAAA,MAAM,MAAA,GAAS,CAAA,8BAAA,EAAiC,QAAQ,CAAA,eAAA,EAAkB,WAAW,CAAA,CAAA,CAAA;AAErF,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,IAAI,KAAA,CAAM,MAAM,CAAA;AAAA,QACvB,OAAA,EAAS,EAAE,WAAA,EAAa,QAAA,EAAU,WAAW,uBAAA;AAAwB,OACxE,CAAA;AAED,MAAA,OAAO,MAAA;AAAA,IAEX;AAEA,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,kBAAA,CAAmB,WAAA,EAAqB,MAAA,EAAwC;AAElF,IAAA,MAAM,GAAG,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAC1B,IAAA,CAAK,GAAA,CACA,YAAY,YAAA,CAAa,UAAU,EACnC,GAAA,CAAI;AAAA,QACD,MAAA,EAAQ,SAAA;AAAA,QACR,WAAA,EAAa;AAAA,OAChB,CAAA,CACA,KAAA,CAAM,WAAA,EAAa,GAAA,EAAK,WAAW,CAAA,CACnC,KAAA,CAAM,QAAA,EAAU,GAAA,EAAK,SAAS,CAAA,CAC9B,OAAA;AAAQ,KACjB;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,sBAAA;AAAuB,OAC7D,CAAA;AAED,MAAA,OAAO,mCAAmC,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,IAE9F;AAEA,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,cAAA,CAAe,IAAA,EAAc,QAAA,EAAkB,KAAA,EAAyC;AAG1F,IAAA,IAAI,KAAA,EAAO;AAEP,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAQ;AAAA,IAE7C;AAIA,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,UAAA,CAAW,YAAA,CAAa,MAAM,CAAA,CAC9B,MAAA,CAAO,CAAC,QAAA,EAAU,UAAU,CAAC,CAAA,CAC7B,KAAA,CAAM,MAAA,EAAQ,KAAK,IAAI,CAAA,CACvB,KAAA,CAAM,WAAA,EAAa,KAAK,QAAQ,CAAA,CAChC,KAAA,CAAM,aAAA,EAAe,KAAK,IAAA,CAAK,WAAW,CAAA,CAC1C,OAAA,CAAQ,MAAM,MAAM,CAAA,CACpB,KAAA,CAAM,CAAC,EACP,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,mBAAA;AAAoB,OACnD,CAAA;AAGD,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAM;AAAA,IAE3C;AAGA,IAAA,IAAI,CAAC,MAAA,EAAQ;AAET,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAM;AAAA,IAE3C;AAGA,IAAA,IAAI,MAAA,CAAO,WAAW,QAAA,EAAU;AAE5B,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,QAAA;AAAA,QACR,kBAAkB,MAAA,CAAO;AAAA,OAC7B;AAAA,IAEJ;AAGA,IAAA,IAAI,MAAA,CAAO,WAAW,UAAA,EAAY;AAE9B,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,OAAA;AAAA;AAAA,QACR,kBAAkB,MAAA,CAAO;AAAA,OAC7B;AAAA,IAEJ;AAGA,IAAA,IAAI,MAAA,CAAO,WAAW,OAAA,EAAS;AAE3B,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,OAAA;AAAA,QACR,kBAAkB,MAAA,CAAO;AAAA,OAC7B;AAAA,IAEJ;AAGA,IAAA,IAAI,MAAA,CAAO,aAAa,QAAA,EAAU;AAE9B,MAAA,OAAO;AAAA,QACH,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ,SAAA;AAAA,QACR,kBAAkB,MAAA,CAAO;AAAA,OAC7B;AAAA,IAEJ;AAGA,IAAA,OAAO;AAAA,MACH,QAAA,EAAU,KAAA;AAAA,MACV,UAAA,EAAY,aAAA;AAAA,MACZ,kBAAkB,MAAA,CAAO;AAAA,KAC7B;AAAA,EAEJ;AAEJ,CAAA;;;ACnjBO,IAAM,aAAA,GAAN,cAA4B,OAAA,CAAQ;AAAA;AAAA;AAAA,EAI9B,GAAA;AAAA,EACA,WAAA;AAAA,EAET,WAAA,CAAY,IAA2B,UAAA,EAAoB;AAEvD,IAAA,KAAA,CAAM,IAAI,UAAU,CAAA;AACpB,IAAA,IAAA,CAAK,GAAA,GAAM,EAAA;AACX,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AAAA,EAEvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAA,CAAU,IAAA,EAAc,KAAA,EAA0C;AAGpE,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,WAAW,YAAA,CAAa,MAAM,EAC9B,MAAA,CAAO,CAAC,QAAQ,CAAC,EACjB,KAAA,CAAM,MAAA,EAAQ,KAAK,IAAI,CAAA,CACvB,MAAM,aAAA,EAAe,GAAA,EAAK,QAAQ,CAAA,CAClC,MAAM,WAAA,EAAa,GAAA,EAAK,QAAQ,CAAA,CAChC,KAAA,CAAM,eAAe,GAAA,EAAK,IAAA,CAAK,WAAW,CAAA,CAC1C,QAAQ,IAAA,EAAM,MAAM,EACpB,KAAA,CAAM,CAAC,EACP,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,YAAA;AAAa,OAC5C,CAAA;AAED,MAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,MAAA,EAAQ,gBAAA,EAAiB;AAAA,IAExD;AAEA,IAAA,IAAI,CAAC,MAAA,EAAQ;AAET,MAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,MAAA,EAAQ,aAAA,EAAc;AAAA,IAErD;AAEA,IAAA,IAAI,KAAA,EAAO;AAEP,MAAA,OAAO,EAAE,SAAA,EAAW,IAAA,EAAM,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,IAEpD;AAEA,IAAA,QAAQ,OAAO,MAAA;AAAQ,MAEvB,KAAK,SAAA;AACD,QAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,QAAQ,iBAAA,EAAmB,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,MAEhF,KAAK,SAAA;AACD,QAAA,OAAO,EAAE,SAAA,EAAW,IAAA,EAAM,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,MAEpD,KAAK,QAAA;AACD,QAAA,OAAO,EAAE,SAAA,EAAW,IAAA,EAAM,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,MAEpD,KAAK,UAAA;AACD,QAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,QAAQ,kBAAA,EAAoB,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,MAEjF,KAAK,OAAA;AACD,QAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,QAAQ,sBAAA,EAAwB,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,MAErF;AACI,QAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,MAAA,EAAQ,gBAAA,EAAiB;AAAA;AAExD,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAAe,IAAA,EAA6B;AAG9C,IAAA,MAAM,CAAC,MAAM,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAC3B,IAAA,CAAK,GAAA,CACA,WAAW,YAAA,CAAa,MAAM,EAC9B,MAAA,CAAO,CAAC,IAAI,CAAC,EACb,KAAA,CAAM,MAAA,EAAQ,KAAK,IAAI,CAAA,CACvB,MAAM,aAAA,EAAe,GAAA,EAAK,QAAQ,CAAA,CAClC,MAAM,WAAA,EAAa,GAAA,EAAK,QAAQ,CAAA,CAChC,KAAA,CAAM,eAAe,GAAA,EAAK,IAAA,CAAK,WAAW,CAAA,CAC1C,QAAQ,IAAA,EAAM,MAAM,EACpB,KAAA,CAAM,CAAC,EACP,gBAAA;AAAiB,KAC1B;AAEA,IAAA,IAAI,MAAA,EAAQ;AAER,MAAA,MAAMA,OAAAA;AAAA,QAAQ,MACV,IAAA,CAAK,GAAA,CACA,YAAY,YAAA,CAAa,MAAM,EAC/B,GAAA,CAAI,EAAE,QAAQ,UAAA,EAAY,EAC1B,KAAA,CAAM,IAAA,EAAM,KAAK,MAAA,CAAO,EAAE,EAC1B,OAAA;AAAQ,OACjB;AAAA,IAEJ;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,cAAA,GAAkC;AAEpC,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAChC,IAAA,CAAK,GAAA,CACA,WAAA,CAAY,aAAa,MAAM,CAAA,CAC/B,GAAA,CAAI,EAAE,MAAA,EAAQ,OAAA,EAAS,CAAA,CACvB,MAAM,WAAA,EAAa,GAAA,EAAK,QAAQ,CAAA,CAChC,KAAA,CAAM,QAAA,EAAU,IAAA,EAAM,CAAC,WAAW,QAAA,EAAU,SAAS,CAAC,CAAA,CACtD,MAAM,aAAA,EAAe,GAAA,EAAK,IAAA,CAAK,WAAW,EAC1C,OAAA;AAAQ,KACjB;AAEA,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,GAAA;AAAA,QACP,OAAA,EAAS,EAAE,SAAA,EAAW,gBAAA;AAAiB,OAC1C,CAAA;AAED,MAAA,OAAO,CAAA;AAAA,IAEX;AAEA,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,GAAM,MAAA,CAAO,CAAA,CAAE,cAAA,IAAkB,CAAC,CAAA,EAAG,CAAC,CAAA;AAAA,EAE3E;AAEJ,CAAA;AC9MA,eAAsB,gBAAgB,QAAA,EAAmC;AAErE,EAAA,MAAM,CAAC,OAAA,EAAS,GAAG,CAAA,GAAI,MAAMA,QAAQ,MAAMI,QAAAA,CAAS,QAAA,EAAU,OAAO,CAAC,CAAA;AAEtE,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,MAAM,IAAI,MAAM,CAAA,kCAAA,EAAqC,QAAQ,IAAI,EAAE,KAAA,EAAO,KAAK,CAAA;AAAA,EAEnF;AAEA,EAAA,OAAO,2BAA2B,OAAO,CAAA;AAE7C;AAiBO,SAAS,2BAA2B,OAAA,EAAyB;AAEhE,EAAA,OAAO,UAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,SAAS,OAAO,CAAA,CAAE,OAAO,KAAK,CAAA;AAErE;AAuBO,SAAS,wBAAwB,SAAA,EAA6B;AAEjE,EAAA,MAAM,MAAA,GAAS,CAAC,GAAG,SAAS,EAAE,IAAA,EAAK;AACnC,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,EAAE,CAAA;AAE/B,EAAA,OAAO,UAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,UAAU,OAAO,CAAA,CAAE,OAAO,KAAK,CAAA;AAEtE;;;ACcO,IAAM,oBAAA,GAA8D;AAAA,EACvE,OAAA,EAAS,UAAA;AAAA,EACT,OAAA,EAAS,IAAI,EAAA,GAAK,GAAA;AAAA;AAAA,EAClB,IAAA,EAAM,KAAA;AAAA,EACN,aAAa,EAAA,GAAK,GAAA;AAAA;AAAA,EAClB,YAAA,EAAc;AAAA;AAClB,CAAA;;;ACjGO,IAAM,gBAAA,GAAN,cAA+B,KAAA,CAAM;AAAA,EAIxC,WAAA,CACoB,UAAA,EACA,MAAA,EACA,SAAA,EACA,WACA,MAAA,EAClB;AAEE,IAAA,MAAM,KAAA,GAAQ,UAAU,WAAA,EAAY;AACpC,IAAA,MAAM,OAAA,GAAU,UAAU,WAAA,EAAY;AACtC,IAAA,MAAM,YAAA,GAAe,MAAA,GAAS,CAAA,EAAA,EAAK,MAAM,CAAA,CAAA,CAAA,GAAM,EAAA;AAE/C,IAAA,KAAA;AAAA,MACI,CAAA,UAAA,EAAa,UAAU,CAAA,UAAA,EAAa,MAAM,UAAU,KAAK,CAAA,UAAA,EAAa,OAAO,CAAA,EAAG,YAAY,CAAA;AAAA,KAChG;AAbgB,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAWpB;AAAA,EAlBkB,IAAA,GAAO,kBAAA;AAoB7B;AAkBO,IAAM,gBAAA,GAAN,cAA+B,KAAA,CAAM;AAAA,EAIxC,WAAA,CACoB,UAAA,EACA,QAAA,EACA,SAAA,EAClB;AAEE,IAAA,KAAA,CAAM,aAAa,UAAU,CAAA,aAAA,EAAgB,SAAA,CAAU,WAAA,EAAa,CAAA,CAAE,CAAA;AALtD,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAAA,EAKpB;AAAA,EAVkB,IAAA,GAAO,kBAAA;AAY7B;AAgBO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EAIzC,WAAA,CACoB,YACA,QAAA,EAClB;AAEE,IAAA,KAAA,CAAM,CAAA,mBAAA,EAAsB,UAAU,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAE,CAAA;AAJ7C,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAKpB;AAAA,EATkB,IAAA,GAAO,mBAAA;AAW7B,CAAA;AAaO,IAAM,kBAAA,GAAN,cAAiC,KAAA,CAAM;AAAA,EAI1C,WAAA,CACoB,UAAA,EACA,WAAA,EACA,YAAA,EAClB;AAEE,IAAA,KAAA;AAAA,MACI,CAAA,yBAAA,EAA4B,UAAU,CAAA,WAAA,EAAc,YAAY,SAAS,WAAW,CAAA;AAAA,KACxF;AAPgB,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AACA,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AAAA,EAOpB;AAAA,EAZkB,IAAA,GAAO,oBAAA;AAc7B,CAAA;ACnFA,SAAS,oBAAA,CAAqB,MAAY,OAAA,EAAiC;AAEvE,EAAA,IAAI,YAAY,QAAA,EAAU;AAEtB,IAAA,OAAO,KAAK,WAAA,EAAY;AAAA,EAE5B;AAEA,EAAA,OAAO,IAAA;AAEX;AAKA,IAAM,cAAN,MAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAed,MAAM,OAAA,CACF,EAAA,EACA,YACA,QAAA,EACA,OAAA,GAAuB,EAAC,EACX;AAGb,IAAA,MAAM,IAAA,GAAO,EAAE,GAAG,oBAAA,EAAsB,GAAG,OAAA,EAAQ;AACnD,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAG3B,IAAA,QAAA,CAAS,IAAA,CAAK,gBAAA,EAAkB,EAAE,UAAA,EAAY,UAAU,CAAA;AAGxD,IAAA,OAAO,IAAA,EAAM;AAGT,MAAA,MAAM,IAAA,CAAK,cAAA,CAAe,EAAA,EAAI,UAAA,EAAY,KAAK,OAAO,CAAA;AAGtD,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,UAAU,CAAA;AAElD,MAAA,IAAI,CAAC,QAAA,EAAU;AAGX,QAAA,MAAM,OAAO,MAAM,IAAA,CAAK,WAAW,EAAA,EAAI,UAAA,EAAY,UAAU,IAAI,CAAA;AACjE,QAAA,QAAA,CAAS,KAAK,eAAA,EAAiB;AAAA,UAC3B,UAAA;AAAA,UACA,QAAA;AAAA,UACA,WAAW,IAAA,CAAK;AAAA,SACnB,CAAA;AAED,QAAA,OAAO,IAAA;AAAA,MAEX;AAIA,MAAA,IAAI,QAAA,CAAS,aAAa,QAAA,EAAU;AAGhC,QAAA,MAAM,OAAO,MAAM,IAAA,CAAK,WAAW,EAAA,EAAI,UAAA,EAAY,UAAU,IAAI,CAAA;AACjE,QAAA,QAAA,CAAS,KAAK,eAAA,EAAiB;AAAA,UAC3B,UAAA;AAAA,UACA,QAAA;AAAA,UACA,WAAW,IAAA,CAAK;AAAA,SACnB,CAAA;AAED,QAAA,OAAO,IAAA;AAAA,MAEX;AAGA,MAAA,QAAA,CAAS,KAAK,cAAA,EAAgB;AAAA,QAC1B,UAAA;AAAA,QACA,QAAQ,QAAA,CAAS,QAAA;AAAA,QACjB,WAAW,QAAA,CAAS;AAAA,OACvB,CAAA;AAED,MAAA,IAAI,CAAC,KAAK,IAAA,EAAM;AAEZ,QAAA,MAAM,IAAI,gBAAA;AAAA,UACN,UAAA;AAAA,UACA,QAAA,CAAS,QAAA;AAAA,UACT,QAAA,CAAS,QAAA;AAAA,UACT,QAAA,CAAS,SAAA;AAAA,UACT,QAAA,CAAS;AAAA,SACb;AAAA,MAEJ;AAGA,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAC7B,MAAA,IAAI,OAAA,IAAW,KAAK,WAAA,EAAa;AAE7B,QAAA,MAAM,IAAI,gBAAA;AAAA,UACN,UAAA;AAAA,UACA,QAAA,CAAS,QAAA;AAAA,UACT,QAAA,CAAS,QAAA;AAAA,UACT,QAAA,CAAS,SAAA;AAAA,UACT,QAAA,CAAS;AAAA,SACb;AAAA,MAEJ;AAGA,MAAA,MAAM,KAAA,CAAM,KAAK,YAAY,CAAA;AAAA,IAEjC;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OAAA,CAAQ,EAAA,EAA2B,UAAA,EAAoB,QAAA,EAAiC;AAG1F,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,UAAU,CAAA;AAElD,IAAA,IAAI,CAAC,QAAA,EAAU;AAEX,MAAA,MAAM,IAAI,iBAAA,CAAkB,UAAA,EAAY,QAAQ,CAAA;AAAA,IAEpD;AAEA,IAAA,IAAI,QAAA,CAAS,aAAa,QAAA,EAAU;AAEhC,MAAA,MAAM,IAAI,kBAAA,CAAmB,UAAA,EAAY,QAAA,EAAU,SAAS,QAAQ,CAAA;AAAA,IAExE;AAGA,IAAA,MAAM,EAAA,CACD,UAAA,CAAW,YAAA,CAAa,IAAI,EAC5B,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,UAAU,EACpC,KAAA,CAAM,WAAA,EAAa,GAAA,EAAK,QAAQ,EAChC,OAAA,EAAQ;AAEb,IAAA,QAAA,CAAS,IAAA,CAAK,eAAA,EAAiB,EAAE,UAAA,EAAY,UAAU,CAAA;AAAA,EAE3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,YAAA,CAAa,EAAA,EAA2B,UAAA,EAAsC;AAEhF,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,UAAU,CAAA;AAClD,IAAA,IAAI,CAAC,QAAA,EAAU;AAEX,MAAA,OAAO,KAAA;AAAA,IAEX;AAEA,IAAA,MAAM,EAAA,CAAG,UAAA,CAAW,YAAA,CAAa,IAAI,CAAA,CAAE,MAAM,aAAA,EAAe,GAAA,EAAK,UAAU,CAAA,CAAE,OAAA,EAAQ;AAErF,IAAA,QAAA,CAAS,KAAK,eAAA,EAAiB;AAAA,MAC3B,UAAA;AAAA,MACA,UAAU,QAAA,CAAS;AAAA,KACtB,CAAA;AAED,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,SACF,EAAA,EACA,UAAA,EACA,UACA,SAAA,EACA,OAAA,GAAuB,EAAC,EACd;AAEV,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,EAAA,EAAI,UAAA,EAAY,UAAU,OAAO,CAAA;AAEpD,IAAA,IAAI;AAEA,MAAA,OAAO,MAAM,SAAA,EAAU;AAAA,IAE3B,CAAA,SACA;AAEI,MAAA,MAAM,GAAG,GAAG,CAAA,GAAI,MAAMJ,OAAAA,CAAQ,MAAM,IAAA,CAAK,OAAA,CAAQ,EAAA,EAAI,UAAA,EAAY,QAAQ,CAAC,CAAA;AAE1E,MAAA,IAAI,GAAA,EAAK;AAGL,QAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,UACnB,MAAA,EAAQ,MAAA;AAAA,UACR,KAAA,EAAO,GAAA;AAAA,UACP,OAAA,EAAS,EAAE,UAAA,EAAY,QAAA;AAAS,SACnC,CAAA;AAAA,MAEL;AAAA,IAEJ;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,QAAA,CACF,EAAA,EACA,UAAA,EACA,QAAA,EACA,UAAmB,UAAA,EACN;AAEb,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,UAAU,CAAA;AAElD,IAAA,IAAI,CAAC,QAAA,EAAU;AAEX,MAAA,MAAM,IAAI,iBAAA,CAAkB,UAAA,EAAY,QAAQ,CAAA;AAAA,IAEpD;AAEA,IAAA,IAAI,QAAA,CAAS,aAAa,QAAA,EAAU;AAEhC,MAAA,MAAM,IAAI,kBAAA,CAAmB,UAAA,EAAY,QAAA,EAAU,SAAS,QAAQ,CAAA;AAAA,IAExE;AAEA,IAAA,IAAI,QAAA,CAAS,SAAA,mBAAY,IAAI,IAAA,EAAK,EAAG;AAGjC,MAAA,MAAM,IAAA,CAAK,cAAA,CAAe,EAAA,EAAI,UAAA,EAAY,OAAO,CAAA;AAEjD,MAAA,MAAM,IAAI,gBAAA,CAAiB,UAAA,EAAY,QAAA,EAAU,SAAS,SAAS,CAAA;AAAA,IAEvE;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,MAAA,CACF,EAAA,EACA,YACA,QAAA,EACA,OAAA,GAAuB,EAAC,EACX;AAGb,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,EAAA,EAAI,UAAA,EAAY,QAAQ,CAAA;AAE5C,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,EAAA,EAAI,UAAA,EAAY,UAAU,OAAO,CAAA;AAAA,EAE5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,MAAA,CACF,EAAA,EACA,UAAA,EACA,UAAmB,UAAA,EACA;AAGnB,IAAA,MAAM,IAAA,CAAK,cAAA,CAAe,EAAA,EAAI,UAAA,EAAY,OAAO,CAAA;AAEjD,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,UAAU,CAAA;AAE9C,IAAA,OAAO;AAAA,MACH,UAAU,IAAA,KAAS,IAAA;AAAA,MACnB;AAAA,KACJ;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,OAAA,CAAQ,EAAA,EAA2B,UAAA,EAA0C;AAEvF,IAAA,MAAM,GAAA,GAAM,MAAM,EAAA,CACb,UAAA,CAAW,aAAa,IAAI,CAAA,CAC5B,SAAA,EAAU,CACV,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,UAAU,EACpC,gBAAA,EAAiB;AAEtB,IAAA,IAAI,CAAC,GAAA,EAAK;AAEN,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,OAAO;AAAA,MACH,UAAU,GAAA,CAAI,SAAA;AAAA,MACd,QAAA,EAAU,IAAI,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA;AAAA,MAChC,SAAA,EAAW,IAAI,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA;AAAA,MAClC,MAAA,EAAQ,IAAI,MAAA,IAAU;AAAA,KAC1B;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,UAAA,CACV,EAAA,EACA,UAAA,EACA,UACA,IAAA,EACa;AAEb,IAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AACrB,IAAA,MAAM,YAAY,IAAI,IAAA,CAAK,IAAI,OAAA,EAAQ,GAAI,KAAK,OAAO,CAAA;AAEvD,IAAA,MAAM,EAAA,CACD,UAAA,CAAW,YAAA,CAAa,IAAI,EAC5B,MAAA,CAAO;AAAA,MACJ,WAAA,EAAa,UAAA;AAAA,MACb,SAAA,EAAW,QAAA;AAAA,MACX,SAAA,EAAW,oBAAA,CAAqB,GAAA,EAAK,IAAA,CAAK,OAAO,CAAA;AAAA,MACjD,UAAA,EAAY,oBAAA,CAAqB,SAAA,EAAW,IAAA,CAAK,OAAO,CAAA;AAAA,MACxD,MAAA,EAAQ,KAAK,MAAA,IAAU;AAAA,KAC1B,EACA,OAAA,EAAQ;AAEb,IAAA,OAAO;AAAA,MACH,QAAA,EAAU,QAAA;AAAA,MACV,QAAA,EAAU,GAAA;AAAA,MACV,SAAA;AAAA,MACA,QAAQ,IAAA,CAAK;AAAA,KACjB;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,UAAA,CACV,EAAA,EACA,UAAA,EACA,UACA,IAAA,EACa;AAEb,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,IAAW,oBAAA,CAAqB,OAAA;AACrD,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,IAAW,oBAAA,CAAqB,OAAA;AACrD,IAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AACrB,IAAA,MAAM,YAAY,IAAI,IAAA,CAAK,GAAA,CAAI,OAAA,KAAY,OAAO,CAAA;AAElD,IAAA,MAAM,YAAA,GAA0D;AAAA,MAC5D,UAAA,EAAY,oBAAA,CAAqB,SAAA,EAAW,OAAO;AAAA,KACvD;AAEA,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAE3B,MAAA,YAAA,CAAa,QAAQ,IAAI,IAAA,CAAK,MAAA;AAAA,IAElC;AAEA,IAAA,MAAM,GACD,WAAA,CAAY,YAAA,CAAa,IAAI,CAAA,CAC7B,GAAA,CAAI,YAAsC,CAAA,CAC1C,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,UAAU,CAAA,CACpC,KAAA,CAAM,aAAa,GAAA,EAAK,QAAQ,EAChC,OAAA,EAAQ;AAGb,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,UAAU,CAAA;AAE9C,IAAA,OAAO,IAAA;AAAA,EAEX;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAA,CACV,EAAA,EACA,UAAA,EACA,UAAmB,UAAA,EACN;AAEb,IAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AACrB,IAAA,MAAM,QAAA,GAAW,oBAAA,CAAqB,GAAA,EAAK,OAAO,CAAA;AAGlD,IAAA,MAAM,OAAA,GAAU,MAAM,EAAA,CACjB,UAAA,CAAW,aAAa,IAAI,CAAA,CAC5B,MAAA,CAAO,CAAC,WAAW,CAAC,EACpB,KAAA,CAAM,aAAA,EAAe,KAAK,UAAU,CAAA,CACpC,MAAM,YAAA,EAAc,GAAA,EAAK,QAAgB,CAAA,CACzC,gBAAA,EAAiB;AAEtB,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,MAAM,EAAA,CACD,UAAA,CAAW,YAAA,CAAa,IAAI,EAC5B,KAAA,CAAM,aAAA,EAAe,GAAA,EAAK,UAAU,EACpC,KAAA,CAAM,YAAA,EAAc,GAAA,EAAK,QAAgB,EACzC,OAAA,EAAQ;AAEb,MAAA,QAAA,CAAS,KAAK,cAAA,EAAgB;AAAA,QAC1B,UAAA;AAAA,QACA,gBAAgB,OAAA,CAAQ;AAAA,OAC3B,CAAA;AAAA,IAEL;AAAA,EAEJ;AAEJ,CAAA;AAMA,IAAIS,SAAAA,GAA+B,IAAA;AAa5B,SAAS,cAAA,GAA8B;AAE1C,EAAA,IAAI,CAACA,SAAAA,EAAU;AAEX,IAAAA,SAAAA,GAAW,IAAI,WAAA,EAAY;AAAA,EAE/B;AAEA,EAAA,OAAOA,SAAAA;AAEX;AAiBA,SAAS,MAAM,EAAA,EAA2B;AAEtC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AAE3D;;;ACvgBA,IAAM,eAAA,GAAuF;AAAA,EACzF,KAAA,EAAO,KAAA;AAAA,EACP,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,KAAA;AAAA,EACT,MAAA,EAAQ;AACZ,CAAA;AAGA,IAAM,YAAA,GAAe,kCAAA;AA0BrB,eAAsB,aAAA,CAClB,OAAA,EACA,MAAA,EACA,OAAA,GAAyB,EAAC,EACL;AAErB,EAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,eAAA,EAAiB,GAAG,OAAA,EAAQ;AAG9C,EAAA,MAAM,GAAG,WAAW,CAAA,GAAIR,YAAY,MAAM;AAEtC,IAAA,cAAA,CAAe,MAAM,CAAA;AAAA,EAEzB,CAAC,CAAA;AAED,EAAA,IAAI,WAAA,EAAa;AAEb,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,WAAA;AAAA,MACP,SAAS,EAAE,IAAA,EAAM,MAAA,CAAO,IAAA,EAAM,WAAW,UAAA;AAAW,KACvD,CAAA;AAED,IAAA,OAAO,mBAAmB,MAAA,CAAO,IAAA,EAAM,QAAA,EAAU,WAAA,CAAY,SAAS,KAAK,CAAA;AAAA,EAE/E;AAGA,EAAA,MAAM,QAAQ,MAAA,CAAO,WAAA;AAErB,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AAEpB,IAAA,MAAM,IAAI,qBAAA,CAAsB,MAAA,CAAO,IAAA,EAAM,4BAA4B,CAAA;AAAA,EAE7E;AAGA,EAAA,MAAM,CAAC,cAAc,UAAU,CAAA,GAAI,MAAMD,OAAAA,CAAQ,MAAM,wBAAA,CAAyB,KAAK,CAAC,CAAA;AAEtF,EAAA,IAAI,UAAA,IAAc,CAAC,YAAA,EAAc;AAE7B,IAAA,MAAM,IAAI,qBAAA;AAAA,MACN,MAAA,CAAO,IAAA;AAAA,MACP;AAAA,KACJ;AAAA,EAEJ;AAGA,EAAA,MAAM,CAAC,SAAA,EAAW,WAAW,CAAA,GAAI,MAAMA,OAAAA;AAAA,IAAQ,MAC3C,oBAAA,CAAqB,KAAA,EAAO,OAAA,CAAQ,MAAM;AAAA,GAC9C;AAEA,EAAA,IAAI,WAAA,EAAa;AAEb,IAAA,OAAO,mBAAmB,MAAA,CAAO,IAAA,EAAM,QAAA,EAAU,WAAA,CAAY,SAAS,KAAK,CAAA;AAAA,EAE/E;AAEA,EAAA,MAAM,cAAA,GAAiB,wBAAwB,SAAS,CAAA;AAGxD,EAAA,MAAM,UAAU,IAAI,aAAA,CAAc,OAAA,CAAQ,EAAA,EAAI,QAAQ,UAAU,CAAA;AAGhE,EAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,CAAC,KAAK,OAAA,EAAS;AAE/B,IAAA,MAAM,cAAA,GAAiB,MAAM,OAAA,CAAQ,QAAA;AAAA,MACjC,MAAA,CAAO,IAAA;AAAA,MACP,cAAA;AAAA,MACA,IAAA,CAAK;AAAA,KACT;AAEA,IAAA,IAAI,CAAC,eAAe,QAAA,EAAU;AAE1B,MAAA,QAAA,CAAS,KAAK,aAAA,EAAe;AAAA,QACzB,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,MAAA,EAAQ,eAAe,UAAA,IAAc;AAAA,OACxC,CAAA;AAED,MAAA,OAAO;AAAA,QACH,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,SAAA,EAAW,QAAA;AAAA,QACX,MAAA,EAAQ,SAAA;AAAA,QACR,OAAO,EAAC;AAAA,QACR,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,OACpC;AAAA,IAEJ;AAAA,EAEJ;AAGA,EAAA,IAAI,KAAK,MAAA,EAAQ;AAEb,IAAA,OAAO,aAAA,CAAc,OAAA,EAAS,MAAA,EAAQ,KAAA,EAAO,UAAU,KAAK,CAAA;AAAA,EAEhE;AAGA,EAAA,IAAI,KAAK,OAAA,EAAS;AAEd,IAAA,OAAO,eAAe,OAAA,EAAS,MAAA,EAAQ,OAAO,QAAA,EAAU,IAAA,CAAK,QAAQ,KAAK,CAAA;AAAA,EAE9E;AAGA,EAAA,MAAM,cAAc,cAAA,EAAe;AACnC,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,OAAA,CAAQ,QAAQ,CAAA;AAEhD,EAAA,MAAM,GAAG,OAAO,CAAA,GAAI,MAAMA,OAAAA;AAAA,IAAQ,MAC9B,WAAA,CAAY,OAAA,CAAQ,QAAQ,EAAA,EAAI,OAAA,CAAQ,YAAY,QAAA,EAAU;AAAA,MAC1D,MAAA,EAAQ,CAAA,QAAA,EAAW,MAAA,CAAO,IAAI,CAAA,CAAA;AAAA,MAC9B,SAAS,OAAA,CAAQ;AAAA,KACpB;AAAA,GACL;AAEA,EAAA,IAAI,OAAA,EAAS;AAGT,IAAA,MAAM,OAAA;AAAA,EAEV;AAGA,EAAA,MAAM,CAAC,MAAA,EAAQ,OAAO,CAAA,GAAI,MAAMA,OAAAA;AAAA,IAAQ,MACpC,YAAA;AAAA,MACI,OAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA;AAAA,MACA,cAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA;AACJ,GACJ;AAGA,EAAA,MAAMA,OAAAA,CAAQ,MAAM,WAAA,CAAY,OAAA,CAAQ,QAAQ,EAAA,EAAI,OAAA,CAAQ,UAAA,EAAY,QAAQ,CAAC,CAAA;AAEjF,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,MAAM,OAAA;AAAA,EAEV;AAEA,EAAA,OAAO,MAAA;AAEX;AAcA,eAAsB,YAAA,CAClB,OAAA,EACA,MAAA,EACA,OAAA,GAAyB,EAAC,EACL;AAErB,EAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,eAAA,EAAiB,GAAG,OAAA,EAAQ;AAG9C,EAAA,IAAI,CAAC,cAAA,CAAe,MAAM,CAAA,EAAG;AAEzB,IAAA,MAAM,IAAI,qBAAA;AAAA,MACN,MAAA,CAAO,IAAA;AAAA,MACP;AAAA,KACJ;AAAA,EAEJ;AAEA,EAAA,MAAM,QAAQ,MAAA,CAAO,WAAA;AAGrB,EAAA,MAAM,CAAC,SAAA,EAAW,WAAW,CAAA,GAAI,MAAMA,OAAAA;AAAA,IAAQ,MAC3C,oBAAA,CAAqB,KAAA,EAAO,OAAA,CAAQ,MAAM;AAAA,GAC9C;AAEA,EAAA,IAAI,WAAA,EAAa;AAEb,IAAA,OAAO,mBAAmB,MAAA,CAAO,IAAA,EAAM,QAAA,EAAU,WAAA,CAAY,SAAS,KAAK,CAAA;AAAA,EAE/E;AAEA,EAAA,MAAM,cAAA,GAAiB,wBAAwB,SAAS,CAAA;AAGxD,EAAA,MAAM,UAAU,IAAI,aAAA,CAAc,OAAA,CAAQ,EAAA,EAAI,QAAQ,UAAU,CAAA;AAChE,EAAA,MAAM,UAAU,IAAI,aAAA,CAAc,OAAA,CAAQ,EAAA,EAAI,QAAQ,UAAU,CAAA;AAGhE,EAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,CAAC,KAAK,OAAA,EAAS;AAE/B,IAAA,MAAM,kBAAkB,MAAM,OAAA,CAAQ,UAAU,MAAA,CAAO,IAAA,EAAM,KAAK,KAAK,CAAA;AAEvE,IAAA,IAAI,CAAC,gBAAgB,SAAA,EAAW;AAE5B,MAAA,IAAI,eAAA,CAAgB,WAAW,aAAA,EAAe;AAE1C,QAAA,MAAM,IAAI,qBAAA,CAAsB,MAAA,CAAO,IAAI,CAAA;AAAA,MAE/C;AAEA,MAAA,QAAA,CAAS,KAAK,aAAA,EAAe;AAAA,QACzB,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,MAAA,EAAQ,gBAAgB,MAAA,IAAU;AAAA,OACrC,CAAA;AAED,MAAA,OAAO;AAAA,QACH,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,SAAA,EAAW,QAAA;AAAA,QACX,MAAA,EAAQ,SAAA;AAAA,QACR,OAAO,EAAC;AAAA,QACR,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,OACpC;AAAA,IAEJ;AAAA,EAEJ;AAGA,EAAA,IAAI,KAAK,MAAA,EAAQ;AAEb,IAAA,OAAO,aAAA,CAAc,OAAA,EAAS,MAAA,EAAQ,KAAA,EAAO,UAAU,KAAK,CAAA;AAAA,EAEhE;AAGA,EAAA,IAAI,KAAK,OAAA,EAAS;AAEd,IAAA,OAAO,eAAe,OAAA,EAAS,MAAA,EAAQ,OAAO,QAAA,EAAU,IAAA,CAAK,QAAQ,KAAK,CAAA;AAAA,EAE9E;AAGA,EAAA,MAAM,cAAc,cAAA,EAAe;AACnC,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,OAAA,CAAQ,QAAQ,CAAA;AAEhD,EAAA,MAAM,GAAG,OAAO,CAAA,GAAI,MAAMA,OAAAA;AAAA,IAAQ,MAC9B,WAAA,CAAY,OAAA,CAAQ,QAAQ,EAAA,EAAI,OAAA,CAAQ,YAAY,QAAA,EAAU;AAAA,MAC1D,MAAA,EAAQ,CAAA,QAAA,EAAW,MAAA,CAAO,IAAI,CAAA,CAAA;AAAA,MAC9B,SAAS,OAAA,CAAQ;AAAA,KACpB;AAAA,GACL;AAEA,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,MAAM,OAAA;AAAA,EAEV;AAGA,EAAA,MAAM,CAAC,MAAA,EAAQ,OAAO,CAAA,GAAI,MAAMA,OAAAA;AAAA,IAAQ,MACpC,YAAA;AAAA,MACI,OAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA;AAAA,MACA,cAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA;AACJ,GACJ;AAGA,EAAA,MAAMA,OAAAA,CAAQ,MAAM,WAAA,CAAY,OAAA,CAAQ,QAAQ,EAAA,EAAI,OAAA,CAAQ,UAAA,EAAY,QAAQ,CAAC,CAAA;AAEjF,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,MAAM,OAAA;AAAA,EAEV;AAGA,EAAA,IAAI,MAAA,CAAO,WAAW,SAAA,EAAW;AAE7B,IAAA,MAAM,OAAA,CAAQ,cAAA,CAAe,MAAA,CAAO,IAAI,CAAA;AAAA,EAE5C;AAEA,EAAA,OAAO,MAAA;AAEX;AASA,eAAe,aACX,OAAA,EACA,MAAA,EACA,OACA,SAAA,EACA,QAAA,EACA,SACA,SAAA,EACqB;AAGrB,EAAA,MAAM,aAAA,GAAgB,MAAM,WAAA,CAAY,KAAA,EAAO,QAAQ,MAAM,CAAA;AAG7D,EAAA,MAAM,CAAC,WAAA,EAAa,SAAS,CAAA,GAAI,MAAMA,OAAAA;AAAA,IAAQ,MAC3C,QAAQ,eAAA,CAAgB;AAAA,MACpB,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,SAAA;AAAA,MACA,UAAA,EAAY,cAAA,CAAe,OAAA,CAAQ,QAAQ;AAAA,KAC9C;AAAA,GACL;AAEA,EAAA,IAAI,SAAA,EAAW;AAEX,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,SAAA;AAAA,MACP,SAAS,EAAE,IAAA,EAAM,MAAA,CAAO,IAAA,EAAM,WAAW,kBAAA;AAAmB,KAC/D,CAAA;AAED,IAAA,OAAO,mBAAmB,MAAA,CAAO,IAAA,EAAM,SAAA,EAAW,SAAA,CAAU,SAAS,SAAS,CAAA;AAAA,EAElF;AAGA,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAAoB;AAE9C,EAAA,KAAA,MAAW,QAAQ,aAAA,EAAe;AAE9B,IAAA,MAAM,CAAC,EAAE,CAAA,GAAI,MAAMA,QAAQ,MAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAC,CAAA;AAC3D,IAAA,aAAA,CAAc,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM,EAAA,IAAM,EAAE,CAAA;AAAA,EAEzC;AAGA,EAAA,MAAM,gBAAA,GAAmB,MAAM,OAAA,CAAQ,iBAAA;AAAA,IACnC,WAAA;AAAA,IACA,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACtB,UAAU,CAAA,CAAE,IAAA;AAAA,MACZ,UAAU,CAAA,CAAE,IAAA;AAAA,MACZ,QAAA,EAAU,aAAA,CAAc,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA,IAAK;AAAA,KAC3C,CAAE;AAAA,GACN;AAEA,EAAA,IAAI,gBAAA,EAAkB;AAGlB,IAAA,MAAM,QAAQ,iBAAA,CAAkB,WAAA,EAAa,QAAA,EAAU,QAAA,EAAU,GAAG,gBAAgB,CAAA;AAEpF,IAAA,OAAO;AAAA,MACH,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,SAAA;AAAA,MACA,MAAA,EAAQ,QAAA;AAAA,MACR,OAAO,EAAC;AAAA,MACR,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AAAA,MAChC,KAAA,EAAO,gBAAA;AAAA,MACP;AAAA,KACJ;AAAA,EAEJ;AAGA,EAAA,QAAA,CAAS,KAAK,cAAA,EAAgB;AAAA,IAC1B,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,SAAA;AAAA,IACA,OAAO,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI;AAAA,GACzC,CAAA;AAGD,EAAA,MAAM,UAA8B,EAAC;AACrC,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,IAAI,UAAA;AACJ,EAAA,IAAI,YAAA;AAGJ,EAAA,MAAM,GAAG,aAAa,CAAA,GAAI,MAAMA,QAAQ,YAAY;AAEhD,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,aAAA,CAAc,QAAQ,CAAA,EAAA,EAAK;AAE3C,MAAA,MAAM,IAAA,GAAO,cAAc,CAAC,CAAA;AAE5B,MAAA,IAAI,CAAC,IAAA,EAAM;AAEX,MAAA,QAAA,CAAS,KAAK,aAAA,EAAe;AAAA,QACzB,QAAQ,MAAA,CAAO,IAAA;AAAA,QACf,UAAU,IAAA,CAAK,IAAA;AAAA,QACf,KAAA,EAAO,CAAA;AAAA,QACP,OAAO,aAAA,CAAc;AAAA,OACxB,CAAA;AAED,MAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAGlC,MAAA,MAAM,CAAC,UAAA,EAAY,OAAO,CAAA,GAAI,MAAMA,OAAAA,CAAQ,MAAM,iBAAA,CAAkB,OAAA,EAAS,IAAA,CAAK,IAAI,CAAC,CAAA;AAEvF,MAAA,IAAI,OAAA,EAAS;AAET,QAAA,MAAM2B,WAAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AAGvC,QAAA,MAAA,GAAS,IAAA;AACT,QAAA,UAAA,GAAa,IAAA,CAAK,IAAA;AAClB,QAAA,YAAA,GAAe,OAAA,CAAQ,OAAA;AAEvB,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACT,UAAU,IAAA,CAAK,IAAA;AAAA,UACf,QAAA,EAAU,aAAA,CAAc,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,IAAK,EAAA;AAAA,UAC1C,MAAA,EAAQ,QAAA;AAAA,UACR,OAAO,OAAA,CAAQ,OAAA;AAAA,UACf,UAAA,EAAAA;AAAA,SACH,CAAA;AAGD,QAAA,MAAMC,UAAAA,GAAY,MAAM,OAAA,CAAQ,mBAAA;AAAA,UAC5B,WAAA;AAAA,UACA,IAAA,CAAK,IAAA;AAAA,UACL,QAAA;AAAA,UACAD,WAAAA;AAAA,UACA,OAAA,CAAQ;AAAA,SACZ;AAEA,QAAA,IAAIC,UAAAA,EAAW;AAGX,UAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,YACnB,MAAA,EAAQ,QAAA;AAAA,YACR,KAAA,EAAO,IAAI,KAAA,CAAMA,UAAS,CAAA;AAAA,YAC1B,SAAS,EAAE,QAAA,EAAU,IAAA,CAAK,IAAA,EAAM,WAAW,sBAAA;AAAuB,WACrE,CAAA;AAAA,QAEL;AAEA,QAAA;AAAA,MAEJ;AAGA,MAAA,MAAM,GAAG,OAAO,CAAA,GAAI,MAAM5B,OAAAA,CAAQ,MAAMkB,GAAAA,CAAI,GAAA,CAAI,UAAU,CAAA,CAAE,OAAA,CAAQ,OAAA,CAAQ,EAAE,CAAC,CAAA;AAE/E,MAAA,MAAM,UAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AAEvC,MAAA,IAAI,OAAA,EAAS;AAGT,QAAA,MAAA,GAAS,IAAA;AACT,QAAA,UAAA,GAAa,IAAA,CAAK,IAAA;AAClB,QAAA,YAAA,GAAe,OAAA,CAAQ,OAAA;AAEvB,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACT,UAAU,IAAA,CAAK,IAAA;AAAA,UACf,QAAA,EAAU,aAAA,CAAc,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,IAAK,EAAA;AAAA,UAC1C,MAAA,EAAQ,QAAA;AAAA,UACR,OAAO,OAAA,CAAQ,OAAA;AAAA,UACf;AAAA,SACH,CAAA;AAGD,QAAA,MAAMU,UAAAA,GAAY,MAAM,OAAA,CAAQ,mBAAA;AAAA,UAC5B,WAAA;AAAA,UACA,IAAA,CAAK,IAAA;AAAA,UACL,QAAA;AAAA,UACA,UAAA;AAAA,UACA,OAAA,CAAQ;AAAA,SACZ;AAEA,QAAA,IAAIA,UAAAA,EAAW;AAGX,UAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,YACnB,MAAA,EAAQ,QAAA;AAAA,YACR,KAAA,EAAO,IAAI,KAAA,CAAMA,UAAS,CAAA;AAAA,YAC1B,SAAS,EAAE,QAAA,EAAU,IAAA,CAAK,IAAA,EAAM,WAAW,sBAAA;AAAuB,WACrE,CAAA;AAAA,QAEL;AAEA,QAAA;AAAA,MAEJ;AAGA,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACT,UAAU,IAAA,CAAK,IAAA;AAAA,QACf,QAAA,EAAU,aAAA,CAAc,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,IAAK,EAAA;AAAA,QAC1C,MAAA,EAAQ,SAAA;AAAA,QACR;AAAA,OACH,CAAA;AAGD,MAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,mBAAA;AAAA,QAC5B,WAAA;AAAA,QACA,IAAA,CAAK,IAAA;AAAA,QACL,SAAA;AAAA,QACA;AAAA,OACJ;AAEA,MAAA,IAAI,SAAA,EAAW;AAGX,QAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,UACnB,MAAA,EAAQ,QAAA;AAAA,UACR,KAAA,EAAO,IAAI,KAAA,CAAM,SAAS,CAAA;AAAA,UAC1B,SAAS,EAAE,QAAA,EAAU,IAAA,CAAK,IAAA,EAAM,WAAW,uBAAA;AAAwB,SACtE,CAAA;AAAA,MAEL;AAAA,IAEJ;AAAA,EAEJ,CAAC,CAAA;AAGD,EAAA,IAAI,aAAA,EAAe;AAEf,IAAA,IAAI,CAAC,MAAA,EAAQ;AAET,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,YAAA,GAAe,aAAA,CAAc,OAAA;AAAA,IAEjC;AAEA,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,aAAA;AAAA,MACP,SAAS,EAAE,IAAA,EAAM,MAAA,CAAO,IAAA,EAAM,WAAW,eAAA;AAAgB,KAC5D,CAAA;AAAA,EAEL;AAIA,EAAA,IAAI,MAAA,EAAQ;AAER,IAAA,MAAM,UAAA,GAAa,UAAA,GACb,CAAA,EAAG1B,KAAAA,CAAK,QAAA,CAAS,UAAU,CAAC,CAAA,SAAA,EAAY,YAAA,IAAgB,eAAe,CAAA,CAAA,GACvE,eAAA;AAEN,IAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,kBAAA,CAAmB,aAAa,UAAU,CAAA;AAE1E,IAAA,IAAI,SAAA,EAAW;AAGX,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,IAAI,KAAA,CAAM,SAAS,CAAA;AAAA,QAC1B,OAAA,EAAS,EAAE,WAAA,EAAa,SAAA,EAAW,sBAAA;AAAuB,OAC7D,CAAA;AAAA,IAEL;AAAA,EAEJ;AAGA,EAAA,MAAM,eAAA,GAAkB,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AAC5C,EAAA,MAAM,eAAA,GAAkB,SAAS,QAAA,GAAW,SAAA;AAG5C,EAAA,MAAM,YAAA,GAAe,UAAA,GACf,CAAA,EAAGA,KAAAA,CAAK,QAAA,CAAS,UAAU,CAAC,CAAA,EAAA,EAAK,YAAA,IAAgB,eAAe,CAAA,CAAA,GAChE,YAAA;AAEN,EAAA,MAAM,aAAA,GAAgB,MAAM,OAAA,CAAQ,iBAAA;AAAA,IAChC,WAAA;AAAA,IACA,eAAA;AAAA,IACA,QAAA;AAAA,IACA,eAAA;AAAA,IACA,SAAS,YAAA,GAAe;AAAA,GAC5B;AAIA,EAAA,MAAM,WAAA,GAAc,gBAAgB,QAAA,GAAW,eAAA;AAC/C,EAAA,MAAM,gBAAgB,aAAA,GAChB,CAAA,EAAG,gBAAgB,6CAA6C,CAAA,gBAAA,EAAmB,aAAa,CAAA,CAAA,GAChG,YAAA;AAGN,EAAA,QAAA,CAAS,KAAK,iBAAA,EAAmB;AAAA,IAC7B,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,SAAA;AAAA,IACA,MAAA,EAAQ,WAAA;AAAA,IACR,UAAA,EAAY;AAAA,GACf,CAAA;AAED,EAAA,OAAO;AAAA,IACH,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,SAAA;AAAA,IACA,MAAA,EAAQ,WAAA;AAAA,IACR,KAAA,EAAO,OAAA;AAAA,IACP,UAAA,EAAY,eAAA;AAAA,IACZ,KAAA,EAAO,WAAA,KAAgB,QAAA,GAAW,aAAA,GAAgB,MAAA;AAAA,IAClD;AAAA,GACJ;AAEJ;AASA,eAAe,eACX,OAAA,EACA,MAAA,EACA,KAAA,EACA,SAAA,EACA,QACA,SAAA,EACqB;AAErB,EAAA,MAAM,aAAA,GAAgB,MAAM,WAAA,CAAY,KAAA,EAAO,QAAQ,MAAM,CAAA;AAC7D,EAAA,MAAM,UAA8B,EAAC;AACrC,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,KAAA,MAAW,QAAQ,aAAA,EAAe;AAE9B,IAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAGlC,IAAA,MAAM,CAAC,QAAQ,CAAA,GAAI,MAAMF,QAAQ,MAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAC,CAAA;AAGjE,IAAA,MAAM,CAAC,UAAA,EAAY,OAAO,CAAA,GAAI,MAAMA,OAAAA,CAAQ,MAAM,iBAAA,CAAkB,OAAA,EAAS,IAAA,CAAK,IAAI,CAAC,CAAA;AAEvF,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACT,UAAU,IAAA,CAAK,IAAA;AAAA,QACf,UAAU,QAAA,IAAY,EAAA;AAAA,QACtB,MAAA,EAAQ,QAAA;AAAA,QACR,OAAO,OAAA,CAAQ,OAAA;AAAA,QACf,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,OACnC,CAAA;AAED,MAAA;AAAA,IAEJ;AAEA,IAAA,QAAA,CAAS,IAAA,CAAK,mBAAA,CAAoB,IAAA,CAAK,IAAI,IAAI,UAAU,CAAA;AAEzD,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACT,UAAU,IAAA,CAAK,IAAA;AAAA,MACf,UAAU,QAAA,IAAY,EAAA;AAAA,MACtB,MAAA,EAAQ,SAAA;AAAA,MACR,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AAAA,MAChC,WAAA,EAAa;AAAA,KAChB,CAAA;AAAA,EAEL;AAGA,EAAA,IAAI,MAAA,EAAQ;AAER,IAAA,MAAM,EAAE,SAAA,EAAAQ,UAAAA,EAAU,GAAI,MAAM,OAAO,aAAkB,CAAA;AAErD,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,IAAA,CAAK,MAAM,CAAA;AACxC,IAAA,MAAMA,UAAAA,CAAU,MAAA,EAAQ,WAAA,EAAa,OAAO,CAAA;AAAA,EAEhD;AAEA,EAAA,OAAO;AAAA,IACH,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,SAAA;AAAA,IACA,MAAA,EAAQ,QAAQ,KAAA,CAAM,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,SAAS,CAAA,GAAI,SAAA,GAAY,QAAA;AAAA,IACnE,KAAA,EAAO,OAAA;AAAA,IACP,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,GACpC;AAEJ;AASA,eAAe,WAAA,CAAY,OAAqB,MAAA,EAAuC;AAEnF,EAAA,MAAM,WAAyB,EAAC;AAEhC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAEtB,IAAA,IAAI,IAAA,CAAK,SAAS,KAAA,EAAO;AAGrB,MAAA,IAAI,KAAK,aAAA,EAAe;AAEpB,QAAA,KAAA,MAAW,YAAA,IAAgB,KAAK,aAAA,EAAe;AAE3C,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACV,QAAA,EAAUN,KAAAA,CAAK,QAAA,CAAS,YAAY,CAAA;AAAA,YACpC,IAAA,EAAM,YAAA;AAAA,YACN,IAAA,EAAM;AAAA,WACT,CAAA;AAAA,QAEL;AAAA,MAEJ,CAAA,MACK;AAGD,QAAA,MAAM,QAAA,GAAW,MAAM,eAAA,CAAgB,IAAA,CAAK,MAAM,MAAM,CAAA;AAExD,QAAA,KAAA,MAAW,gBAAgB,QAAA,EAAU;AAEjC,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACV,QAAA,EAAUA,KAAAA,CAAK,QAAA,CAAS,YAAY,CAAA;AAAA,YACpC,IAAA,EAAM,YAAA;AAAA,YACN,IAAA,EAAM;AAAA,WACT,CAAA;AAAA,QAEL;AAAA,MAEJ;AAAA,IAEJ,CAAA,MACK;AAED,MAAA,QAAA,CAAS,KAAK,IAAI,CAAA;AAAA,IAEtB;AAAA,EAEJ;AAEA,EAAA,OAAO,QAAA;AAEX;AAKA,eAAe,oBAAA,CAAqB,OAAqB,MAAA,EAAmC;AAExF,EAAA,MAAM,YAAsB,EAAC;AAE7B,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAGtB,IAAA,MAAM,YAAA,GAAe,MAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA;AACpD,IAAA,SAAA,CAAU,KAAK,YAAY,CAAA;AAG3B,IAAA,IAAI,IAAA,CAAK,SAAS,KAAA,EAAO;AAErB,MAAA,MAAM,WAAW,IAAA,CAAK,aAAA,IAAkB,MAAM,eAAA,CAAgB,IAAA,CAAK,MAAM,MAAM,CAAA;AAE/E,MAAA,KAAA,MAAW,gBAAgB,QAAA,EAAU;AAEjC,QAAA,MAAM,WAAA,GAAc,MAAM,eAAA,CAAgB,YAAY,CAAA;AACtD,QAAA,SAAA,CAAU,KAAK,WAAW,CAAA;AAAA,MAE9B;AAAA,IAEJ;AAAA,EAEJ;AAEA,EAAA,OAAO,SAAA;AAEX;AAKA,SAAS,oBAAoB,QAAA,EAA0B;AAEnD,EAAA,OAAO,CAAA;AAAA,SAAA,EACA,QAAQ;AAAA;;AAAA,CAAA;AAKnB;AAMA,eAAe,yBAAyB,KAAA,EAAuC;AAE3E,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAGtB,IAAA,IAAI,IAAA,CAAK,SAAS,KAAA,EAAO;AAErB,MAAA,OAAO,IAAA;AAAA,IAEX;AAEA,IAAA,MAAM,CAAC,OAAA,EAAS,GAAG,CAAA,GAAI,MAAMF,OAAAA,CAAQ,MAAMI,QAAAA,CAAS,IAAA,CAAK,IAAA,EAAM,OAAO,CAAC,CAAA;AAEvE,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA;AAAA,IAEJ;AAEA,IAAA,MAAM,OAAA,GAAU,OAAA,EAAS,IAAA,EAAK,IAAK,EAAA;AAGnC,IAAA,IAAI,OAAA,IAAW,YAAY,YAAA,EAAc;AAErC,MAAA,OAAO,IAAA;AAAA,IAEX;AAAA,EAEJ;AAEA,EAAA,OAAO,KAAA;AAEX;AAKA,SAAS,kBAAA,CACL,IAAA,EACA,SAAA,EACA,KAAA,EACA,SAAA,EACY;AAEZ,EAAA,OAAO;AAAA,IACH,IAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA,EAAQ,QAAA;AAAA,IACR,OAAO,EAAC;AAAA,IACR,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AAAA,IAChC;AAAA,GACJ;AAEJ;AAOA,eAAe,aAAA,CACX,OAAA,EACA,MAAA,EACA,KAAA,EACA,WACA,SAAA,EACqB;AAErB,EAAA,MAAM,aAAA,GAAgB,MAAM,WAAA,CAAY,KAAA,EAAO,QAAQ,MAAM,CAAA;AAC7D,EAAA,MAAM,UAA8B,EAAC;AAErC,EAAA,KAAA,MAAW,QAAQ,aAAA,EAAe;AAE9B,IAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAGlC,IAAA,MAAM,CAAC,QAAQ,CAAA,GAAI,MAAMJ,QAAQ,MAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAC,CAAA;AAGjE,IAAA,MAAM,CAAC,UAAA,EAAY,OAAO,CAAA,GAAI,MAAMA,OAAAA,CAAQ,MAAM,iBAAA,CAAkB,OAAA,EAAS,IAAA,CAAK,IAAI,CAAC,CAAA;AAEvF,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACT,UAAU,IAAA,CAAK,IAAA;AAAA,QACf,UAAU,QAAA,IAAY,EAAA;AAAA,QACtB,MAAA,EAAQ,QAAA;AAAA,QACR,OAAO,OAAA,CAAQ,OAAA;AAAA,QACf,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,OACnC,CAAA;AAED,MAAA;AAAA,IAEJ;AAGA,IAAA,MAAM,GAAG,QAAQ,CAAA,GAAI,MAAMA,OAAAA;AAAA,MAAQ,MAC/B,iBAAA,CAAkB,OAAA,CAAQ,WAAA,EAAa,IAAA,CAAK,MAAM,UAAU;AAAA,KAChE;AAEA,IAAA,MAAM,UAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AAEvC,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,QAAA;AAAA,QACP,SAAS,EAAE,QAAA,EAAU,IAAA,CAAK,IAAA,EAAM,WAAW,eAAA;AAAgB,OAC9D,CAAA;AAAA,IAEL;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACT,UAAU,IAAA,CAAK,IAAA;AAAA,MACf,UAAU,QAAA,IAAY,EAAA;AAAA,MACtB,MAAA,EAAQ,SAAA;AAAA,MACR,UAAA;AAAA,MACA,WAAA,EAAa;AAAA,KAChB,CAAA;AAAA,EAEL;AAEA,EAAA,OAAO;AAAA,IACH,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,SAAA;AAAA,IACA,MAAA,EAAQ,QAAQ,KAAA,CAAM,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,SAAS,CAAA,GAAI,SAAA,GAAY,QAAA;AAAA,IACnE,KAAA,EAAO,OAAA;AAAA,IACP,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,GACpC;AAEJ;AAOA,SAAS,mBAAA,CAAoB,aAAqB,QAAA,EAA0B;AAExE,EAAA,MAAM,YAAA,GAAeE,KAAAA,CAAK,QAAA,CAAS,WAAA,EAAa,QAAQ,CAAA;AAExD,EAAA,MAAM,kBAAA,GAAqB,aAAa,QAAA,CAAS,OAAO,IAClD,YAAA,CAAa,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GACxB,YAAA;AAEN,EAAA,OAAOA,KAAAA,CAAK,IAAA,CAAK,WAAA,EAAa,KAAA,EAAO,kBAAkB,CAAA;AAE3D;AAKA,eAAe,iBAAA,CACX,WAAA,EACA,QAAA,EACA,OAAA,EACa;AAEb,EAAA,MAAM,UAAA,GAAa,mBAAA,CAAoB,WAAA,EAAa,QAAQ,CAAA;AAG5D,EAAA,MAAM,SAAA,GAAYA,KAAAA,CAAK,OAAA,CAAQ,UAAU,CAAA;AACzC,EAAA,MAAMI,KAAAA,CAAM,SAAA,EAAW,EAAE,SAAA,EAAW,MAAM,CAAA;AAG1C,EAAA,MAAMuB,SAAA,CAAY,UAAA,EAAY,OAAA,EAAS,OAAO,CAAA;AAElD;AAKA,eAAe,iBAAA,CAAkB,SAAwB,QAAA,EAAmC;AAExF,EAAA,IAAI,UAAA,CAAW,QAAQ,CAAA,EAAG;AAEtB,IAAA,MAAM,MAAA,GAAS,MAAM,WAAA,CAAY,QAAA,EAAU;AAAA,MACvC,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,MAAA,EAAQ,MAAA;AAAA;AAAA,MACR,OAAA,EAAS,MAAA;AAAA,MACT,aAAA,EAAe;AAAA,KAClB,CAAA;AAED,IAAA,OAAO,MAAA,CAAO,GAAA;AAAA,EAElB;AAEA,EAAA,MAAM,CAAC,OAAA,EAAS,GAAG,CAAA,GAAI,MAAM7B,QAAQ,MAAMI,QAAAA,CAAS,QAAA,EAAU,OAAO,CAAC,CAAA;AAEtE,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,MAAM,IAAI,MAAM,CAAA,qBAAA,EAAwB,QAAQ,IAAI,EAAE,KAAA,EAAO,KAAK,CAAA;AAAA,EAEtE;AAEA,EAAA,OAAO,OAAA;AAEX;AChgCA,IAAM,aAAA,GAA0F;AAAA,EAC5F,KAAA,EAAO,KAAA;AAAA,EACP,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,KAAA;AAAA,EACT,MAAA,EAAQ,IAAA;AAAA,EACR,YAAA,EAAc;AAClB,CAAA;AAwBO,IAAM,gBAAN,MAAoB;AAAA,EAEd,QAAA;AAAA,EACA,QAAA;AAAA,EAET,YAAY,OAAA,EAAwB;AAEhC,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,IAAA,IAAA,CAAK,WAAW,IAAI,aAAA,CAAc,OAAA,CAAQ,EAAA,EAAI,QAAQ,UAAU,CAAA;AAAA,EAEpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,IAAA,GAAkC;AAGpC,IAAA,MAAM,cAAc,MAAM,eAAA;AAAA,MACtB,KAAK,QAAA,CAAS,UAAA;AAAA,MACd,KAAK,QAAA,CAAS;AAAA,KAClB;AAGA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,QAAA,CAAS,cAAA,EAAe;AAGpD,IAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,WAAA,CAAY,IAAI,CAAC,EAAA,KAAO,EAAA,CAAG,IAAI,CAAC,CAAA;AAG1D,IAAA,MAAM,aAAA,GAAgB,MAAM,IAAA,CAAK,QAAA,CAAS,YAAY,SAAS,CAAA;AAG/D,IAAA,MAAM,SAA2B,EAAC;AAGlC,IAAA,KAAA,MAAW,MAAM,WAAA,EAAa;AAE1B,MAAA,MAAM,MAAA,GAAS,QAAA,CAAS,GAAA,CAAI,EAAA,CAAG,IAAI,CAAA;AAEnC,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACR,GAAG,EAAA;AAAA,QACH,MAAM,EAAA,CAAG,IAAA;AAAA,QACT,MAAA,EAAQ,QAAQ,MAAA,IAAU,SAAA;AAAA,QAC1B,SAAA,EAAW,QAAQ,SAAA,IAAa,IAAA;AAAA,QAChC,SAAA,EAAW,QAAQ,SAAA,IAAa,IAAA;AAAA,QAChC,UAAA,EAAY,QAAQ,UAAA,IAAc,IAAA;AAAA,QAClC,YAAA,EAAc,QAAQ,YAAA,IAAgB,IAAA;AAAA,QACtC,OAAO,CAAC,MAAA;AAAA,QACR,QAAA,EAAU;AAAA,OACb,CAAA;AAAA,IAEL;AAGA,IAAA,KAAA,MAAW,QAAQ,aAAA,EAAe;AAE9B,MAAA,MAAM,MAAA,GAAS,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA;AAEhC,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACR,IAAA;AAAA,QACA,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,cAAc,MAAA,CAAO,YAAA;AAAA,QACrB,KAAA,EAAO,KAAA;AAAA,QACP,QAAA,EAAU,IAAA;AAAA;AAAA,QAEV,IAAA,EAAM,MAAA;AAAA,QACN,IAAA,EAAM,MAAA;AAAA,QACN,WAAA,EAAa,MAAA;AAAA,QACb,WAAA,EAAa,MAAA;AAAA,QACb,WAAA,EAAa,MAAA;AAAA,QACb,YAAA,EAAc;AAAA,OACjB,CAAA;AAAA,IAEL;AAGA,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,EAE7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,GAAA,CAAI,IAAA,EAAc,OAAA,GAAyB,EAAC,EAA0B;AAExE,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA;AAE1C,IAAA,OAAO,aAAA,CAAc,IAAA,CAAK,QAAA,EAAU,MAAA,EAAQ,OAAO,CAAA;AAAA,EAEvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAA,CACF,MAAA,EACA,OAAA,GAAyB,EAAC,EACL;AAErB,IAAA,OAAO,aAAA,CAAc,IAAA,CAAK,QAAA,EAAU,MAAA,EAAQ,OAAO,CAAA;AAAA,EAEvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,MAAA,CAAO,IAAA,EAAc,OAAA,GAAyB,EAAC,EAA0B;AAE3E,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA;AAE1C,IAAA,OAAO,YAAA,CAAa,IAAA,CAAK,QAAA,EAAU,MAAA,EAAQ,OAAO,CAAA;AAAA,EAEtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAA,CACF,MAAA,EACA,OAAA,GAAyB,EAAC,EACL;AAErB,IAAA,OAAO,YAAA,CAAa,IAAA,CAAK,QAAA,EAAU,MAAA,EAAQ,OAAO,CAAA;AAAA,EAEtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,IAAA,CACF,KAAA,GAAgB,CAAA,EAChB,OAAA,GAA8B,EAAC,EACL;AAE1B,IAAA,MAAM,IAAA,GAAO,EAAE,GAAG,aAAA,EAAe,GAAG,OAAA,EAAQ;AAC5C,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAG9B,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,IAAA,MAAM,UAAU,IAAA,CACX,MAAA,CAAO,CAAC,EAAA,KAAO,CAAC,EAAA,CAAG,QAAA,KAAa,EAAA,CAAG,MAAA,KAAW,aAAa,EAAA,CAAG,MAAA,KAAW,WAAW,CAAA,CACpF,KAAA,CAAM,GAAG,KAAK,CAAA;AAEnB,IAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AAEtB,MAAA,OAAO;AAAA,QACH,MAAA,EAAQ,SAAA;AAAA,QACR,SAAS,EAAC;AAAA,QACV,QAAA,EAAU,CAAA;AAAA,QACV,OAAA,EAAS,CAAA;AAAA,QACT,MAAA,EAAQ,CAAA;AAAA,QACR,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,OACpC;AAAA,IAEJ;AAGA,IAAA,MAAM,UAA0B,EAAC;AACjC,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,IAAI,QAAA,GAAW,CAAA;AAEf,IAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAGxB,MAAA,MAAM,CAAC,MAAA,EAAQ,OAAO,CAAA,GAAI,MAAMJ,OAAAA,CAAQ,MAAM,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA;AAEzE,MAAA,IAAI,OAAA,EAAS;AAET,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACT,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,SAAA,EAAW,QAAA;AAAA,UACX,MAAA,EAAQ,QAAA;AAAA,UACR,OAAO,EAAC;AAAA,UACR,UAAA,EAAY,CAAA;AAAA,UACZ,OAAO,OAAA,CAAQ;AAAA,SAClB,CAAA;AAED,QAAA,MAAA,EAAA;AAEA,QAAA,IAAI,KAAK,YAAA,EAAc;AAEvB,QAAA;AAAA,MAEJ;AAEA,MAAA,MAAM,SAAS,MAAM,aAAA,CAAc,IAAA,CAAK,QAAA,EAAU,QAAQ,IAAI,CAAA;AAC9D,MAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AAEnB,MAAA,IAAI,MAAA,CAAO,WAAW,SAAA,EAAW;AAE7B,QAAA,QAAA,EAAA;AAAA,MAEJ,CAAA,MACK;AAED,QAAA,MAAA,EAAA;AAEA,QAAA,IAAI,KAAK,YAAA,EAAc;AAAA,MAE3B;AAAA,IAEJ;AAEA,IAAA,OAAO;AAAA,MACH,QAAQ,MAAA,GAAS,CAAA,GAAK,QAAA,GAAW,CAAA,GAAI,YAAY,QAAA,GAAY,SAAA;AAAA,MAC7D,OAAA,EAAS,OAAA;AAAA,MACT,QAAA;AAAA,MACA,OAAA,EAAS,OAAA,CAAQ,MAAA,GAAS,QAAA,GAAW,MAAA;AAAA,MACrC,MAAA;AAAA,MACA,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,KACpC;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,EAAA,CAAG,OAAA,GAA8B,EAAC,EAA+B;AAGnE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,IAAA,MAAM,eAAe,IAAA,CAAK,MAAA;AAAA,MACtB,CAAC,OAAO,CAAC,EAAA,CAAG,aAAa,EAAA,CAAG,MAAA,KAAW,SAAA,IAAa,EAAA,CAAG,MAAA,KAAW,UAAA;AAAA,KACtE,CAAE,MAAA;AAEF,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,OAAO,CAAA;AAAA,EAE1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,CACF,MAAA,EACA,OAAA,GAA8B,EAAC,EACL;AAE1B,IAAA,MAAM,IAAA,GAAO,EAAE,GAAG,aAAA,EAAe,GAAG,OAAA,EAAQ;AAC5C,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAG9B,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,IAAA,MAAM,UAAU,IAAA,CACX,MAAA,CAAO,CAAC,EAAA,KAAO,CAAC,EAAA,CAAG,QAAA,IAAY,EAAA,CAAG,MAAA,KAAW,aAAa,EAAA,CAAG,SAAS,EACtE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM;AAEZ,MAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,SAAA,EAAW,OAAA,EAAQ,IAAK,CAAA;AACxC,MAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,SAAA,EAAW,OAAA,EAAQ,IAAK,CAAA;AAExC,MAAA,OAAO,KAAA,GAAQ,KAAA;AAAA,IAEnB,CAAC,CAAA;AAGL,IAAA,IAAI,QAAA;AAEJ,IAAA,IAAI,OAAO,WAAW,QAAA,EAAU;AAE5B,MAAA,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA;AAAA,IAEtC,CAAA,MACK;AAGD,MAAA,MAAM,cAAc,OAAA,CAAQ,SAAA,CAAU,CAAC,EAAA,KAAO,EAAA,CAAG,SAAS,MAAM,CAAA;AAEhE,MAAA,IAAI,gBAAgB,EAAA,EAAI;AAEpB,QAAA,OAAO;AAAA,UACH,MAAA,EAAQ,QAAA;AAAA,UACR,SAAS,EAAC;AAAA,UACV,QAAA,EAAU,CAAA;AAAA,UACV,OAAA,EAAS,CAAA;AAAA,UACT,MAAA,EAAQ,CAAA;AAAA,UACR,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,SACpC;AAAA,MAEJ;AAEA,MAAA,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,WAAA,GAAc,CAAC,CAAA;AAAA,IAE/C;AAEA,IAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAEvB,MAAA,OAAO;AAAA,QACH,MAAA,EAAQ,SAAA;AAAA,QACR,SAAS,EAAC;AAAA,QACV,QAAA,EAAU,CAAA;AAAA,QACV,OAAA,EAAS,CAAA;AAAA,QACT,MAAA,EAAQ,CAAA;AAAA,QACR,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,OACpC;AAAA,IAEJ;AAGA,IAAA,MAAM,UAA0B,EAAC;AACjC,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,IAAI,OAAA,GAAU,CAAA;AAEd,IAAA,KAAA,MAAW,QAAQ,QAAA,EAAU;AAGzB,MAAA,IAAI,IAAA,CAAK,WAAW,UAAA,EAAY;AAE5B,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACT,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,SAAA,EAAW,QAAA;AAAA,UACX,MAAA,EAAQ,SAAA;AAAA,UACR,OAAO,EAAC;AAAA,UACR,UAAA,EAAY;AAAA,SACf,CAAA;AAED,QAAA,OAAA,EAAA;AACA,QAAA;AAAA,MAEJ;AAGA,MAAA,MAAM,CAAC,MAAA,EAAQ,OAAO,CAAA,GAAI,MAAMA,OAAAA,CAAQ,MAAM,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA;AAEzE,MAAA,IAAI,OAAA,EAAS;AAET,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACT,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,SAAA,EAAW,QAAA;AAAA,UACX,MAAA,EAAQ,QAAA;AAAA,UACR,OAAO,EAAC;AAAA,UACR,UAAA,EAAY,CAAA;AAAA,UACZ,OAAO,OAAA,CAAQ;AAAA,SAClB,CAAA;AAED,QAAA,MAAA,EAAA;AAEA,QAAA,IAAI,KAAK,YAAA,EAAc;AAEvB,QAAA;AAAA,MAEJ;AAEA,MAAA,MAAM,SAAS,MAAM,YAAA,CAAa,IAAA,CAAK,QAAA,EAAU,QAAQ,IAAI,CAAA;AAC7D,MAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AAEnB,MAAA,IAAI,MAAA,CAAO,WAAW,SAAA,EAAW;AAE7B,QAAA,QAAA,EAAA;AAAA,MAEJ,CAAA,MACK;AAED,QAAA,MAAA,EAAA;AAEA,QAAA,IAAI,KAAK,YAAA,EAAc;AAAA,MAE3B;AAAA,IAEJ;AAEA,IAAA,OAAO;AAAA,MACH,QAAQ,MAAA,GAAS,CAAA,GAAK,QAAA,GAAW,CAAA,GAAI,YAAY,QAAA,GAAY,SAAA;AAAA,MAC7D,OAAA,EAAS,OAAA;AAAA,MACT,QAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,KACpC;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,UAAA,CAAW,IAAA,EAAe,KAAA,EAAgD;AAE5E,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,IAAA,EAAM,KAAK,CAAA;AAAA,EAE/C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAAA,EAAmD;AAEpE,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,cAAA,CAAe,WAAW,CAAA;AAAA,EAEnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,MAAA,CAAO,IAAA,EAAc,OAAA,EAA0D;AAEjF,IAAA,IAAI,QAAQ,IAAA,EAAM;AAEd,MAAA,MAAM,aAAaE,KAAAA,CAAK,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,YAAY,IAAI,CAAA;AAE3D,MAAA,MAAM,CAAC,MAAA,EAAQ,OAAO,CAAA,GAAI,MAAMF,OAAAA;AAAA,QAAQ,MACpC,WAAA,CAAY,UAAA,EAAY,IAAA,CAAK,SAAS,MAAM;AAAA,OAChD;AAEA,MAAA,IAAI,CAAC,WAAW,MAAA,EAAQ;AAEpB,QAAA,MAAM,aAAe,MAAM,CAAA;AAAA,MAE/B;AAAA,IAEJ;AAEA,IAAA,IAAI,QAAQ,EAAA,EAAI;AAEZ,MAAA,MAAM,IAAA,CAAK,QAAA,CAAS,aAAA,CAAc,IAAI,CAAA;AAAA,IAE1C;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAI,IAAA,EAA8C;AAEpD,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAE7B,IAAA,OAAO,KAAK,IAAA,CAAK,CAAC,OAAO,EAAA,CAAG,IAAA,KAAS,IAAI,CAAA,IAAK,IAAA;AAAA,EAElD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,IAAA,EAA+B;AAEtC,IAAA,OAAO,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,EAEhC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YAAY,IAAA,EAA+B;AAE7C,IAAA,MAAM,aAAaE,KAAAA,CAAK,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,YAAY,IAAI,CAAA;AAE3D,IAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAMF,OAAAA;AAAA,MAAQ,MAChC,WAAA,CAAY,UAAA,EAAY,IAAA,CAAK,SAAS,MAAM;AAAA,KAChD;AAEA,IAAA,IAAI,GAAA,EAAK;AAGL,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,QAAA,CAAS,UAAU,IAAI,CAAA;AAEjD,MAAA,IAAI,MAAA,EAAQ;AAER,QAAA,MAAM,IAAI,oBAAoB,IAAI,CAAA;AAAA,MAEtC;AAEA,MAAA,MAAM,IAAI,oBAAoB,IAAI,CAAA;AAAA,IAEtC;AAEA,IAAA,OAAO,MAAA;AAAA,EAEX;AAEJ,CAAA;;;ACzkBA,IAAM,oBAAoB,IAAI,GAAA,CAAY,MAAA,CAAO,MAAA,CAAO,YAAY,CAAC,CAAA;AAM9D,SAAS8B,cAAa,IAAA,EAA0C;AAEnE,EAAA,IAAI,CAAC,MAAM,OAAO,KAAA;AAElB,EAAA,OAAO,KAAK,UAAA,CAAW,UAAU,CAAA,IAAK,iBAAA,CAAkB,IAAI,IAAI,CAAA;AAEpE;AA4BA,eAAsB,YAAA,CAClB,EAAA,EACA,OAAA,EACA,OAAA,GAA2B,EAAC,EACL;AAEvB,EAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAClC,EAAA,MAAM,GAAA,GAAM,sBAAsB,OAAO,CAAA;AACzC,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,MAAM,YAAsB,EAAC;AAC7B,EAAA,MAAM,YAAsB,EAAC;AAE7B,EAAA,QAAA,CAAS,IAAA,CAAK,gBAAA,EAAkB,EAAE,IAAA,EAAM,YAAY,CAAA;AAGpD,EAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,CAAA,GAAI,MAAM9B,OAAAA,CAAQ,MAAM,SAAA,CAAU,EAAA,EAAI,SAAS,QAAA,EAAU,EAAE,kBAAA,EAAoB,IAAA,EAAM,CAAC,CAAA;AAExG,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,QAAA,CAAS,KAAK,gBAAA,EAAkB,EAAE,OAAO,GAAA,EAAK,MAAA,EAAQ,MAAM,CAAA;AAC5D,IAAA,MAAM,GAAA;AAAA,EAEV;AAGA,EAAA,MAAM,cAAc,IAAI,GAAA,CAAI,OAAA,CAAQ,QAAA,IAAY,EAAE,CAAA;AAElD,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAExB,IAAA,MAAM,YAAY,KAAA,CAAM,IAAA;AAGxB,IAAA,IAAI8B,aAAAA,CAAa,SAAS,CAAA,EAAG;AAEzB,MAAA,SAAA,CAAU,KAAK,SAAS,CAAA;AACxB,MAAA;AAAA,IAEJ;AAGA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA,EAAG;AAE5B,MAAA,SAAA,CAAU,KAAK,SAAS,CAAA;AACxB,MAAA;AAAA,IAEJ;AAGA,IAAA,IAAI,QAAQ,IAAA,IAAQ,CAAC,QAAQ,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,EAAG;AAEnD,MAAA,SAAA,CAAU,KAAK,SAAS,CAAA;AACxB,MAAA;AAAA,IAEJ;AAEA,IAAA,SAAA,CAAU,KAAK,SAAS,CAAA;AAAA,EAE5B;AAGA,EAAA,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,uBAAA,EAAyB,CAAA;AAE7C,EAAA,KAAA,MAAW,aAAa,SAAA,EAAW;AAE/B,IAAA,UAAA,CAAW,IAAA,CAAK,IAAI,aAAA,CAAc,SAAA,EAAW,QAAW,OAAA,CAAQ,eAAA,IAAmB,IAAI,CAAC,CAAA;AAAA,EAE5F;AAEA,EAAA,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,sBAAA,EAAwB,CAAA;AAG5C,EAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AAEjB,IAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAG3B,MAAA,IAAI,IAAA,CAAK,UAAA,CAAW,IAAI,CAAA,EAAG;AAG3B,MAAA,MAAM,aAAA,GAAgB,KAAK,QAAA,CAAS,IAAI,IAClC,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,IAAA,EAAM,EAAE,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,MAAA,GAAS,CAAC,CAAA,GAC5D,CAAC,IAAI,CAAA;AAEX,MAAA,KAAA,MAAW,WAAW,aAAA,EAAe;AAEjC,QAAA,QAAA,CAAS,KAAK,mBAAA,EAAqB;AAAA,UAC/B,QAAA,EAAU,QAAA;AAAA,UACV,MAAA,EAAQ,QAAQ,QAAA,CAAS,QAAQ,KAAK,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA,GAAI,OAAA,GAAU,IAAA;AAAA,UAC/E,MAAA,EAAQ;AAAA,SACX,CAAA;AAED,QAAA,MAAM,GAAG,OAAO,CAAA,GAAI,MAAM9B,OAAAA,CAAQ,MAAMkB,GAAAA,CAAI,GAAA,CAAI,OAAO,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAC,CAAA;AAEpE,QAAA,IAAI,OAAA,EAAS;AAET,UAAA,QAAA,CAAS,KAAK,gBAAA,EAAkB,EAAE,OAAO,OAAA,EAAS,MAAA,EAAQ,SAAS,CAAA;AACnE,UAAA,MAAM,OAAA;AAAA,QAEV;AAAA,MAEJ;AAAA,IAEJ;AAAA,EAEJ;AAEA,EAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,SAAS,CAAA;AAE3D,EAAA,MAAM,MAAA,GAAyB;AAAA,IAC3B,SAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACJ;AAEA,EAAA,QAAA,CAAS,IAAA,CAAK,mBAAA,EAAqB,EAAE,MAAA,EAAQ,CAAA;AAE7C,EAAA,OAAO,MAAA;AAEX;AA0BA,eAAsB,cAAA,CAClB,EAAA,EACA,OAAA,EACA,OAAA,GAA2B,EAAC,EACL;AAEvB,EAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAClC,EAAA,MAAM,GAAA,GAAM,sBAAsB,OAAO,CAAA;AACzC,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,MAAM,YAAsB,EAAC;AAC7B,EAAA,MAAM,OAAA,GAAqC;AAAA,IACvC,QAAQ,EAAC;AAAA,IACT,OAAO,EAAC;AAAA,IACR,WAAW,EAAC;AAAA,IACZ,YAAY,EAAC;AAAA,IACb,OAAO,EAAC;AAAA,IACR,aAAa;AAAC,GAClB;AAEA,EAAA,QAAA,CAAS,IAAA,CAAK,gBAAA,EAAkB,EAAE,IAAA,EAAM,UAAU,CAAA;AAElD,EAAA,MAAM,cAAc,IAAI,GAAA,CAAI,OAAA,CAAQ,cAAA,IAAkB,EAAE,CAAA;AAGxD,EAAA,MAAM;AAAA,IACF,CAAC,QAAQ,SAAS,CAAA;AAAA,IAClB,CAAC,OAAO,QAAQ,CAAA;AAAA,IAChB,CAAC,WAAW,YAAY,CAAA;AAAA,IACxB,CAAC,YAAY,aAAa,CAAA;AAAA,IAC1B,CAAC,OAAO,QAAQ,CAAA;AAAA,IAChB,CAAC,aAAa,MAAM;AAAA,GACxB,GAAI,MAAM,OAAA,CAAQ,GAAA,CAAI;AAAA,IAClBlB,OAAAA,CAAQ,MAAM,SAAA,CAAU,EAAA,EAAI,OAAA,EAAS,UAAU,EAAE,kBAAA,EAAoB,IAAA,EAAM,CAAC,CAAA;AAAA,IAC5EA,QAAQ,MAAM,SAAA,CAAU,EAAA,EAAI,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,IAC7CA,QAAQ,MAAM,SAAA,CAAU,EAAA,EAAI,OAAA,EAAS,WAAW,CAAC,CAAA;AAAA,IACjDA,QAAQ,MAAM,SAAA,CAAU,EAAA,EAAI,OAAA,EAAS,YAAY,CAAC,CAAA;AAAA,IAClDA,QAAQ,MAAM,SAAA,CAAU,EAAA,EAAI,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,IAC7CA,QAAQ,MAAM,SAAA,CAAU,EAAA,EAAI,OAAA,EAAS,aAAa,CAAC;AAAA,GACtD,CAAA;AAED,EAAA,IAAI,WAAW,MAAM,SAAA;AACrB,EAAA,IAAI,UAAU,MAAM,QAAA;AACpB,EAAA,IAAI,cAAc,MAAM,YAAA;AACxB,EAAA,IAAI,eAAe,MAAM,aAAA;AACzB,EAAA,IAAI,UAAU,MAAM,QAAA;AACpB,EAAA,IAAI,QAAQ,MAAM,MAAA;AAGlB,EAAA,KAAA,MAAW,MAAM,WAAA,EAAa;AAE1B,IAAA,MAAM,YAAY,EAAA,CAAG,SAAA;AAGrB,IAAA,IAAI8B,aAAAA,CAAa,SAAS,CAAA,EAAG;AAG7B,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA,EAAG;AAEhC,IAAA,OAAA,CAAQ,WAAA,CAAY,IAAA,CAAK,EAAA,CAAG,IAAI,CAAA;AAChC,IAAA,UAAA,CAAW,IAAA,CAAK,IAAI,cAAA,CAAe,EAAA,CAAG,MAAM,SAAA,EAAW,EAAA,CAAG,MAAM,CAAC,CAAA;AAAA,EAErE;AAGA,EAAA,IAAI,CAAC,QAAQ,SAAA,EAAW;AAEpB,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAEtB,MAAA,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AAC5B,MAAA,UAAA,CAAW,KAAK,GAAA,CAAI,QAAA,CAAS,KAAK,IAAA,EAAM,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,IAExD;AAAA,EAEJ;AAGA,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAExB,IAAA,MAAM,YAAY,KAAA,CAAM,IAAA;AAGxB,IAAA,IAAIA,aAAAA,CAAa,SAAS,CAAA,EAAG;AAEzB,MAAA,SAAA,CAAU,KAAK,SAAS,CAAA;AACxB,MAAA;AAAA,IAEJ;AAGA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA,EAAG;AAE5B,MAAA,SAAA,CAAU,KAAK,SAAS,CAAA;AACxB,MAAA;AAAA,IAEJ;AAEA,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAK,SAAS,CAAA;AAC7B,IAAA,UAAA,CAAW,KAAK,GAAA,CAAI,SAAA,CAAU,SAAA,EAAW,KAAA,CAAM,MAAM,CAAC,CAAA;AAAA,EAE1D;AAGA,EAAA,IAAI,CAAC,QAAQ,aAAA,EAAe;AAExB,IAAA,KAAA,MAAW,MAAM,SAAA,EAAW;AAExB,MAAA,OAAA,CAAQ,SAAA,CAAU,IAAA,CAAK,EAAA,CAAG,IAAI,CAAA;AAC9B,MAAA,UAAA,CAAW,KAAK,GAAA,CAAI,YAAA,CAAa,GAAG,IAAA,EAAM,EAAA,CAAG,MAAM,CAAC,CAAA;AAAA,IAExD;AAAA,EAEJ;AAGA,EAAA,IAAI,CAAC,QAAQ,cAAA,EAAgB;AAEzB,IAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAE3B,MAAA,OAAA,CAAQ,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AACjC,MAAA,UAAA,CAAW,KAAK,GAAA,CAAI,aAAA,CAAc,KAAK,IAAA,EAAM,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,IAE7D;AAAA,EAEJ;AAGA,EAAA,IAAI,CAAC,QAAQ,SAAA,EAAW;AAEpB,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAEtB,MAAA,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AAC5B,MAAA,UAAA,CAAW,KAAK,GAAA,CAAI,QAAA,CAAS,KAAK,IAAA,EAAM,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,IAExD;AAAA,EAEJ;AAGA,EAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AAEjB,IAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAG3B,MAAA,IAAI,IAAA,CAAK,UAAA,CAAW,IAAI,CAAA,EAAG;AAE3B,MAAA,QAAA,CAAS,KAAK,mBAAA,EAAqB;AAAA,QAC/B,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ,IAAA;AAAA,QACR,MAAA,EAAQ;AAAA,OACX,CAAA;AAED,MAAA,MAAM,GAAG,OAAO,CAAA,GAAI,MAAM9B,OAAAA,CAAQ,MAAMkB,GAAAA,CAAI,GAAA,CAAI,IAAI,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAC,CAAA;AAEjE,MAAA,IAAI,OAAA,EAAS;AAET,QAAA,QAAA,CAAS,KAAK,gBAAA,EAAkB,EAAE,OAAO,OAAA,EAAS,MAAA,EAAQ,MAAM,CAAA;AAChE,QAAA,MAAM,OAAA;AAAA,MAEV;AAAA,IAEJ;AAAA,EAEJ;AAEA,EAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,SAAS,CAAA;AAE3D,EAAA,MAAM,MAAA,GAAyB;AAAA,IAC3B,OAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACJ;AAGA,EAAA,IAAI,OAAA,CAAQ,UAAA,IAAc,CAAC,OAAA,CAAQ,MAAA,EAAQ;AAEvC,IAAA,MAAM,gBAAA,GAAmB,MAAM,iBAAA,CAAkB,EAAA,EAAI,QAAQ,UAAU,CAAA;AACvE,IAAA,MAAA,CAAO,gBAAA,GAAmB,gBAAA;AAAA,EAE9B;AAGA,EAAA,IAAI,QAAQ,UAAA,IAAc,OAAA,CAAQ,UAAA,IAAc,CAAC,QAAQ,MAAA,EAAQ;AAE7D,IAAA,MAAM,UAAU,IAAI,aAAA;AAAA,MAChB,EAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACZ;AAEA,IAAA,MAAM,UAAU,IAAI,aAAA;AAAA,MAChB,EAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACZ;AAGA,IAAA,MAAA,CAAO,UAAA,GAAa,MAAM,OAAA,CAAQ,cAAA,EAAe;AAGjD,IAAA,MAAM,KAAA,GAAQ;AAAA,MACV,CAAA,EAAG,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,OAAA,CAAA;AAAA,MACxB,CAAA,EAAG,OAAA,CAAQ,KAAA,CAAM,MAAM,CAAA,MAAA,CAAA;AAAA,MACvB,CAAA,EAAG,OAAA,CAAQ,SAAA,CAAU,MAAM,CAAA,UAAA,CAAA;AAAA,MAC3B,CAAA,EAAG,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA,WAAA;AAAA,KAChC;AACA,IAAA,MAAA,CAAO,aAAA,GAAgB,MAAM,OAAA,CAAQ,WAAA;AAAA,MACjC,OAAA,CAAQ,UAAA;AAAA,MACR,CAAA,yBAAA,EAA4B,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,KAChD;AAAA,EAEJ;AAEA,EAAA,QAAA,CAAS,IAAA,CAAK,mBAAA,EAAqB,EAAE,MAAA,EAAQ,CAAA;AAE7C,EAAA,OAAO,MAAA;AAEX;AA8BA,eAAe,iBAAA,CACX,IACA,UAAA,EAC8C;AAE9C,EAAA,MAAM,QAAA,GAAWnB,IAAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,UAAU,CAAA;AAE/C,EAAA,MAAM,CAAC,OAAA,EAAS,OAAO,CAAA,GAAI,MAAMC,QAAQ,MAAMI,QAAAA,CAAS,QAAA,EAAU,OAAO,CAAC,CAAA;AAE1E,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,OAAO,CAAA,uBAAA,EAA0B,OAAA,CAAQ,OAAO,CAAA,CAAA,EAAG;AAAA,EAEjF;AAGA,EAAA,MAAM,KAAA,GAAQ,QACT,KAAA,CAAM,GAAG,EACT,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,IAAA,EAAM,EACjB,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,MAAA,GAAS,CAAA,IAAK,CAAC,CAAA,CAAE,UAAA,CAAW,IAAI,CAAC,CAAA;AAEpD,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAEtB,IAAA,MAAM,GAAG,OAAO,CAAA,GAAI,MAAMJ,OAAAA,CAAQ,MAAMkB,GAAAA,CAAI,GAAA,CAAI,IAAI,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAC,CAAA;AAEjE,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,OAAO,CAAA,eAAA,EAAkB,OAAA,CAAQ,OAAO,CAAA,CAAA,EAAG;AAAA,IAEzE;AAAA,EAEJ;AAEA,EAAA,OAAO,EAAE,UAAU,IAAA,EAAK;AAE5B;AC1bA,IAAMa,eAAAA,GAAiB,CAAC,MAAA,EAAQ,WAAW,CAAA;AAE3C,IAAM,oBAAA,GAAuB,CAAA;AAAA;AAAA;;AAAA,CAAA;AA6B7B,eAAsB,QAAA,CAClB,OAAA,EACA,OAAA,EACA,OAAA,GAAsB,EAAC,EACH;AAEpB,EAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,4BAAA,EAA8B,GAAG,OAAA,EAAQ;AAG3D,EAAA,MAAM,CAAC,OAAO,WAAW,CAAA,GAAI,MAAM/B,OAAAA,CAAQ,MAAM,aAAA,CAAc,OAAO,CAAC,CAAA;AAEvE,EAAA,IAAI,WAAA,EAAa;AAEb,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,WAAA;AAAA,MACP,OAAA,EAAS,EAAE,OAAA,EAAS,SAAA,EAAW,gBAAA;AAAiB,KACnD,CAAA;AAED,IAAA,OAAO,wBAAwB,WAAA,CAAY,OAAA,EAAS,WAAA,CAAY,GAAA,KAAQ,KAAK,CAAA;AAAA,EAEjF;AAEA,EAAA,QAAA,CAAS,KAAK,aAAA,EAAe;AAAA,IACzB,OAAA;AAAA,IACA,WAAW,KAAA,CAAM;AAAA,GACpB,CAAA;AAGD,EAAA,MAAM,SAAS,MAAM,oBAAA,CAAqB,OAAA,EAAS,KAAA,EAAO,MAAM,OAAO,CAAA;AAEvE,EAAA,QAAA,CAAS,KAAK,gBAAA,EAAkB;AAAA,IAC5B,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,cAAc,MAAA,CAAO,YAAA;AAAA,IACrB,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,YAAY,MAAA,CAAO;AAAA,GACtB,CAAA;AAED,EAAA,OAAO,MAAA;AAEX;AAuBA,eAAsB,OAAA,CAClB,OAAA,EACA,QAAA,EACA,OAAA,GAAsB,EAAC,EACJ;AAEnB,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,4BAAA,EAA8B,GAAG,OAAA,EAAQ;AAE3D,EAAA,QAAA,CAAS,KAAK,UAAA,EAAY;AAAA,IACtB,QAAA;AAAA,IACA,YAAY,OAAA,CAAQ;AAAA,GACvB,CAAA;AAGD,EAAA,MAAM,UAAU,IAAI,OAAA,CAAQ,OAAA,CAAQ,EAAA,EAAI,QAAQ,UAAU,CAAA;AAC1D,EAAA,MAAM,gBAAgB,CAAA,IAAA,EAAA,iBAAO,IAAI,IAAA,EAAK,EAAE,aAAa,CAAA,CAAA;AAErD,EAAA,MAAM,CAAC,WAAA,EAAa,SAAS,CAAA,GAAI,MAAMA,OAAAA;AAAA,IAAQ,MAC3C,QAAQ,eAAA,CAAgB;AAAA,MACpB,IAAA,EAAM,aAAA;AAAA,MACN,UAAA,EAAY,KAAA;AAAA,MACZ,YAAY,OAAA,CAAQ,UAAA;AAAA,MACpB,UAAA,EAAY,cAAA,CAAe,OAAA,CAAQ,QAAQ;AAAA,KAC9C;AAAA,GACL;AAEA,EAAA,IAAI,SAAA,EAAW;AAEX,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,SAAA;AAAA,MACP,OAAA,EAAS,EAAE,QAAA,EAAU,SAAA,EAAW,kBAAA;AAAmB,KACtD,CAAA;AAED,IAAA,OAAO;AAAA,MACH,QAAA;AAAA,MACA,QAAA,EAAU,EAAA;AAAA,MACV,MAAA,EAAQ,QAAA;AAAA,MACR,OAAO,SAAA,CAAU;AAAA,KACrB;AAAA,EAEJ;AAEA,EAAA,MAAM,SAAS,MAAM,iBAAA,CAAkB,SAAS,QAAA,EAAU,IAAA,EAAM,SAAS,WAAY,CAAA;AAGrF,EAAA,MAAM,OAAA,CAAQ,iBAAA;AAAA,IACV,WAAA;AAAA,IACA,MAAA,CAAO,MAAA,KAAW,QAAA,GAAW,QAAA,GAAW,SAAA;AAAA,IACxC,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,UAAA,IAAc,CAAC,CAAA;AAAA,IACjC,MAAA,CAAO,QAAA;AAAA,IACP,MAAA,CAAO;AAAA,GACX;AAEA,EAAA,OAAO,MAAA;AAEX;AAqBA,eAAsB,MAAA,CAClB,OAAA,EACA,OAAA,EACA,OAAA,GAAsB,EAAC,EACH;AAEpB,EAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,4BAAA,EAA8B,GAAG,OAAA,EAAQ;AAG3D,EAAA,MAAM,CAAC,OAAO,WAAW,CAAA,GAAI,MAAMA,OAAAA,CAAQ,MAAM,aAAA,CAAc,OAAO,CAAC,CAAA;AAEvE,EAAA,IAAI,WAAA,EAAa;AAEb,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,WAAA;AAAA,MACP,OAAA,EAAS,EAAE,OAAA,EAAS,SAAA,EAAW,gBAAA;AAAiB,KACnD,CAAA;AAED,IAAA,OAAO,wBAAwB,WAAA,CAAY,OAAA,EAAS,WAAA,CAAY,GAAA,KAAQ,KAAK,CAAA;AAAA,EAEjF;AAEA,EAAA,QAAA,CAAS,KAAK,SAAA,EAAW;AAAA,IACrB,OAAA;AAAA,IACA,WAAW,KAAA,CAAM,MAAA;AAAA,IACjB,YAAY,OAAA,CAAQ;AAAA,GACvB,CAAA;AAGD,EAAA,OAAO,oBAAA,CAAqB,OAAA,EAAS,KAAA,EAAO,IAAA,EAAM,KAAK,CAAA;AAE3D;AAYA,eAAsB,QAAA,CAClB,OAAA,EACA,KAAA,EACA,OAAA,GAAsB,EAAC,EACH;AAEpB,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,4BAAA,EAA8B,GAAG,OAAA,EAAQ;AAE3D,EAAA,QAAA,CAAS,KAAK,WAAA,EAAa;AAAA,IACvB,WAAW,KAAA,CAAM,MAAA;AAAA,IACjB,YAAY,OAAA,CAAQ;AAAA,GACvB,CAAA;AAGD,EAAA,OAAO,oBAAA,CAAqB,OAAA,EAAS,KAAA,EAAO,IAAA,EAAM,KAAK,CAAA;AAE3D;AAgBA,eAAsB,OAAA,CAClB,OAAA,EACA,SAAA,EACA,MAAA,EACqB;AAErB,EAAA,MAAM,UAAwB,EAAC;AAC/B,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAE9B,IAAA,MAAM,CAAC,UAAA,EAAY,GAAG,CAAA,GAAI,MAAMA,QAAQ,MAAMgC,kBAAAA,CAAkB,OAAA,EAAS,QAAQ,CAAC,CAAA;AAElF,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACT,QAAA;AAAA,QACA,QAAA,EAAU,EAAA;AAAA,QACV,MAAA,EAAQ,QAAA;AAAA,QACR,OAAO,GAAA,CAAI;AAAA,OACd,CAAA;AACD,MAAA;AAAA,IAEJ;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,eAAA,CAAgB,QAAQ,CAAA;AAE/C,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACT,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,WAAA,EAAa;AAAA,KAChB,CAAA;AAED,IAAA,QAAA,CAAS,KAAK,oBAAA,CAAqB,OAAA,CAAQ,QAAA,EAAU,QAAQ,IAAI,UAAU,CAAA;AAAA,EAE/E;AAGA,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,IAAA,CAAK,MAAM,CAAA;AAExC,EAAA,IAAI,MAAA,EAAQ;AAER,IAAA,MAAM,GAAG,QAAQ,CAAA,GAAI,MAAMhC,OAAAA,CAAQ,MAAM6B,SAAAA,CAAY,MAAA,EAAQ,WAAA,EAAa,OAAO,CAAC,CAAA;AAElF,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,QAAA;AAAA,QACP,OAAA,EAAS,EAAE,MAAA,EAAQ,SAAA,EAAW,eAAA;AAAgB,OACjD,CAAA;AAAA,IAEL;AAAA,EAEJ;AAMA,EAAA,OAAO,OAAA;AAEX;AASA,IAAM,4BAAA,GAA+B;AAAA,EACjC,KAAA,EAAO,KAAA;AAAA,EACP,WAAA,EAAa,CAAA;AAAA,EACb,YAAA,EAAc,IAAA;AAAA,EACd,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,KAAA;AAAA,EACT,MAAA,EAAQ;AACZ,CAAA;AAeA,eAAsBI,aAAAA,CAClB,OAAA,EACA,KAAA,EACA,UAAA,EACA,WAAA,EACoB;AAEpB,EAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,EAAA,MAAM,IAAA,GAAO,EAAE,GAAG,4BAAA,EAA8B,GAAG,UAAA,EAAW;AAG9D,EAAA,MAAM,YAAY,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AAGzC,EAAA,IAAI,KAAK,OAAA,EAAS;AAEd,IAAA,MAAMC,WAAU,MAAM,OAAA,CAAQ,OAAA,EAAS,SAAA,EAAW,KAAK,MAAM,CAAA;AAC7D,IAAA,MAAMP,WAAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,KAAA;AAEvC,IAAA,OAAO;AAAA,MACH,MAAA,EAAQO,SAAQ,KAAA,CAAM,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,QAAQ,CAAA,GAAI,SAAA,GAAY,QAAA;AAAA,MAClE,KAAA,EAAOA,QAAAA;AAAA,MACP,QAAA,EAAU,CAAA;AAAA,MACV,YAAA,EAAc,CAAA;AAAA,MACd,WAAA,EAAaA,SAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,QAAQ,CAAA,CAAE,MAAA;AAAA,MAC1D,UAAA,EAAAP;AAAA,KACJ;AAAA,EAEJ;AAGA,EAAA,IAAI,KAAK,MAAA,EAAQ;AAEb,IAAA,MAAMO,QAAAA,GAAU,MAAMC,cAAAA,CAAc,OAAA,EAAS,SAAS,CAAA;AACtD,IAAA,MAAMR,WAAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,KAAA;AAEvC,IAAA,OAAO;AAAA,MACH,MAAA,EAAQO,SAAQ,KAAA,CAAM,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,QAAQ,CAAA,GAAI,SAAA,GAAY,QAAA;AAAA,MAClE,KAAA,EAAOA,QAAAA;AAAA,MACP,QAAA,EAAUA,SAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,SAAS,CAAA,CAAE,MAAA;AAAA,MACxD,YAAA,EAAc,CAAA;AAAA,MACd,WAAA,EAAaA,SAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,QAAQ,CAAA,CAAE,MAAA;AAAA,MAC1D,UAAA,EAAAP;AAAA,KACJ;AAAA,EAEJ;AAGA,EAAA,MAAM,OAAA,GAAW,YAAY,OAAA,IAAuB,IAAI,QAAQ,OAAA,CAAQ,EAAA,EAAI,QAAQ,UAAU,CAAA;AAG9F,EAAA,MAAM,CAAC,WAAA,EAAa,SAAS,CAAA,GAAI,MAAM3B,OAAAA;AAAA,IAAQ,MAC3C,QAAQ,eAAA,CAAgB;AAAA,MACpB,MAAM,WAAA,CAAY,aAAA;AAAA,MAClB,YAAY,WAAA,CAAY,UAAA;AAAA,MACxB,WAAW,WAAA,CAAY,SAAA;AAAA,MACvB,YAAY,OAAA,CAAQ,UAAA;AAAA,MACpB,UAAA,EAAY,cAAA,CAAe,OAAA,CAAQ,QAAQ;AAAA,KAC9C;AAAA,GACL;AAEA,EAAA,IAAI,SAAA,EAAW;AAEX,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,yBAAA;AAAA,MACR,KAAA,EAAO,SAAA;AAAA,MACP,OAAA,EAAS,EAAE,aAAA,EAAe,WAAA,CAAY,aAAA;AAAc,KACvD,CAAA;AAED,IAAA,OAAO,wBAAwB,SAAA,CAAU,OAAA,EAAS,WAAA,CAAY,GAAA,KAAQ,KAAK,CAAA;AAAA,EAE/E;AAGA,EAAA,MAAM,cAAsF,EAAC;AAE7F,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAEtB,IAAA,IAAI,WAAW,IAAA,CAAK,QAAA;AAEpB,IAAA,IAAI,CAAC,QAAA,EAAU;AAEX,MAAA,MAAM,CAAC,QAAA,EAAU,GAAG,CAAA,GAAI,MAAMA,QAAQ,MAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAC,CAAA;AACtE,MAAA,QAAA,GAAW,MAAM,EAAA,GAAK,QAAA;AAAA,IAE1B;AAEA,IAAA,WAAA,CAAY,IAAA,CAAK;AAAA,MACb,UAAU,IAAA,CAAK,IAAA;AAAA,MACf,UAAU,IAAA,CAAK,IAAA;AAAA,MACf;AAAA,KACH,CAAA;AAAA,EAEL;AAIA,EAAA,MAAM,gBAAA,GAAmB,MAAM,OAAA,CAAQ,iBAAA,CAAkB,aAAc,WAAW,CAAA;AAElF,EAAA,IAAI,gBAAA,EAAkB;AAElB,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,4BAAA;AAAA,MACR,KAAA,EAAO,IAAI,KAAA,CAAM,gBAAgB,CAAA;AAAA,MACjC,OAAA,EAAS,EAAE,WAAA;AAA0B,KACxC,CAAA;AAED,IAAA,MAAM,QAAQ,iBAAA,CAAkB,WAAA,EAAc,QAAA,EAAU,CAAA,EAAG,IAAI,gBAAgB,CAAA;AAE/E,IAAA,OAAO,uBAAA,CAAwB,gBAAA,EAAkB,WAAA,CAAY,GAAA,KAAQ,KAAK,CAAA;AAAA,EAE9E;AAGA,EAAA,MAAM,UAAwB,EAAC;AAC/B,EAAA,IAAI,MAAA,GAAS,KAAA;AAEb,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AAEnC,IAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AACpB,IAAA,MAAM,UAAA,GAAa,YAAY,CAAC,CAAA;AAEhC,IAAA,MAAM,SAAS,MAAM,2BAAA;AAAA,MACjB,OAAA;AAAA,MACA,IAAA,CAAK,IAAA;AAAA,MACL,UAAA,CAAW,QAAA;AAAA,MACX,IAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAA;AAAA,MACA,WAAA,CAAY;AAAA,KAChB;AAEA,IAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AAGnB,IAAA,IAAI,MAAA,CAAO,MAAA,KAAW,QAAA,IAAY,IAAA,CAAK,YAAA,EAAc;AAEjD,MAAA,MAAA,GAAS,IAAA;AAGT,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,kBAAA;AAAA,QAC1B,WAAA;AAAA,QACA,CAAA,0BAAA,EAA6B,KAAK,IAAI,CAAA;AAAA,OAC1C;AAEA,MAAA,IAAI,OAAA,EAAS;AAET,QAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,UACnB,MAAA,EAAQ,uBAAA;AAAA,UACR,KAAA,EAAO,IAAI,KAAA,CAAM,OAAO,CAAA;AAAA,UACxB,OAAA,EAAS,EAAE,WAAA;AAA0B,SACxC,CAAA;AAAA,MAEL;AAEA,MAAA;AAAA,IAEJ;AAAA,EAEJ;AAGA,EAAA,MAAM,QAAA,GAAW,QAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,SAAS,CAAA,CAAE,MAAA;AAC/D,EAAA,MAAM,YAAA,GAAe,QAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,SAAS,CAAA,CAAE,MAAA;AACnE,EAAA,MAAM,WAAA,GAAc,QAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,QAAQ,CAAA,CAAE,MAAA;AACjE,EAAA,MAAM,UAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,KAAA;AAGvC,EAAA,IAAI,MAAA,GAAsB,SAAA;AAE1B,EAAA,IAAI,WAAA,GAAc,KAAK,MAAA,EAAQ;AAE3B,IAAA,MAAA,GAAS,QAAA,GAAW,IAAI,SAAA,GAAY,QAAA;AAAA,EAExC;AAGA,EAAA,MAAM,gBAAA,GACF,WAAA,CAAY,QAAA,IAAY,uBAAA,CAAwB,WAAA,CAAY,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,CAAC,CAAA;AAItF,EAAA,MAAM,WAAA,GAAc,MAAA,KAAW,SAAA,GAAY,SAAA,GAAY,QAAA;AAEvD,EAAA,MAAM,WAAA,GAAc,MAAM,OAAA,CAAQ,iBAAA;AAAA,IAC9B,WAAA;AAAA,IACA,WAAA;AAAA,IACA,IAAA,CAAK,MAAM,UAAU,CAAA;AAAA,IACrB,gBAAA;AAAA,IACA,MAAA,GAAS,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,QAAQ,CAAA,EAAG,KAAA,GAAQ;AAAA,GACjE;AAEA,EAAA,IAAI,WAAA,EAAa;AAEb,IAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,MACnB,MAAA,EAAQ,iBAAA;AAAA,MACR,KAAA,EAAO,IAAI,KAAA,CAAM,WAAW,CAAA;AAAA,MAC5B,OAAA,EAAS,EAAE,WAAA;AAA0B,KACxC,CAAA;AAAA,EAEL;AAEA,EAAA,OAAO;AAAA,IACH,MAAA;AAAA,IACA,KAAA,EAAO,OAAA;AAAA,IACP,QAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA,EAAU;AAAA,GACd;AAEJ;AAOA,eAAe,oBAAA,CACX,OAAA,EACA,KAAA,EACA,OAAA,EACA,UAAA,EACoB;AAGpB,EAAA,MAAM,UAAA,GAA0B,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IAC9C,IAAA,EAAM,CAAA;AAAA,IACN,IAAA,EAAM;AAAA,GACV,CAAE,CAAA;AAGF,EAAA,MAAM,WAAA,GAAmC;AAAA,IACrC,UAAA;AAAA,IACA,SAAA,EAAW,QAAA;AAAA,IACX,aAAA,EAAe,GAAG,UAAU,CAAA,CAAA,EAAA,qBAAQ,IAAA,EAAK,EAAE,aAAa,CAAA;AAAA,GAC5D;AAEA,EAAA,OAAOiC,aAAAA,CAAa,OAAA,EAAS,UAAA,EAAY,OAAA,EAAS,WAAW,CAAA;AAEjE;AAgBA,eAAe,4BACX,OAAA,EACA,QAAA,EACA,UACA,OAAA,EACA,OAAA,EACA,aACA,UAAA,EACmB;AAEnB,EAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAG9B,EAAA,MAAM,CAAC,UAAA,EAAY,OAAO,CAAA,GAAI,MAAMjC,QAAQ,MAAMgC,kBAAAA,CAAkB,OAAA,EAAS,QAAQ,CAAC,CAAA;AAEtF,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,MAAML,WAAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,KAAA;AACvC,IAAA,MAAMS,OAAAA,GAAqB;AAAA,MACvB,QAAA;AAAA,MACA,UAAU,QAAA,IAAY,EAAA;AAAA,MACtB,MAAA,EAAQ,QAAA;AAAA,MACR,OAAO,OAAA,CAAQ,OAAA;AAAA,MACf,UAAA,EAAAT;AAAA,KACJ;AAEA,IAAA,MAAM,OAAA,CAAQ,mBAAA;AAAA,MACV,WAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA,CAAK,MAAMA,WAAU,CAAA;AAAA,MACrB,OAAA,CAAQ;AAAA,KACZ;AAEA,IAAA,QAAA,CAAS,KAAK,YAAA,EAAc;AAAA,MACxB,QAAA;AAAA,MACA,MAAA,EAAQ,QAAA;AAAA,MACR,UAAA,EAAAA,WAAAA;AAAA,MACA,OAAO,OAAA,CAAQ;AAAA,KAClB,CAAA;AAED,IAAA,OAAOS,OAAAA;AAAA,EAEX;AAGA,EAAA,MAAM,CAAC,kBAAkB,WAAW,CAAA,GAAInC,YAAY,MAAM,0BAAA,CAA2B,UAAU,CAAC,CAAA;AAChG,EAAA,MAAM,aAAA,GAAgB,cAAc,QAAA,GAAW,gBAAA;AAE/C,EAAA,QAAA,CAAS,KAAK,aAAA,EAAe;AAAA,IACzB,QAAA;AAAA,IACA,QAAA,EAAU,aAAA;AAAA,IACV,YAAY,OAAA,CAAQ;AAAA,GACvB,CAAA;AAID,EAAA,IAAI,eAAe,QAAA,EAAU;AAEzB,IAAA,MAAM,iBAAiB,MAAM,OAAA,CAAQ,SAAS,QAAA,EAAU,aAAA,EAAe,QAAQ,KAAK,CAAA;AAEpF,IAAA,IAAI,CAAC,eAAe,QAAA,EAAU;AAE1B,MAAA,MAAMmC,OAAAA,GAAqB;AAAA,QACvB,QAAA;AAAA,QACA,QAAA,EAAU,aAAA;AAAA,QACV,MAAA,EAAQ,SAAA;AAAA,QACR,YAAY,cAAA,CAAe;AAAA,OAC/B;AAEA,MAAA,MAAM,OAAA,CAAQ,mBAAA;AAAA,QACV,WAAA;AAAA,QACA,QAAA;AAAA,QACA,SAAA;AAAA,QACA,CAAA;AAAA,QACA,MAAA;AAAA,QACA,cAAA,CAAe;AAAA,OACnB;AAEA,MAAA,QAAA,CAAS,KAAK,WAAA,EAAa;AAAA,QACvB,QAAA;AAAA,QACA,QAAQ,cAAA,CAAe;AAAA,OAC1B,CAAA;AAED,MAAA,OAAOA,OAAAA;AAAA,IAEX;AAAA,EAEJ;AAGA,EAAA,MAAM,GAAG,OAAO,CAAA,GAAI,MAAMpC,OAAAA,CAAQ,MAAMkB,GAAAA,CAAI,GAAA,CAAI,UAAU,CAAA,CAAE,OAAA,CAAQ,OAAA,CAAQ,EAAE,CAAC,CAAA;AAE/E,EAAA,MAAM,UAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,KAAA;AAEvC,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,MAAMkB,OAAAA,GAAqB;AAAA,MACvB,QAAA;AAAA,MACA,QAAA,EAAU,aAAA;AAAA,MACV,MAAA,EAAQ,QAAA;AAAA,MACR,OAAO,OAAA,CAAQ,OAAA;AAAA,MACf;AAAA,KACJ;AAEA,IAAA,MAAM,OAAA,CAAQ,mBAAA;AAAA,MACV,WAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA,CAAK,MAAM,UAAU,CAAA;AAAA,MACrB,OAAA,CAAQ;AAAA,KACZ;AAEA,IAAA,QAAA,CAAS,KAAK,YAAA,EAAc;AAAA,MACxB,QAAA;AAAA,MACA,MAAA,EAAQ,QAAA;AAAA,MACR,UAAA;AAAA,MACA,OAAO,OAAA,CAAQ;AAAA,KAClB,CAAA;AAED,IAAA,OAAOA,OAAAA;AAAA,EAEX;AAGA,EAAA,MAAM,MAAA,GAAqB;AAAA,IACvB,QAAA;AAAA,IACA,QAAA,EAAU,aAAA;AAAA,IACV,MAAA,EAAQ,SAAA;AAAA,IACR;AAAA,GACJ;AAEA,EAAA,MAAM,OAAA,CAAQ,mBAAA;AAAA,IACV,WAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,IAAA,CAAK,MAAM,UAAU;AAAA,GACzB;AAEA,EAAA,QAAA,CAAS,KAAK,YAAA,EAAc;AAAA,IACxB,QAAA;AAAA,IACA,MAAA,EAAQ,SAAA;AAAA,IACR;AAAA,GACH,CAAA;AAED,EAAA,OAAO,MAAA;AAEX;AAOA,eAAe,iBAAA,CACX,OAAA,EACA,QAAA,EACA,OAAA,EACA,SACA,WAAA,EACmB;AAEnB,EAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAI9B,EAAA,MAAM,CAAC,UAAA,EAAY,OAAO,CAAA,GAAI,MAAMpC,QAAQ,MAAMgC,kBAAAA,CAAkB,OAAA,EAAS,QAAQ,CAAC,CAAA;AAEtF,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,MAAML,WAAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,KAAA;AACvC,IAAA,MAAMS,OAAAA,GAAqB;AAAA,MACvB,QAAA;AAAA,MACA,QAAA,EAAU,EAAA;AAAA,MACV,MAAA,EAAQ,QAAA;AAAA,MACR,OAAO,OAAA,CAAQ,OAAA;AAAA,MACf,UAAA,EAAAT;AAAA,KACJ;AAEA,IAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,MAC1B,QAAA,EAAU,WAAA;AAAA,MACV,QAAA;AAAA,MACA,QAAA,EAAU,EAAA;AAAA,MACV,MAAA,EAAQ,QAAA;AAAA,MACR,cAAc,OAAA,CAAQ,OAAA;AAAA,MACtB,UAAA,EAAY,IAAA,CAAK,KAAA,CAAMA,WAAU;AAAA,KACpC,CAAA;AAED,IAAA,QAAA,CAAS,KAAK,YAAA,EAAc;AAAA,MACxB,QAAA;AAAA,MACA,MAAA,EAAQ,QAAA;AAAA,MACR,UAAA,EAAAA,WAAAA;AAAA,MACA,OAAO,OAAA,CAAQ;AAAA,KAClB,CAAA;AAED,IAAA,OAAOS,OAAAA;AAAA,EAEX;AAGA,EAAA,MAAM,CAAC,UAAU,WAAW,CAAA,GAAInC,YAAY,MAAM,0BAAA,CAA2B,UAAU,CAAC,CAAA;AAExF,EAAA,IAAI,WAAA,EAAa;AAEb,IAAA,MAAMmC,OAAAA,GAAqB;AAAA,MACvB,QAAA;AAAA,MACA,QAAA,EAAU,EAAA;AAAA,MACV,MAAA,EAAQ,QAAA;AAAA,MACR,OAAO,WAAA,CAAY,OAAA;AAAA,MACnB,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,KACpC;AAEA,IAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,MAC1B,QAAA,EAAU,WAAA;AAAA,MACV,QAAA;AAAA,MACA,QAAA,EAAU,EAAA;AAAA,MACV,MAAA,EAAQ,QAAA;AAAA,MACR,cAAc,WAAA,CAAY,OAAA;AAAA,MAC1B,UAAA,EAAY,IAAA,CAAK,KAAA,CAAMA,OAAAA,CAAO,cAAc,CAAC;AAAA,KAChD,CAAA;AAED,IAAA,QAAA,CAAS,KAAK,YAAA,EAAc;AAAA,MACxB,QAAA;AAAA,MACA,MAAA,EAAQ,QAAA;AAAA,MACR,UAAA,EAAYA,QAAO,UAAA,IAAc,CAAA;AAAA,MACjC,OAAO,WAAA,CAAY;AAAA,KACtB,CAAA;AAED,IAAA,OAAOA,OAAAA;AAAA,EAEX;AAEA,EAAA,QAAA,CAAS,KAAK,aAAA,EAAe;AAAA,IACzB,QAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAY,OAAA,CAAQ;AAAA,GACvB,CAAA;AAGD,EAAA,MAAM,iBAAiB,MAAM,OAAA,CAAQ,SAAS,QAAA,EAAU,QAAA,EAAU,QAAQ,KAAK,CAAA;AAE/E,EAAA,IAAI,CAAC,eAAe,QAAA,EAAU;AAE1B,IAAA,MAAMA,OAAAA,GAAqB;AAAA,MACvB,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,YAAY,cAAA,CAAe;AAAA,KAC/B;AAEA,IAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,MAC1B,QAAA,EAAU,WAAA;AAAA,MACV,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,YAAY,cAAA,CAAe;AAAA,KAC9B,CAAA;AAED,IAAA,QAAA,CAAS,KAAK,WAAA,EAAa;AAAA,MACvB,QAAA;AAAA,MACA,QAAQ,cAAA,CAAe;AAAA,KAC1B,CAAA;AAED,IAAA,OAAOA,OAAAA;AAAA,EAEX;AAGA,EAAA,MAAM,GAAG,OAAO,CAAA,GAAI,MAAMpC,OAAAA,CAAQ,MAAMkB,GAAAA,CAAI,GAAA,CAAI,UAAU,CAAA,CAAE,OAAA,CAAQ,OAAA,CAAQ,EAAE,CAAC,CAAA;AAE/E,EAAA,MAAM,UAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,KAAA;AAEvC,EAAA,IAAI,OAAA,EAAS;AAET,IAAA,MAAMkB,OAAAA,GAAqB;AAAA,MACvB,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA,EAAQ,QAAA;AAAA,MACR,OAAO,OAAA,CAAQ,OAAA;AAAA,MACf;AAAA,KACJ;AAEA,IAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,MAC1B,QAAA,EAAU,WAAA;AAAA,MACV,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA,EAAQ,QAAA;AAAA,MACR,cAAc,OAAA,CAAQ,OAAA;AAAA,MACtB,UAAA,EAAY,IAAA,CAAK,KAAA,CAAM,UAAU;AAAA,KACpC,CAAA;AAED,IAAA,QAAA,CAAS,KAAK,YAAA,EAAc;AAAA,MACxB,QAAA;AAAA,MACA,MAAA,EAAQ,QAAA;AAAA,MACR,UAAA;AAAA,MACA,OAAO,OAAA,CAAQ;AAAA,KAClB,CAAA;AAED,IAAA,OAAOA,OAAAA;AAAA,EAEX;AAGA,EAAA,MAAM,MAAA,GAAqB;AAAA,IACvB,QAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA,EAAQ,SAAA;AAAA,IACR;AAAA,GACJ;AAEA,EAAA,MAAM,QAAQ,eAAA,CAAgB;AAAA,IAC1B,QAAA,EAAU,WAAA;AAAA,IACV,QAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA,EAAQ,SAAA;AAAA,IACR,UAAA,EAAY,IAAA,CAAK,KAAA,CAAM,UAAU;AAAA,GACpC,CAAA;AAED,EAAA,QAAA,CAAS,KAAK,YAAA,EAAc;AAAA,IACxB,QAAA;AAAA,IACA,MAAA,EAAQ,SAAA;AAAA,IACR;AAAA,GACH,CAAA;AAED,EAAA,OAAO,MAAA;AAEX;AAKA,eAAeJ,kBAAAA,CAAkB,SAAqB,QAAA,EAAmC;AAErF,EAAA,IAAI,UAAA,CAAW,QAAQ,CAAA,EAAG;AAEtB,IAAA,MAAM,MAAA,GAAS,MAAM,WAAA,CAAY,QAAA,EAAU;AAAA,MACvC,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,eAAe,OAAA,CAAQ;AAAA,KAC1B,CAAA;AAED,IAAA,OAAO,MAAA,CAAO,GAAA;AAAA,EAElB;AAEA,EAAA,MAAM,CAAC,OAAA,EAAS,GAAG,CAAA,GAAI,MAAMhC,QAAQ,MAAMI,QAAAA,CAAS,QAAA,EAAU,OAAO,CAAC,CAAA;AAEtE,EAAA,IAAI,GAAA,EAAK;AAEL,IAAA,MAAM,IAAI,MAAM,CAAA,qBAAA,EAAwB,QAAQ,IAAI,EAAE,KAAA,EAAO,KAAK,CAAA;AAAA,EAEtE;AAEA,EAAA,OAAO,OAAA;AAEX;AAOA,eAAe+B,cAAAA,CAAc,SAAqB,KAAA,EAAwC;AAEtF,EAAA,MAAM,UAAwB,EAAC;AAE/B,EAAA,KAAA,MAAW,YAAY,KAAA,EAAO;AAE1B,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAG9B,IAAA,MAAM,CAAC,UAAU,WAAW,CAAA,GAAI,MAAMnC,OAAAA,CAAQ,MAAM,eAAA,CAAgB,QAAQ,CAAC,CAAA;AAE7E,IAAA,IAAI,WAAA,EAAa;AAEb,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACT,QAAA;AAAA,QACA,QAAA,EAAU,EAAA;AAAA,QACV,MAAA,EAAQ,QAAA;AAAA,QACR,OAAO,WAAA,CAAY,OAAA;AAAA,QACnB,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,OACnC,CAAA;AACD,MAAA;AAAA,IAEJ;AAGA,IAAA,MAAM,CAAC,UAAA,EAAY,OAAO,CAAA,GAAI,MAAMA,QAAQ,MAAMgC,kBAAAA,CAAkB,OAAA,EAAS,QAAQ,CAAC,CAAA;AAEtF,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACT,QAAA;AAAA,QACA,QAAA;AAAA,QACA,MAAA,EAAQ,QAAA;AAAA,QACR,OAAO,OAAA,CAAQ,OAAA;AAAA,QACf,UAAA,EAAY,WAAA,CAAY,GAAA,EAAI,GAAI;AAAA,OACnC,CAAA;AACD,MAAA;AAAA,IAEJ;AAGA,IAAA,MAAM,GAAG,QAAQ,CAAA,GAAI,MAAMhC,OAAAA;AAAA,MAAQ,MAC/BqC,kBAAAA,CAAkB,OAAA,CAAQ,WAAA,EAAa,UAAU,UAAU;AAAA,KAC/D;AAEA,IAAA,MAAM,UAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,KAAA;AAEvC,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,QAAA,CAAS,KAAK,OAAA,EAAS;AAAA,QACnB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,QAAA;AAAA,QACP,OAAA,EAAS,EAAE,QAAA,EAAU,SAAA,EAAW,eAAA;AAAgB,OACnD,CAAA;AAAA,IAEL;AAEA,IAAA,MAAM,UAAA,GAAaC,oBAAAA,CAAoB,OAAA,CAAQ,WAAA,EAAa,QAAQ,CAAA;AAEpE,IAAA,QAAA,CAAS,KAAK,cAAA,EAAgB;AAAA,MAC1B,QAAA;AAAA,MACA;AAAA,KACH,CAAA;AAED,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACT,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,UAAA;AAAA,MACA,WAAA,EAAa;AAAA,KAChB,CAAA;AAAA,EAEL;AAEA,EAAA,OAAO,OAAA;AAEX;AAQA,SAASA,oBAAAA,CAAoB,aAAqB,QAAA,EAA0B;AAExE,EAAA,MAAM,YAAA,GAAepC,KAAAA,CAAK,QAAA,CAAS,WAAA,EAAa,QAAQ,CAAA;AAExD,EAAA,MAAM,kBAAA,GAAqB,aAAa,QAAA,CAAS,OAAO,IAClD,YAAA,CAAa,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GACxB,YAAA;AAEN,EAAA,OAAOA,KAAAA,CAAK,IAAA,CAAK,WAAA,EAAa,KAAA,EAAO,kBAAkB,CAAA;AAE3D;AAKA,eAAemC,kBAAAA,CACX,WAAA,EACA,QAAA,EACA,OAAA,EACa;AAEb,EAAA,MAAM,UAAA,GAAaC,oBAAAA,CAAoB,WAAA,EAAa,QAAQ,CAAA;AAG5D,EAAA,MAAM,SAAA,GAAYpC,KAAAA,CAAK,OAAA,CAAQ,UAAU,CAAA;AACzC,EAAA,MAAMI,KAAAA,CAAM,SAAA,EAAW,EAAE,SAAA,EAAW,MAAM,CAAA;AAG1C,EAAA,MAAMuB,SAAAA,CAAY,UAAA,EAAY,OAAA,EAAS,OAAO,CAAA;AAElD;AAiBA,eAAsB,cAAc,OAAA,EAAoC;AAEpE,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,eAAe,KAAK,GAAA,EAA4B;AAE5C,IAAA,MAAM,CAAC,OAAA,EAAS,GAAG,CAAA,GAAI,MAAM7B,OAAAA,CAAQ,MAAMuB,OAAAA,CAAQ,GAAA,EAAK,EAAE,aAAA,EAAe,IAAA,EAAM,CAAC,CAAA;AAEhF,IAAA,IAAI,GAAA,EAAK;AAEL,MAAA,MAAM,IAAI,MAAM,CAAA,0BAAA,EAA6B,GAAG,IAAI,EAAE,KAAA,EAAO,KAAK,CAAA;AAAA,IAEtE;AAEA,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAEzB,MAAA,MAAM,QAAA,GAAWrB,KAAAA,CAAK,IAAA,CAAK,GAAA,EAAK,MAAM,IAAI,CAAA;AAE1C,MAAA,IAAI,KAAA,CAAM,aAAY,EAAG;AAErB,QAAA,MAAM,KAAK,QAAQ,CAAA;AAAA,MAEvB,WACS,KAAA,CAAM,MAAA,MAAY,SAAA,CAAU,KAAA,CAAM,IAAI,CAAA,EAAG;AAE9C,QAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,MAEvB;AAAA,IAEJ;AAAA,EAEJ;AAEA,EAAA,MAAM,KAAK,OAAO,CAAA;AAGlB,EAAA,OAAO,MAAM,IAAA,EAAK;AAEtB;AAKA,SAAS,UAAU,QAAA,EAA2B;AAE1C,EAAA,OAAO6B,gBAAe,IAAA,CAAK,CAAC,QAAQ,QAAA,CAAS,QAAA,CAAS,GAAG,CAAC,CAAA;AAE9D;AAKA,SAAS,uBAAA,CAAwB,OAAe,UAAA,EAAiC;AAE7E,EAAA,OAAO;AAAA,IACH,MAAA,EAAQ,QAAA;AAAA,IACR,OAAO,EAAC;AAAA,IACR,QAAA,EAAU,CAAA;AAAA,IACV,YAAA,EAAc,CAAA;AAAA,IACd,WAAA,EAAa,CAAA;AAAA,IACb;AAAA,GACJ;AAEJ;;;ACnqCO,IAAM,gBAAA,GAAN,cAA+B,KAAA,CAAM;AAAA,EAIxC,YAA4B,UAAA,EAAoB;AAE5C,IAAA,KAAA,CAAM,CAAA,QAAA,EAAW,UAAU,CAAA,4BAAA,CAA8B,CAAA;AAFjC,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAAA,EAI5B;AAAA,EANkB,IAAA,GAAO,kBAAA;AAQ7B;AAWO,IAAM,oBAAA,GAAN,cAAmC,KAAA,CAAM;AAAA,EAI5C,WAAA,CACoB,YACA,SAAA,EAClB;AAEE,IAAA,KAAA,CAAM,CAAA,OAAA,EAAU,SAAS,CAAA,sBAAA,EAAyB,UAAU,CAAA,CAAA,CAAG,CAAA;AAJ/C,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAAA,EAKpB;AAAA,EATkB,IAAA,GAAO,sBAAA;AAW7B;AAWO,SAAS,gBAAA,CACZ,QACA,OAAA,EACI;AAEJ,EAAA,IAAI,OAAA,CAAQ,WAAA,IAAe,CAAC,MAAA,CAAO,MAAA,EAAQ;AAEvC,IAAA,MAAM,IAAI,gBAAA,CAAiB,MAAA,CAAO,IAAI,CAAA;AAAA,EAE1C;AAEJ;AAOO,SAAS,oBAAA,CACZ,MAAA,EACA,SAAA,EACA,OAAA,EACI;AAEJ,EAAA,IAAI,MAAA,CAAO,SAAA,IAAa,CAAC,OAAA,CAAQ,cAAA,EAAgB;AAE7C,IAAA,MAAM,IAAI,oBAAA,CAAqB,MAAA,CAAO,IAAA,EAAM,SAAS,CAAA;AAAA,EAEzD;AAEJ;;;ACrBO,IAAM,UAAN,MAA4B;AAAA,EAE/B,WAAA,GAAuC,IAAA;AAAA,EACvC,OAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA,GAAuC,IAAA;AAAA,EAEvC,WAAA,CACI,MAAA,EACA,QAAA,EACA,QAAA,EACA,SACA,WAAA,EACF;AAEE,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AAAA,EAExB;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,MAAA,GAAiB;AAEjB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EAEhB;AAAA,EAEA,IAAI,QAAA,GAAqB;AAErB,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EAEhB;AAAA,EAEA,IAAI,QAAA,GAAqB;AAErB,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EAEhB;AAAA,EAEA,IAAI,OAAA,GAAmB;AAEnB,IAAA,OAAO,IAAA,CAAK,QAAQ,UAAA,CAAW,OAAA;AAAA,EAEnC;AAAA,EAEA,IAAI,SAAA,GAAqB;AAErB,IAAA,OAAO,KAAK,WAAA,KAAgB,IAAA;AAAA,EAEhC;AAAA,EAEA,IAAI,QAAA,GAAW;AAEX,IAAA,OAAO,QAAA;AAAA,EAEX;AAAA,EAEA,IAAI,MAAA,GAAqB;AAErB,IAAA,IAAI,CAAC,KAAK,WAAA,EAAa;AAEnB,MAAA,MAAM,IAAI,MAAM,sCAAsC,CAAA;AAAA,IAE1D;AAEA,IAAA,OAAO,KAAK,WAAA,CAAY,EAAA;AAAA,EAE5B;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAA,GAAyB;AAE3B,IAAA,IAAI,KAAK,WAAA,EAAa;AAEtB,IAAA,IAAA,CAAK,cAAc,MAAM,gBAAA;AAAA,MACrB,KAAK,OAAA,CAAQ,UAAA;AAAA,MACb,KAAK,OAAA,CAAQ;AAAA,KACjB;AAAA,EAEJ;AAAA,EAEA,MAAM,UAAA,GAA4B;AAE9B,IAAA,IAAI,CAAC,KAAK,WAAA,EAAa;AAEvB,IAAA,MAAM,IAAA,CAAK,YAAY,OAAA,EAAQ;AAC/B,IAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,IAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAAA,EAE1B;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAA,CACF,MAAA,EACA,OAAA,EACY;AAKZ,IAAA,MAAM,KAAK,IAAA,CAAK,MAAA;AAChB,IAAA,MAAM,SAAS,MAAMb,GAAAA,CAAI,IAAO,MAAM,CAAA,CAAE,QAAQ,EAAE,CAAA;AAElD,IAAA,OAAQ,MAAA,CAAO,QAAQ,EAAC;AAAA,EAE5B;AAAA,EAEA,MAAM,OAAA,CAAQ,MAAA,EAAgB,OAAA,EAA6C;AAIvE,IAAA,MAAM,KAAK,IAAA,CAAK,MAAA;AAChB,IAAA,MAAM,SAAS,MAAMA,GAAAA,CAAI,IAAI,MAAM,CAAA,CAAE,QAAQ,EAAE,CAAA;AAE/C,IAAA,OAAO;AAAA,MACH,cAAc,MAAA,CAAO,eAAA,GACf,MAAA,CAAO,MAAA,CAAO,eAAe,CAAA,GAC7B;AAAA,KACV;AAAA,EAEJ;AAAA,EAEA,MAAM,YAAe,EAAA,EAAwD;AAEzE,IAAA,MAAM,KAAK,IAAA,CAAK,MAAA;AAEhB,IAAA,OAAO,EAAA,CAAG,WAAA,EAAY,CAAE,OAAA,CAAQ,OAAO,GAAA,KAAQ;AAE3C,MAAA,MAAM,EAAA,GAAyB;AAAA,QAC3B,MAAM,KAAA,CAAS,CAAA,EAAW,EAAA,EAA8B;AAEpD,UAAA,MAAM,IAAI,MAAMA,GAAAA,CAAI,IAAO,CAAC,CAAA,CAAE,QAAQ,GAAG,CAAA;AAEzC,UAAA,OAAQ,CAAA,CAAE,QAAQ,EAAC;AAAA,QAEvB,CAAA;AAAA,QACA,MAAM,OAAA,CAAQ,CAAA,EAAW,EAAA,EAAwC;AAE7D,UAAA,MAAM,IAAI,MAAMA,GAAAA,CAAI,IAAI,CAAC,CAAA,CAAE,QAAQ,GAAG,CAAA;AAEtC,UAAA,OAAO;AAAA,YACH,cAAc,CAAA,CAAE,eAAA,GACV,MAAA,CAAO,CAAA,CAAE,eAAe,CAAA,GACxB;AAAA,WACV;AAAA,QAEJ;AAAA,OACJ;AAEA,MAAA,OAAO,GAAG,EAAE,CAAA;AAAA,IAEhB,CAAC,CAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAA,GAAsC;AAExC,IAAA,OAAO,SAAA,CAAU,IAAA,CAAK,MAAA,EAA2B,IAAA,CAAK,SAAS,QAAQ,CAAA;AAAA,EAE3E;AAAA,EAEA,MAAM,aAAA,CAAc,IAAA,EAAc,MAAA,EAA8C;AAE5E,IAAA,OAAO,YAAY,IAAA,CAAK,MAAA,EAA2B,KAAK,OAAA,EAAS,QAAA,EAAU,MAAM,MAAM,CAAA;AAAA,EAE3F;AAAA,EAEA,MAAM,QAAA,GAAqC;AAEvC,IAAA,OAAO,aAAA,CAAc,IAAA,CAAK,MAAA,EAA2B,IAAA,CAAK,OAAO,CAAA;AAAA,EAErE;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAA,GAAoC;AAEtC,IAAA,oBAAA,CAAqB,IAAA,CAAK,OAAA,EAAS,UAAA,EAAY,IAAA,CAAK,QAAQ,CAAA;AAE5D,IAAA,OAAO,YAAA,CAAa,IAAA,CAAK,MAAA,EAA2B,IAAA,CAAK,OAAO,CAAA;AAAA,EAEpE;AAAA,EAEA,MAAM,QAAA,GAAoC;AAEtC,IAAA,oBAAA,CAAqB,IAAA,CAAK,OAAA,EAAS,UAAA,EAAY,IAAA,CAAK,QAAQ,CAAA;AAE5D,IAAA,OAAO,cAAA,CAAe,IAAA,CAAK,MAAA,EAA2B,IAAA,CAAK,OAAA,EAAS;AAAA,MAChE,UAAA,EAAY,KAAK,OAAA,CAAQ,IAAA;AAAA,MACzB,UAAA,EAAY,cAAA,CAAe,IAAA,CAAK,SAAS;AAAA,KAC5C,CAAA;AAAA,EAEL;AAAA,EAEA,MAAM,MAAM,OAAA,EAA8C;AAEtD,IAAA,MAAM,UAAA,GAAa,KAAK,iBAAA,EAAkB;AAC1C,IAAA,MAAM,UAAUhB,KAAAA,CAAK,IAAA;AAAA,MACjB,IAAA,CAAK,YAAA;AAAA,MACL,IAAA,CAAK,QAAQ,KAAA,CAAM;AAAA,KACvB;AAEA,IAAA,OAAO,SAAS,UAAA,EAAY,OAAA,EAAS,EAAE,KAAA,EAAO,OAAA,EAAS,OAAO,CAAA;AAAA,EAElE;AAAA,EAEA,MAAM,KAAA,GAAuB;AAEzB,IAAA,oBAAA,CAAqB,IAAA,CAAK,OAAA,EAAS,OAAA,EAAS,IAAA,CAAK,QAAQ,CAAA;AAEzD,IAAA,MAAM,KAAK,QAAA,EAAS;AACpB,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,EAAE,KAAA,EAAO,MAAM,CAAA;AAAA,EAEpC;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAA,CAAQ,QAAA,EAAkB,OAAA,EAA2C;AAEvE,IAAA,MAAM,UAAA,GAAa,KAAK,iBAAA,EAAkB;AAC1C,IAAA,MAAM,YAAA,GAAeA,KAAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,GACvC,WACAA,KAAAA,CAAK,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,QAAQ,CAAA;AAE3C,IAAA,OAAO,OAAA,CAAY,UAAA,EAAY,YAAA,EAAc,OAAO,CAAA;AAAA,EAExD;AAAA,EAEA,MAAM,QAAA,CAAS,SAAA,EAAqB,OAAA,EAA4C;AAE5E,IAAA,MAAM,UAAA,GAAa,KAAK,iBAAA,EAAkB;AAC1C,IAAA,MAAM,gBAAgB,SAAA,CAAU,GAAA;AAAA,MAAI,CAAC,EAAA,KACjCA,KAAAA,CAAK,UAAA,CAAW,EAAE,CAAA,GAAI,EAAA,GAAKA,KAAAA,CAAK,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,EAAE;AAAA,KAC9D;AAEA,IAAA,OAAO,QAAA,CAAa,UAAA,EAAY,aAAA,EAAe,OAAO,CAAA;AAAA,EAE1D;AAAA,EAEA,MAAM,MAAA,CAAO,OAAA,EAAiB,OAAA,EAA4C;AAEtE,IAAA,MAAM,UAAA,GAAa,KAAK,iBAAA,EAAkB;AAC1C,IAAA,MAAM,YAAA,GAAeA,KAAAA,CAAK,UAAA,CAAW,OAAO,CAAA,GACtC,UACAA,KAAAA,CAAK,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,OAAO,CAAA;AAE1C,IAAA,OAAO,MAAA,CAAW,UAAA,EAAY,YAAA,EAAc,OAAO,CAAA;AAAA,EAEvD;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAA,CACF,IAAA,EACA,OAAA,EACqB;AAErB,IAAA,OAAO,IAAA,CAAK,iBAAA,EAAkB,CAAE,GAAA,CAAI,MAAM,OAAO,CAAA;AAAA,EAErD;AAAA,EAEA,MAAM,YAAA,CACF,IAAA,EACA,OAAA,EACqB;AAErB,IAAA,OAAO,IAAA,CAAK,iBAAA,EAAkB,CAAE,MAAA,CAAO,MAAM,OAAO,CAAA;AAAA,EAExD;AAAA,EAEA,MAAM,WAAA,GAA0C;AAE5C,IAAA,OAAO,IAAA,CAAK,iBAAA,EAAkB,CAAE,EAAA,EAAG;AAAA,EAEvC;AAAA,EAEA,MAAM,eAAA,GAA6C;AAE/C,IAAA,OAAO,IAAA,CAAK,iBAAA,EAAkB,CAAE,IAAA,EAAK;AAAA,EAEzC;AAAA,EAEA,MAAM,iBAAA,GAA+C;AAEjD,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,eAAA,EAAgB;AAEvC,IAAA,OAAO,GAAA,CAAI,MAAA;AAAA,MACP,CAAC,OAAO,CAAC,EAAA,CAAG,aAAa,EAAA,CAAG,MAAA,KAAW,SAAA,IAAa,EAAA,CAAG,MAAA,KAAW,UAAA;AAAA,KACtE;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,GAAA,EAAiC;AAEvC,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,YAAY,CAAA;AAC/C,IAAA,MAAM,QAAQ,KAAA,CAAM,SAAA,CAAU,IAAA,CAAK,OAAA,CAAQ,MAAM,GAAG,CAAA;AAEpD,IAAA,OAAO,KAAA,IAAS,MAAA;AAAA,EAEpB;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAY,OAAA,EAAsC;AAEpD,IAAA,MAAM,cAAc,cAAA,EAAe;AACnC,IAAA,MAAM,WAAA,GAAc,cAAA,CAAe,IAAA,CAAK,SAAS,CAAA;AAEjD,IAAA,OAAO,WAAA,CAAY,OAAA;AAAA,MACf,IAAA,CAAK,MAAA;AAAA,MACL,KAAK,OAAA,CAAQ,IAAA;AAAA,MACb,WAAA;AAAA,MACA,EAAE,GAAG,OAAA,EAAS,SAAS,IAAA,CAAK,OAAA,CAAQ,WAAW,OAAA;AAAQ,KAC3D;AAAA,EAEJ;AAAA,EAEA,MAAM,WAAA,GAA6B;AAE/B,IAAA,MAAM,cAAc,cAAA,EAAe;AACnC,IAAA,MAAM,WAAA,GAAc,cAAA,CAAe,IAAA,CAAK,SAAS,CAAA;AAEjD,IAAA,MAAM,WAAA,CAAY,OAAA;AAAA,MACd,IAAA,CAAK,MAAA;AAAA,MACL,KAAK,OAAA,CAAQ,IAAA;AAAA,MACb;AAAA,KACJ;AAAA,EAEJ;AAAA,EAEA,MAAM,aAAA,GAAqC;AAEvC,IAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,IAAA,OAAO,WAAA,CAAY,MAAA;AAAA,MACf,IAAA,CAAK,MAAA;AAAA,MACL,KAAK,OAAA,CAAQ,IAAA;AAAA,MACb,IAAA,CAAK,QAAQ,UAAA,CAAW;AAAA,KAC5B;AAAA,EAEJ;AAAA,EAEA,MAAM,QAAA,CAAY,EAAA,EAAsB,OAAA,EAAmC;AAEvE,IAAA,MAAM,cAAc,cAAA,EAAe;AACnC,IAAA,MAAM,WAAA,GAAc,cAAA,CAAe,IAAA,CAAK,SAAS,CAAA;AAEjD,IAAA,OAAO,WAAA,CAAY,QAAA;AAAA,MACf,IAAA,CAAK,MAAA;AAAA,MACL,KAAK,OAAA,CAAQ,IAAA;AAAA,MACb,WAAA;AAAA,MACA,EAAA;AAAA,MACA,EAAE,GAAG,OAAA,EAAS,SAAS,IAAA,CAAK,OAAA,CAAQ,WAAW,OAAA;AAAQ,KAC3D;AAAA,EAEJ;AAAA,EAEA,MAAM,gBAAA,GAAqC;AAEvC,IAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,IAAA,OAAO,WAAA,CAAY,YAAA;AAAA,MACf,IAAA,CAAK,MAAA;AAAA,MACL,KAAK,OAAA,CAAQ;AAAA,KACjB;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eAAe,QAAA,EAA2C;AAE5D,IAAA,MAAM,YAAA,GAAeA,KAAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,GACvC,WACAA,KAAAA,CAAK,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,QAAQ,CAAA;AAE3C,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,YAAY,CAAA;AAE/C,IAAA,OAAO,YAAY,YAAA,EAAc;AAAA,MAC7B,aAAa,IAAA,CAAK,YAAA;AAAA,MAClB,QAAQ,IAAA,CAAK,OAAA;AAAA,MACb,OAAA,EAAS,KAAA,CAAM,aAAA,CAAc,IAAA,CAAK,QAAQ,IAAI,CAAA;AAAA,MAC9C,aAAA,EAAe,MAAM,mBAAA;AAAoB,KAC5C,CAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW,KAAA,EAAgD;AAE7D,IAAA,OAAO,IAAA,CAAK,iBAAA,EAAkB,CAAE,UAAA,CAAW,QAAW,KAAK,CAAA;AAAA,EAE/D;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAAgB,QAAA,EAAmC;AAErD,IAAA,MAAM,YAAA,GAAeA,KAAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,GACvC,WACAA,KAAAA,CAAK,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,QAAQ,CAAA;AAE3C,IAAA,OAAO,gBAAoB,YAAY,CAAA;AAAA,EAE3C;AAAA,EAEA,MAAM,cAAA,GAA2D;AAE7D,IAAA,OAAO,cAAA,CAAmB,IAAA,CAAK,OAAA,CAAQ,UAAU,CAAA;AAAA,EAErD;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAA,GAAgC;AAE5B,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,YAAY,CAAA;AAE/C,IAAA,OAAO;AAAA,MACH,IAAI,IAAA,CAAK,MAAA;AAAA,MACT,UAAA,EAAY,KAAK,OAAA,CAAQ,IAAA;AAAA,MACzB,UAAU,IAAA,CAAK,SAAA;AAAA,MACf,aAAa,IAAA,CAAK,YAAA;AAAA,MAClB,QAAQ,IAAA,CAAK,OAAA;AAAA,MACb,OAAA,EAAS,KAAA,CAAM,aAAA,CAAc,IAAA,CAAK,QAAQ,IAAI,CAAA;AAAA,MAC9C,aAAA,EAAe,MAAM,mBAAA;AAAoB,KAC7C;AAAA,EAEJ;AAAA,EAEA,oBAAA,GAAsC;AAElC,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,YAAY,CAAA;AAE/C,IAAA,OAAO;AAAA,MACH,IAAI,IAAA,CAAK,MAAA;AAAA,MACT,UAAA,EAAY,KAAK,OAAA,CAAQ,IAAA;AAAA,MACzB,UAAU,IAAA,CAAK,SAAA;AAAA,MACf,aAAa,IAAA,CAAK,YAAA;AAAA,MAClB,UAAA,EAAYA,MAAK,IAAA,CAAK,IAAA,CAAK,cAAc,IAAA,CAAK,OAAA,CAAQ,MAAM,OAAO,CAAA;AAAA,MACnE,MAAA,EAAQA,MAAK,IAAA,CAAK,IAAA,CAAK,cAAc,IAAA,CAAK,OAAA,CAAQ,MAAM,GAAG,CAAA;AAAA,MAC3D,QAAQ,IAAA,CAAK,OAAA;AAAA,MACb,OAAA,EAAS,KAAA,CAAM,aAAA,CAAc,IAAA,CAAK,QAAQ,IAAI,CAAA;AAAA,MAC9C,aAAA,EAAe,MAAM,mBAAA;AAAoB,KAC7C;AAAA,EAEJ;AAAA,EAEA,iBAAA,GAAmC;AAE/B,IAAA,IAAI,CAAC,KAAK,cAAA,EAAgB;AAEtB,MAAA,IAAA,CAAK,cAAA,GAAiB,IAAI,aAAA,CAAc,IAAA,CAAK,sBAAsB,CAAA;AAAA,IAEvE;AAEA,IAAA,OAAO,IAAA,CAAK,cAAA;AAAA,EAEhB;AAEJ;;;ACxhBA,SAAS,mBAAmB,OAAA,EAA4C;AAEpE,EAAA,OAAO,IAAI,iBAAiB,OAAO,CAAA;AAEvC;AA0CA,eAAsB,aAAA,CAClB,OAAA,GAAgC,EAAC,EACb;AAGpB,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,WAAA,IAAe,OAAA,CAAQ,GAAA,EAAI;AAGvD,EAAA,MAAM,UAAU,WAAW,CAAA;AAC3B,EAAA,MAAM,KAAA,GAAQ,gBAAgB,WAAW,CAAA;AAGzC,EAAA,MAAM,eAAA,GAAkB,mBAAmB,WAAW,CAAA;AACtD,EAAA,MAAM,gBAAgB,IAAA,EAAK;AAC3B,EAAA,MAAM,WAAW,eAAA,CAAgB,QAAA;AAIjC,EAAA,MAAM,MAAA,GAAS,cAAc,KAAA,EAAO;AAAA,IAChC,MAAM,OAAA,CAAQ,MAAA;AAAA,IACd,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,QAAA,EAAU,mBAAmB,eAAe;AAAA,GAC/C,CAAA;AAED,EAAA,IAAI,CAAC,MAAA,EAAQ;AAET,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,OAAA,CAAQ,MAAA,GACF,CAAA,QAAA,EAAW,OAAA,CAAQ,MAAM,CAAA,WAAA,CAAA,GACzB;AAAA,KAIV;AAAA,EAEJ;AAGA,EAAA,gBAAA,CAAiB,QAAQ,OAAO,CAAA;AAGhC,EAAA,MAAM,QAAA,GAAW,qBAAqB,MAAM,CAAA;AAE5C,EAAA,OAAO,IAAI,OAAA,CAAY,MAAA,EAAQ,QAAA,EAAU,QAAA,EAAU,SAAS,WAAW,CAAA;AAE3E","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.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';\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/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/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 * 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 * 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';\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 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 * 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\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\nexport type NoormIdentity = Selectable<NoormIdentitiesTable>;\nexport type NewNoormIdentity = Insertable<NoormIdentitiesTable>;\nexport type NoormIdentityUpdate = Updateable<NoormIdentitiesTable>;\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}\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 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 type { CryptoIdentity, Identity, IdentityOptions } from './types.js';\nimport { resolveIdentity as resolve } from './resolver.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// 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","/**\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} 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 * Check if a config is complete and usable.\n *\n * A config is complete when all required secrets (from its stage) are set.\n * Also checks for stage constraint violations.\n *\n * @example\n * ```typescript\n * const check = checkConfigCompleteness(config, state, settings)\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 stageName?: string,\n): CompletenessCheck {\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\n const existingSecrets = state.listSecrets(config.name);\n\n for (const secret of stage.secrets ?? []) {\n\n const isRequired = secret.required !== false; // Default to true\n if (isRequired && !existingSecrets.includes(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 * 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 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 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} 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 * @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): 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(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 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// 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 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 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 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 * 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 * SDK Context Implementation.\n *\n * The Context class provides programmatic access to all noorm operations.\n * It wraps core modules and provides a clean API for SDK users.\n */\nimport path from 'node:path';\n\nimport { sql, type Kysely } from 'kysely';\n\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 { ConnectionResult, Dialect } from '../core/connection/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 { createConnection, testConnection as coreTestConnection } from '../core/connection/index.js';\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';\n\nimport { checkProtectedConfig } from './guards.js';\nimport type {\n CreateContextOptions,\n ExecuteResult,\n TransactionContext,\n BuildOptions,\n} from './types.js';\n\n// ─────────────────────────────────────────────────────────────\n// Context Class\n// ─────────────────────────────────────────────────────────────\n\n/**\n * SDK Context implementation.\n *\n * Provides programmatic access to all noorm operations.\n *\n * @example\n * ```typescript\n * const ctx = await createContext({ config: 'dev' })\n * await ctx.connect()\n *\n * // Run queries\n * const users = await ctx.query('SELECT * FROM users')\n *\n * // Clean disconnect\n * await ctx.disconnect()\n * ```\n */\nexport class Context<DB = unknown> {\n\n #connection: ConnectionResult | null = null;\n #config: Config;\n #settings: Settings;\n #identity: Identity;\n #options: CreateContextOptions;\n #projectRoot: string;\n #changeManager: ChangeManager | null = null;\n\n constructor(\n config: Config,\n settings: Settings,\n identity: Identity,\n options: CreateContextOptions,\n projectRoot: string,\n ) {\n\n this.#config = config;\n this.#settings = settings;\n this.#identity = identity;\n this.#options = options;\n this.#projectRoot = projectRoot;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Read-only Properties\n // ─────────────────────────────────────────────────────────\n\n get config(): Config {\n\n return this.#config;\n\n }\n\n get settings(): Settings {\n\n return this.#settings;\n\n }\n\n get identity(): Identity {\n\n return this.#identity;\n\n }\n\n get dialect(): Dialect {\n\n return this.#config.connection.dialect;\n\n }\n\n get connected(): boolean {\n\n return this.#connection !== null;\n\n }\n\n get observer() {\n\n return observer;\n\n }\n\n get kysely(): Kysely<DB> {\n\n if (!this.#connection) {\n\n throw new Error('Not connected. Call connect() first.');\n\n }\n\n return this.#connection.db as Kysely<DB>;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async connect(): Promise<void> {\n\n if (this.#connection) return;\n\n this.#connection = await createConnection(\n this.#config.connection,\n this.#config.name,\n );\n\n }\n\n async disconnect(): Promise<void> {\n\n if (!this.#connection) return;\n\n await this.#connection.destroy();\n this.#connection = null;\n this.#changeManager = null;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // SQL Execution\n // ─────────────────────────────────────────────────────────\n\n async query<T = Record<string, unknown>>(\n sqlStr: string,\n _params?: unknown[],\n ): Promise<T[]> {\n\n // Note: Kysely's sql.raw() executes raw SQL without parameter binding.\n // For parameterized queries, users should use ctx.kysely directly with\n // Kysely's type-safe query builder or sql tagged template literals.\n const db = this.kysely;\n const result = await sql.raw<T>(sqlStr).execute(db);\n\n return (result.rows ?? []) as T[];\n\n }\n\n async execute(sqlStr: string, _params?: unknown[]): Promise<ExecuteResult> {\n\n // Note: Kysely's sql.raw() executes raw SQL without parameter binding.\n // For parameterized queries, users should use ctx.kysely directly.\n const db = this.kysely;\n const result = await sql.raw(sqlStr).execute(db);\n\n return {\n rowsAffected: result.numAffectedRows\n ? Number(result.numAffectedRows)\n : undefined,\n };\n\n }\n\n async transaction<T>(fn: (tx: TransactionContext) => Promise<T>): Promise<T> {\n\n const db = this.kysely;\n\n return db.transaction().execute(async (trx) => {\n\n const tx: TransactionContext = {\n async query<R>(s: string, _p?: unknown[]): Promise<R[]> {\n\n const r = await sql.raw<R>(s).execute(trx);\n\n return (r.rows ?? []) as R[];\n\n },\n async execute(s: string, _p?: unknown[]): Promise<ExecuteResult> {\n\n const r = await sql.raw(s).execute(trx);\n\n return {\n rowsAffected: r.numAffectedRows\n ? Number(r.numAffectedRows)\n : undefined,\n };\n\n },\n };\n\n return fn(tx);\n\n });\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Explore\n // ─────────────────────────────────────────────────────────\n\n async listTables(): Promise<TableSummary[]> {\n\n return fetchList(this.kysely as Kysely<unknown>, this.dialect, 'tables');\n\n }\n\n async describeTable(name: string, schema?: string): Promise<TableDetail | null> {\n\n return fetchDetail(this.kysely as Kysely<unknown>, this.dialect, 'tables', name, schema);\n\n }\n\n async overview(): Promise<ExploreOverview> {\n\n return fetchOverview(this.kysely as Kysely<unknown>, this.dialect);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Schema Operations\n // ─────────────────────────────────────────────────────────\n\n async truncate(): Promise<TruncateResult> {\n\n checkProtectedConfig(this.#config, 'truncate', this.#options);\n\n return truncateData(this.kysely as Kysely<unknown>, this.dialect);\n\n }\n\n async teardown(): Promise<TeardownResult> {\n\n checkProtectedConfig(this.#config, 'teardown', this.#options);\n\n return teardownSchema(this.kysely as Kysely<unknown>, this.dialect, {\n configName: this.#config.name,\n executedBy: formatIdentity(this.#identity),\n });\n\n }\n\n async build(options?: BuildOptions): Promise<BatchResult> {\n\n const runContext = this.#createRunContext();\n const sqlPath = path.join(\n this.#projectRoot,\n this.#config.paths.sql,\n );\n\n return runBuild(runContext, sqlPath, { force: options?.force });\n\n }\n\n async reset(): Promise<void> {\n\n checkProtectedConfig(this.#config, 'reset', this.#options);\n\n await this.teardown();\n await this.build({ force: true });\n\n }\n\n // ─────────────────────────────────────────────────────────\n // File Runner\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.#projectRoot, filepath);\n\n return coreRunFile(runContext, absolutePath, options);\n\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.#projectRoot, fp),\n );\n\n return coreRunFiles(runContext, absolutePaths, options);\n\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.#projectRoot, dirpath);\n\n return coreRunDir(runContext, absolutePath, options);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Changes\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 async revertChange(\n name: string,\n options?: ChangeOptions,\n ): Promise<ChangeResult> {\n\n return this.#getChangeManager().revert(name, options);\n\n }\n\n async fastForward(): Promise<BatchChangeResult> {\n\n return this.#getChangeManager().ff();\n\n }\n\n async getChangeStatus(): Promise<ChangeListItem[]> {\n\n return this.#getChangeManager().list();\n\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 getSecret(key: string): string | undefined {\n\n const state = getStateManager(this.#projectRoot);\n const value = state.getSecret(this.#config.name, key);\n\n return value ?? undefined;\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Locks\n // ─────────────────────────────────────────────────────────\n\n async acquireLock(options?: LockOptions): Promise<Lock> {\n\n const lockManager = getLockManager();\n const identityStr = formatIdentity(this.#identity);\n\n return lockManager.acquire(\n this.kysely as unknown as Kysely<NoormDatabase>,\n this.#config.name,\n identityStr,\n { ...options, dialect: this.#config.connection.dialect },\n );\n\n }\n\n async releaseLock(): Promise<void> {\n\n const lockManager = getLockManager();\n const identityStr = formatIdentity(this.#identity);\n\n await lockManager.release(\n this.kysely as unknown as Kysely<NoormDatabase>,\n this.#config.name,\n identityStr,\n );\n\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.#config.name,\n this.#config.connection.dialect,\n );\n\n }\n\n async withLock<T>(fn: () => Promise<T>, options?: LockOptions): Promise<T> {\n\n const lockManager = getLockManager();\n const identityStr = formatIdentity(this.#identity);\n\n return lockManager.withLock(\n this.kysely as unknown as Kysely<NoormDatabase>,\n this.#config.name,\n identityStr,\n fn,\n { ...options, dialect: this.#config.connection.dialect },\n );\n\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.#config.name,\n );\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Templates\n // ─────────────────────────────────────────────────────────\n\n async renderTemplate(filepath: string): Promise<TemplateResult> {\n\n const absolutePath = path.isAbsolute(filepath)\n ? filepath\n : path.join(this.#projectRoot, filepath);\n\n const state = getStateManager(this.#projectRoot);\n\n return processFile(absolutePath, {\n projectRoot: this.#projectRoot,\n config: this.#config as unknown as Record<string, unknown>,\n secrets: state.getAllSecrets(this.#config.name),\n globalSecrets: state.getAllGlobalSecrets(),\n });\n\n }\n\n // ─────────────────────────────────────────────────────────\n // History\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 async computeChecksum(filepath: string): Promise<string> {\n\n const absolutePath = path.isAbsolute(filepath)\n ? filepath\n : path.join(this.#projectRoot, filepath);\n\n return coreComputeChecksum(absolutePath);\n\n }\n\n async testConnection(): Promise<{ ok: boolean; error?: string }> {\n\n return coreTestConnection(this.#config.connection);\n\n }\n\n // ─────────────────────────────────────────────────────────\n // Private Helpers\n // ─────────────────────────────────────────────────────────\n\n #createRunContext(): RunContext {\n\n const state = getStateManager(this.#projectRoot);\n\n return {\n db: this.kysely as unknown as Kysely<NoormDatabase>,\n configName: this.#config.name,\n identity: this.#identity,\n projectRoot: this.#projectRoot,\n config: this.#config as unknown as Record<string, unknown>,\n secrets: state.getAllSecrets(this.#config.name),\n globalSecrets: state.getAllGlobalSecrets(),\n };\n\n }\n\n #createChangeContext(): ChangeContext {\n\n const state = getStateManager(this.#projectRoot);\n\n return {\n db: this.kysely as unknown as Kysely<NoormDatabase>,\n configName: this.#config.name,\n identity: this.#identity,\n projectRoot: this.#projectRoot,\n changesDir: path.join(this.#projectRoot, this.#config.paths.changes),\n sqlDir: path.join(this.#projectRoot, this.#config.paths.sql),\n config: this.#config as unknown as Record<string, unknown>,\n secrets: state.getAllSecrets(this.#config.name),\n globalSecrets: state.getAllGlobalSecrets(),\n };\n\n }\n\n #getChangeManager(): ChangeManager {\n\n if (!this.#changeManager) {\n\n this.#changeManager = new ChangeManager(this.#createChangeContext());\n\n }\n\n return this.#changeManager;\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({ config: 'dev' })\n * await ctx.connect()\n *\n * // Query the database\n * const users = await ctx.query<User>('SELECT * FROM users')\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>(\n options: CreateContextOptions = {},\n): Promise<Context<DB>> {\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>(config, settings, identity, options, projectRoot);\n\n}\n\n// ─────────────────────────────────────────────────────────────\n// Re-exports\n// ─────────────────────────────────────────────────────────────\n\nexport { Context } from './context.js';\n\n// Types\nexport type {\n CreateContextOptions,\n ExecuteResult,\n TransactionContext,\n BuildOptions,\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"]}
|