/** * SQLite schema feature expressiveness matrix for CLEO's Drizzle schema layer. * * This matrix is intentionally code, not prose-only documentation: PM-Core V2 * planning can import it, tests can lock it, and future schema work has a small * SSoT for deciding whether an invariant belongs in TypeScript Drizzle schema or * in a hand-written SQL migration. * * Scope: SQLite DDL features used or plausibly needed by CLEO tasks.db and sibling * stores while the repo is pinned to `drizzle-orm@1.0.0-beta.22-ec7b61d` and * `drizzle-kit@1.0.0-beta.19-d95b7a4`. * * @task T10567 */ /** Expressiveness class for a SQLite DDL feature in CLEO's schema workflow. */ export type SqliteFeatureExpressiveness = 'schema-supported' | 'schema-supported-with-sql-template' | 'raw-sql-required' | 'dual-source-required'; /** SQLite DDL capability groups covered by the expressiveness matrix. */ export type SqliteFeatureGroup = 'index' | 'constraint' | 'programmability' | 'column'; /** * A single SQLite feature classification entry. * * `drizzleSchemaPath` states whether the TypeScript schema can be the authoring * surface. `rawSqlPath` states whether hand-written migration SQL remains needed * for first-class SQLite semantics or drizzle-kit gaps. */ export interface SqliteFeatureExpressivenessEntry { /** Stable machine key used by tests and downstream PM-Core consumers. */ readonly key: string; /** Feature family for grouping the matrix. */ readonly group: SqliteFeatureGroup; /** Human-facing SQLite feature label. */ readonly feature: string; /** Classification for CLEO's current Drizzle + SQLite migration workflow. */ readonly expressiveness: SqliteFeatureExpressiveness; /** How the feature is represented, if at all, in Drizzle schema TypeScript. */ readonly drizzleSchemaPath: string; /** How the feature is represented in migration SQL. */ readonly rawSqlPath: string; /** CLEO-local note that explains why this classification exists. */ readonly cleoGuidance: string; } /** * SQLite feature expressiveness matrix for Drizzle schema TypeScript versus raw * SQL migrations. */ export declare const SQLITE_FEATURE_EXPRESSIVENESS_MATRIX: readonly [{ readonly key: "index.plain"; readonly group: "index"; readonly feature: "Plain single-column index"; readonly expressiveness: "schema-supported"; readonly drizzleSchemaPath: "index('idx_name').on(table.column)"; readonly rawSqlPath: "Generated or hand-written CREATE INDEX is equivalent."; readonly cleoGuidance: "Prefer Drizzle schema for ordinary lookup indexes."; }, { readonly key: "index.composite"; readonly group: "index"; readonly feature: "Composite multi-column index"; readonly expressiveness: "schema-supported"; readonly drizzleSchemaPath: "index('idx_name').on(table.columnA, table.columnB)"; readonly rawSqlPath: "Generated or hand-written CREATE INDEX over the same ordered column list."; readonly cleoGuidance: "Prefer Drizzle schema when every indexed term is a table column."; }, { readonly key: "index.unique"; readonly group: "index"; readonly feature: "Unique index or unique constraint"; readonly expressiveness: "schema-supported"; readonly drizzleSchemaPath: "uniqueIndex('uq_name').on(...) or unique('uq_name').on(...)"; readonly rawSqlPath: "Generated or hand-written CREATE UNIQUE INDEX / UNIQUE constraint."; readonly cleoGuidance: "Prefer Drizzle schema for uniqueness invariants that map to columns."; }, { readonly key: "index.partial"; readonly group: "index"; readonly feature: "Partial index with WHERE predicate"; readonly expressiveness: "schema-supported-with-sql-template"; readonly drizzleSchemaPath: "index('idx_name').on(...).where(sql`predicate`)"; readonly rawSqlPath: "Hand-written SQL remains acceptable for predicates drizzle-kit cannot diff safely."; readonly cleoGuidance: "Schema expression is available in current CLEO code; keep SQL migration comments when predicates are complex or historically raw-SQL only."; }, { readonly key: "index.expression"; readonly group: "index"; readonly feature: "Expression index"; readonly expressiveness: "schema-supported-with-sql-template"; readonly drizzleSchemaPath: "index('idx_name').on(sql template expression such as date(created_at))"; readonly rawSqlPath: "CREATE INDEX idx_name ON table_name (expression)."; readonly cleoGuidance: "Use Drizzle only when the expression is stable and covered by tests; otherwise prefer raw SQL with an adjacent schema comment."; }, { readonly key: "constraint.check"; readonly group: "constraint"; readonly feature: "CHECK constraint"; readonly expressiveness: "dual-source-required"; readonly drizzleSchemaPath: "Drizzle sqlite-core exposes table-level CHECK builders, but CLEO enum/invariant checks are often migration-owned."; readonly rawSqlPath: "CHECK (...) in CREATE TABLE or table rebuild migration."; readonly cleoGuidance: "Document every CHECK that is not visible beside the relevant TypeScript field; migration SQL is still the enforcement SSoT for existing tables."; }, { readonly key: "constraint.foreign-key"; readonly group: "constraint"; readonly feature: "Foreign key constraint"; readonly expressiveness: "schema-supported"; readonly drizzleSchemaPath: "column.references(() => other.id, { onDelete: 'cascade' }) or foreignKey(...)"; readonly rawSqlPath: "REFERENCES target(column) with ON DELETE/UPDATE actions in CREATE TABLE."; readonly cleoGuidance: "Prefer Drizzle schema for FK shape, then keep migrations parity-tested."; }, { readonly key: "programmability.trigger"; readonly group: "programmability"; readonly feature: "Trigger"; readonly expressiveness: "raw-sql-required"; readonly drizzleSchemaPath: "No first-class Drizzle table-builder construct for SQLite triggers."; readonly rawSqlPath: "CREATE TRIGGER ... BEGIN ... END in hand-written migration SQL."; readonly cleoGuidance: "Triggers must live in raw SQL migrations with tests proving fresh-db and upgrade behavior."; }, { readonly key: "column.generated"; readonly group: "column"; readonly feature: "Generated column"; readonly expressiveness: "raw-sql-required"; readonly drizzleSchemaPath: "Do not rely on schema TypeScript as the authoritative migration surface until generated-column diffing is proven in this repo."; readonly rawSqlPath: "column_name TYPE GENERATED ALWAYS AS (expression) VIRTUAL|STORED."; readonly cleoGuidance: "Use raw SQL plus a TypeScript schema documentation comment for generated columns; add parity tests before exposing as a typed field."; }]; /** * Documentation gaps in existing schema TypeScript that future schema work should * close when raw SQL carries more semantics than the Drizzle table declaration. */ export declare const SQLITE_SCHEMA_TS_DOCUMENTATION_GAPS: readonly [{ readonly key: "gap.check-constraints"; readonly title: "CHECK constraints are not consistently documented beside TS fields"; readonly guidance: "When a migration owns enum or cross-column CHECK logic, add a nearby field/table comment naming the migration and invariant."; }, { readonly key: "gap.raw-sql-triggers"; readonly title: "Triggers have no TypeScript schema anchor"; readonly guidance: "For any CREATE TRIGGER migration, add a schema comment or exported metadata entry describing trigger name, timing, table, and side effects."; }, { readonly key: "gap.generated-columns"; readonly title: "Generated columns need explicit raw-SQL provenance comments"; readonly guidance: "Generated column definitions should name the raw SQL migration and whether the column is VIRTUAL or STORED before consumers depend on it."; }, { readonly key: "gap.expression-indexes"; readonly title: "Expression and partial indexes need predicate/expression rationale"; readonly guidance: "Expression/partial indexes expressed through sql templates should explain query shape, predicate, and fallback raw SQL migration behavior."; }]; /** Return the matrix entry for a stable SQLite feature key. */ export declare function getSqliteFeatureExpressivenessEntry(key: string): SqliteFeatureExpressivenessEntry | undefined; //# sourceMappingURL=sqlite-feature-expressiveness.d.ts.map