@happyvertical/smrt-core 0.41.0 → 0.42.0
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/AGENTS.md +1 -1
- package/agents/schema-paths.md +79 -8
- package/dist/change-feed.d.ts.map +1 -1
- package/dist/change-feed.js +2 -2
- package/dist/change-feed.js.map +1 -1
- package/dist/change-signals.d.ts.map +1 -1
- package/dist/change-signals.js +8 -1
- package/dist/change-signals.js.map +1 -1
- package/dist/class.d.ts.map +1 -1
- package/dist/class.js +10 -9
- package/dist/class.js.map +1 -1
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +2 -2
- package/dist/collection.js.map +1 -1
- package/dist/dispatch/collections/Dispatches.d.ts.map +1 -1
- package/dist/dispatch/collections/Dispatches.js +5 -5
- package/dist/dispatch/collections/Dispatches.js.map +1 -1
- package/dist/dispatch/models/Dispatch.d.ts +1 -1
- package/dist/dispatch/models/Dispatch.d.ts.map +1 -1
- package/dist/dispatch/models/Dispatch.js +3 -2
- package/dist/dispatch/models/Dispatch.js.map +1 -1
- package/dist/dispatch/models/DispatchSubscription.d.ts +1 -1
- package/dist/dispatch/models/DispatchSubscription.d.ts.map +1 -1
- package/dist/dispatch/models/DispatchSubscription.js +2 -1
- package/dist/dispatch/models/DispatchSubscription.js.map +1 -1
- package/dist/embeddings/storage.d.ts.map +1 -1
- package/dist/embeddings/storage.js +2 -1
- package/dist/embeddings/storage.js.map +1 -1
- package/dist/learning/memory.d.ts.map +1 -1
- package/dist/learning/memory.js +5 -4
- package/dist/learning/memory.js.map +1 -1
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/migrations/differ.js +2 -2
- package/dist/migrations/differ.js.map +1 -1
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +2 -1
- package/dist/migrations/integer-width.d.ts +99 -0
- package/dist/migrations/integer-width.d.ts.map +1 -0
- package/dist/migrations/integer-width.js +237 -0
- package/dist/migrations/integer-width.js.map +1 -0
- package/dist/migrations/minor-units.d.ts +2 -2
- package/dist/migrations/minor-units.d.ts.map +1 -1
- package/dist/migrations/minor-units.js +16 -14
- package/dist/migrations/minor-units.js.map +1 -1
- package/dist/migrations/tracker.d.ts.map +1 -1
- package/dist/migrations/tracker.js +28 -20
- package/dist/migrations/tracker.js.map +1 -1
- package/dist/migrations.js +2 -1
- package/dist/schema/ddl/duckdb-strategy.d.ts.map +1 -1
- package/dist/schema/ddl/duckdb-strategy.js +1 -0
- package/dist/schema/ddl/duckdb-strategy.js.map +1 -1
- package/dist/schema/ddl/postgres-strategy.d.ts.map +1 -1
- package/dist/schema/ddl/postgres-strategy.js +2 -0
- package/dist/schema/ddl/postgres-strategy.js.map +1 -1
- package/dist/schema/generator.d.ts +1 -33
- package/dist/schema/generator.d.ts.map +1 -1
- package/dist/schema/generator.js +1 -150
- package/dist/schema/generator.js.map +1 -1
- package/dist/schema/index.d.ts +1 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -2
- package/dist/schema/live-parity.d.ts +3 -1
- package/dist/schema/live-parity.d.ts.map +1 -1
- package/dist/schema/live-parity.js +19 -0
- package/dist/schema/live-parity.js.map +1 -1
- package/dist/schema/types.d.ts +17 -10
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema.js +1 -2
- package/dist/smrt-knowledge.json +7 -7
- package/dist/system/retention.d.ts.map +1 -1
- package/dist/system/retention.js +3 -3
- package/dist/system/retention.js.map +1 -1
- package/dist/system/schema.d.ts +2 -1
- package/dist/system/schema.d.ts.map +1 -1
- package/dist/system/schema.js +4 -2
- package/dist/system/schema.js.map +1 -1
- package/dist/utils/safe-integer.d.ts +19 -0
- package/dist/utils/safe-integer.d.ts.map +1 -0
- package/dist/utils/safe-integer.js +31 -0
- package/dist/utils/safe-integer.js.map +1 -0
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +6 -3
- package/dist/utils.js.map +1 -1
- package/dist/vite-plugin/index.d.ts.map +1 -1
- package/dist/vite-plugin/index.js +0 -53
- package/dist/vite-plugin/index.js.map +1 -1
- package/package.json +4 -4
- package/dist/schema/override-system.d.ts +0 -43
- package/dist/schema/override-system.d.ts.map +0 -1
- package/dist/schema/override-system.js +0 -205
- package/dist/schema/override-system.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"duckdb-strategy.js","names":[],"sources":["../../../src/schema/ddl/duckdb-strategy.ts"],"sourcesContent":["/**\n * DuckDB DDL Strategy\n *\n * DuckDB-specific DDL generation with the following characteristics:\n * - UNIQUE constraints MUST be inline for UPSERT to work (DuckDB issue #12684)\n * - Supports CAST in DEFAULT values\n * - Native BOOLEAN, JSON types\n * - Does NOT support triggers\n *\n * CRITICAL: DuckDB's ON CONFLICT clause only works with inline UNIQUE constraints,\n * not with separate UNIQUE indexes. This is a known DuckDB limitation.\n */\n\nimport { isStiSubtypeUniqueIndex, renderIndexTarget } from '../index-utils.js';\nimport type { SchemaDefinition, SQLDataType } from '../types.js';\nimport { BaseDDLStrategy } from './base-strategy.js';\nimport type { DatabaseEngine } from './types.js';\n\nexport class DuckDBStrategy extends BaseDDLStrategy {\n readonly engine: DatabaseEngine = 'duckdb';\n\n /**\n * Map types for DuckDB\n * DuckDB has native support for most types\n */\n mapType(type: SQLDataType): string {\n switch (type) {\n case 'TIMESTAMP':\n return 'TIMESTAMP'; // DuckDB supports TIMESTAMP natively\n case 'JSON':\n return 'JSON'; // DuckDB has native JSON type\n case 'UUID':\n return 'UUID'; // DuckDB has a native UUID type (R11)\n default:\n return super.mapType(type);\n }\n }\n\n /**\n * Generate CREATE INDEX statements\n *\n * CRITICAL: Skip UNIQUE indexes - they must be inline constraints for UPSERT\n */\n generateIndexes(schema: SchemaDefinition): string[] {\n const { tableName, indexes } = schema;\n const statements: string[] = [];\n\n for (const index of indexes) {\n // Skip UNIQUE indexes - they're inline constraints\n if (index.unique && !index.where && !index.jsonPath) {\n continue;\n }\n\n // An STI subtype-scoped UNIQUE (`unique: true` declared only on a\n // descendant, #2359) cannot degrade to a full index the way the other\n // partial indexes below do: dropping the predicate while keeping UNIQUE\n // would enforce one subtype's constraint across every sibling's rows in\n // the shared table. DuckDB has no faithful shape for it, so it is not\n // emitted here (nor by the migration differ on this engine) — the\n // constraint is simply not enforced on DuckDB/JSON. Caller-declared\n // partial uniques (`WHERE active = TRUE`) keep degrading to full UNIQUE.\n if (isStiSubtypeUniqueIndex(index)) {\n continue;\n }\n\n const target = renderIndexTarget(index, this.engine);\n if (!target) {\n continue;\n }\n const indexType = index.unique ? 'UNIQUE INDEX' : 'INDEX';\n let sql = `CREATE ${indexType} IF NOT EXISTS \"${index.name}\" ON \"${tableName}\" (${target})`;\n\n // DuckDB (and the JSON adapter backed by it) rejects partial indexes.\n // Match the migration differ's documented compatibility behavior by\n // degrading the declaration to a full index while preserving UNIQUE.\n\n sql += ';';\n statements.push(sql);\n }\n\n return statements;\n }\n\n /**\n * DuckDB does NOT support triggers\n */\n generateTriggers(_schema: SchemaDefinition): string[] {\n return []; // DuckDB doesn't support triggers\n }\n\n /**\n * DuckDB does NOT support triggers\n */\n supportsTriggers(): boolean {\n return false;\n }\n\n /**\n * CRITICAL: DuckDB requires inline UNIQUE for UPSERT\n *\n * DuckDB issue #12684: ON CONFLICT only works with inline UNIQUE constraints,\n * not with separate CREATE UNIQUE INDEX statements.\n */\n requiresInlineUnique(): boolean {\n return true;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,IAAa,iBAAb,cAAoC,gBAAgB;CAClD,SAAkC;;;;;CAMlC,QAAQ,MAA2B;EACjC,QAAQ,MAAR;GACE,KAAK,aACH,OAAO;GACT,KAAK,QACH,OAAO;GACT,KAAK,QACH,OAAO;GACT,SACE,OAAO,MAAM,QAAQ,IAAI;EAC7B;CACF;;;;;;CAOA,gBAAgB,QAAoC;EAClD,MAAM,EAAE,WAAW,YAAY;EAC/B,MAAM,aAAuB,CAAC;EAE9B,KAAK,MAAM,SAAS,SAAS;GAE3B,IAAI,MAAM,UAAU,CAAC,MAAM,SAAS,CAAC,MAAM,UACzC;GAWF,IAAI,wBAAwB,KAAK,GAC/B;GAGF,MAAM,SAAS,kBAAkB,OAAO,KAAK,MAAM;GACnD,IAAI,CAAC,QACH;GAGF,IAAI,MAAM,UADQ,MAAM,SAAS,iBAAiB,QACpB,kBAAkB,MAAM,KAAK,QAAQ,UAAU,KAAK,OAAO;GAMzF,OAAO;GACP,WAAW,KAAK,GAAG;EACrB;EAEA,OAAO;CACT;;;;CAKA,iBAAiB,SAAqC;EACpD,OAAO,CAAC;CACV;;;;CAKA,mBAA4B;EAC1B,OAAO;CACT;;;;;;;CAQA,uBAAgC;EAC9B,OAAO;CACT;AACF"}
|
|
1
|
+
{"version":3,"file":"duckdb-strategy.js","names":[],"sources":["../../../src/schema/ddl/duckdb-strategy.ts"],"sourcesContent":["/**\n * DuckDB DDL Strategy\n *\n * DuckDB-specific DDL generation with the following characteristics:\n * - UNIQUE constraints MUST be inline for UPSERT to work (DuckDB issue #12684)\n * - Supports CAST in DEFAULT values\n * - Native BOOLEAN, JSON types\n * - Does NOT support triggers\n *\n * CRITICAL: DuckDB's ON CONFLICT clause only works with inline UNIQUE constraints,\n * not with separate UNIQUE indexes. This is a known DuckDB limitation.\n */\n\nimport { isStiSubtypeUniqueIndex, renderIndexTarget } from '../index-utils.js';\nimport type { SchemaDefinition, SQLDataType } from '../types.js';\nimport { BaseDDLStrategy } from './base-strategy.js';\nimport type { DatabaseEngine } from './types.js';\n\nexport class DuckDBStrategy extends BaseDDLStrategy {\n readonly engine: DatabaseEngine = 'duckdb';\n\n /**\n * Map types for DuckDB\n * DuckDB has native support for most types\n */\n mapType(type: SQLDataType): string {\n switch (type) {\n case 'INTEGER':\n return 'BIGINT';\n case 'TIMESTAMP':\n return 'TIMESTAMP'; // DuckDB supports TIMESTAMP natively\n case 'JSON':\n return 'JSON'; // DuckDB has native JSON type\n case 'UUID':\n return 'UUID'; // DuckDB has a native UUID type (R11)\n default:\n return super.mapType(type);\n }\n }\n\n /**\n * Generate CREATE INDEX statements\n *\n * CRITICAL: Skip UNIQUE indexes - they must be inline constraints for UPSERT\n */\n generateIndexes(schema: SchemaDefinition): string[] {\n const { tableName, indexes } = schema;\n const statements: string[] = [];\n\n for (const index of indexes) {\n // Skip UNIQUE indexes - they're inline constraints\n if (index.unique && !index.where && !index.jsonPath) {\n continue;\n }\n\n // An STI subtype-scoped UNIQUE (`unique: true` declared only on a\n // descendant, #2359) cannot degrade to a full index the way the other\n // partial indexes below do: dropping the predicate while keeping UNIQUE\n // would enforce one subtype's constraint across every sibling's rows in\n // the shared table. DuckDB has no faithful shape for it, so it is not\n // emitted here (nor by the migration differ on this engine) — the\n // constraint is simply not enforced on DuckDB/JSON. Caller-declared\n // partial uniques (`WHERE active = TRUE`) keep degrading to full UNIQUE.\n if (isStiSubtypeUniqueIndex(index)) {\n continue;\n }\n\n const target = renderIndexTarget(index, this.engine);\n if (!target) {\n continue;\n }\n const indexType = index.unique ? 'UNIQUE INDEX' : 'INDEX';\n let sql = `CREATE ${indexType} IF NOT EXISTS \"${index.name}\" ON \"${tableName}\" (${target})`;\n\n // DuckDB (and the JSON adapter backed by it) rejects partial indexes.\n // Match the migration differ's documented compatibility behavior by\n // degrading the declaration to a full index while preserving UNIQUE.\n\n sql += ';';\n statements.push(sql);\n }\n\n return statements;\n }\n\n /**\n * DuckDB does NOT support triggers\n */\n generateTriggers(_schema: SchemaDefinition): string[] {\n return []; // DuckDB doesn't support triggers\n }\n\n /**\n * DuckDB does NOT support triggers\n */\n supportsTriggers(): boolean {\n return false;\n }\n\n /**\n * CRITICAL: DuckDB requires inline UNIQUE for UPSERT\n *\n * DuckDB issue #12684: ON CONFLICT only works with inline UNIQUE constraints,\n * not with separate CREATE UNIQUE INDEX statements.\n */\n requiresInlineUnique(): boolean {\n return true;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,IAAa,iBAAb,cAAoC,gBAAgB;CAClD,SAAkC;;;;;CAMlC,QAAQ,MAA2B;EACjC,QAAQ,MAAR;GACE,KAAK,WACH,OAAO;GACT,KAAK,aACH,OAAO;GACT,KAAK,QACH,OAAO;GACT,KAAK,QACH,OAAO;GACT,SACE,OAAO,MAAM,QAAQ,IAAI;EAC7B;CACF;;;;;;CAOA,gBAAgB,QAAoC;EAClD,MAAM,EAAE,WAAW,YAAY;EAC/B,MAAM,aAAuB,CAAC;EAE9B,KAAK,MAAM,SAAS,SAAS;GAE3B,IAAI,MAAM,UAAU,CAAC,MAAM,SAAS,CAAC,MAAM,UACzC;GAWF,IAAI,wBAAwB,KAAK,GAC/B;GAGF,MAAM,SAAS,kBAAkB,OAAO,KAAK,MAAM;GACnD,IAAI,CAAC,QACH;GAGF,IAAI,MAAM,UADQ,MAAM,SAAS,iBAAiB,QACpB,kBAAkB,MAAM,KAAK,QAAQ,UAAU,KAAK,OAAO;GAMzF,OAAO;GACP,WAAW,KAAK,GAAG;EACrB;EAEA,OAAO;CACT;;;;CAKA,iBAAiB,SAAqC;EACpD,OAAO,CAAC;CACV;;;;CAKA,mBAA4B;EAC1B,OAAO;CACT;;;;;;;CAQA,uBAAgC;EAC9B,OAAO;CACT;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-strategy.d.ts","sourceRoot":"","sources":["../../../src/schema/ddl/postgres-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAc;IAE7C;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"postgres-strategy.d.ts","sourceRoot":"","sources":["../../../src/schema/ddl/postgres-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAc;IAE7C;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM;IAsBlC;;;;;OAKG;IACH,SAAS,CAAC,wBAAwB,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,iBAAiB,GACzB,MAAM;IAsDT;;OAEG;IACH,gBAAgB,IAAI,OAAO;IAI3B;;;OAGG;IACH,oBAAoB,IAAI,OAAO;CAGhC"}
|
|
@@ -20,6 +20,8 @@ var PostgresStrategy = class extends BaseDDLStrategy {
|
|
|
20
20
|
*/
|
|
21
21
|
mapType(type) {
|
|
22
22
|
switch (type) {
|
|
23
|
+
case "INTEGER": return "BIGINT";
|
|
24
|
+
case "BLOB": return "BYTEA";
|
|
23
25
|
case "JSON": return "JSONB";
|
|
24
26
|
case "TIMESTAMP": return "TIMESTAMPTZ";
|
|
25
27
|
case "REAL": return "DOUBLE PRECISION";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-strategy.js","names":[],"sources":["../../../src/schema/ddl/postgres-strategy.ts"],"sourcesContent":["/**\n * PostgreSQL DDL Strategy\n *\n * PostgreSQL-specific DDL generation with the following characteristics:\n * - JSONB type for JSON columns (more efficient than JSON)\n * - Native BOOLEAN type\n * - Full trigger support with PL/pgSQL functions\n * - UNIQUE can be inline or separate indexes\n * - Supports CAST in DEFAULT values\n */\n\nimport { shortenIdentifier } from '../index-utils.js';\nimport type { SQLDataType, TriggerDefinition } from '../types.js';\nimport { BaseDDLStrategy } from './base-strategy.js';\nimport type { DatabaseEngine } from './types.js';\n\nexport class PostgresStrategy extends BaseDDLStrategy {\n readonly engine: DatabaseEngine = 'postgres';\n\n /**\n * Map types for PostgreSQL\n * - JSON → JSONB (more efficient, supports indexing)\n * - TIMESTAMP → TIMESTAMP WITH TIME ZONE (best practice)\n */\n mapType(type: SQLDataType): string {\n switch (type) {\n case 'JSON':\n return 'JSONB'; // PostgreSQL JSONB is more efficient\n case 'TIMESTAMP':\n // JavaScript Date represents an instant. Preserve that contract in\n // PostgreSQL instead of discarding the ISO offset in a timezone-naive\n // TIMESTAMP column and reinterpreting the wall time at hydration.\n return 'TIMESTAMPTZ';\n case 'REAL':\n return 'DOUBLE PRECISION'; // PostgreSQL convention\n case 'UUID':\n return 'uuid'; // Native 16-byte uuid (R11) — vs 37-byte text\n default:\n return super.mapType(type);\n }\n }\n\n /**\n * Generate trigger for PostgreSQL\n *\n * PostgreSQL triggers require a separate function, then the trigger.\n * For updated_at timestamps, we generate both.\n */\n protected generateTriggerStatement(\n tableName: string,\n trigger: TriggerDefinition,\n ): string {\n // For simple triggers, we need to create a function first\n // This is PostgreSQL's two-step trigger process\n\n // Check if this is an updated_at trigger\n if (trigger.name.includes('updated_at')) {\n // Generate the function and trigger for updated_at. The function name is\n // a PostgreSQL identifier like any other, so it is subject to the same\n // 63-byte limit — and unlike an index it is *referenced* by the trigger\n // below, so a truncation that CREATE FUNCTION accepts would leave\n // EXECUTE FUNCTION pointing at a name PostgreSQL never stored (#2374).\n const functionName = shortenIdentifier(`update_${tableName}_updated_at`);\n\n let sql = `-- Function for ${trigger.name}\\n`;\n sql += `CREATE OR REPLACE FUNCTION ${functionName}()\\n`;\n sql += `RETURNS TRIGGER AS $$\\n`;\n sql += `BEGIN\\n`;\n sql += ` NEW.updated_at = CURRENT_TIMESTAMP;\\n`;\n sql += ` RETURN NEW;\\n`;\n sql += `END;\\n`;\n sql += `$$ LANGUAGE plpgsql;\\n\\n`;\n\n sql += `-- Trigger\\n`;\n sql += `DROP TRIGGER IF EXISTS \"${trigger.name}\" ON \"${tableName}\";\\n`;\n sql += `CREATE TRIGGER \"${trigger.name}\"\\n`;\n sql += `${trigger.when} ${trigger.event} ON \"${tableName}\"\\n`;\n sql += `FOR EACH ROW\\n`;\n sql += `EXECUTE FUNCTION ${functionName}();`;\n\n return sql;\n }\n\n // For custom triggers, use the provided body\n let sql = `DROP TRIGGER IF EXISTS \"${trigger.name}\" ON \"${tableName}\";\\n`;\n sql += `CREATE TRIGGER \"${trigger.name}\"\\n`;\n sql += `${trigger.when} ${trigger.event} ON \"${tableName}\"\\n`;\n sql += `FOR EACH ROW\\n`;\n\n if (trigger.condition) {\n sql += `WHEN (${trigger.condition})\\n`;\n }\n\n // PostgreSQL triggers need EXECUTE FUNCTION or EXECUTE PROCEDURE\n // If body contains a function call, use it directly\n if (trigger.body.includes('EXECUTE')) {\n sql += trigger.body;\n } else {\n // Wrap in anonymous DO block or assume it's a function name\n sql += `EXECUTE FUNCTION ${trigger.body}`;\n }\n\n return `${sql};`;\n }\n\n /**\n * PostgreSQL supports triggers\n */\n supportsTriggers(): boolean {\n return true;\n }\n\n /**\n * PostgreSQL doesn't require inline UNIQUE for UPSERT\n * Both inline and separate indexes work with ON CONFLICT\n */\n requiresInlineUnique(): boolean {\n return false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,IAAa,mBAAb,cAAsC,gBAAgB;CACpD,SAAkC;;;;;;CAOlC,QAAQ,MAA2B;EACjC,QAAQ,MAAR;GACE,KAAK,QACH,OAAO;GACT,KAAK,aAIH,OAAO;GACT,KAAK,QACH,OAAO;GACT,KAAK,QACH,OAAO;GACT,SACE,OAAO,MAAM,QAAQ,IAAI;EAC7B;CACF;;;;;;;CAQA,yBACE,WACA,SACQ;EAKR,IAAI,QAAQ,KAAK,SAAS,YAAY,GAAG;GAMvC,MAAM,eAAe,kBAAkB,UAAU,UAAU,YAAY;GAEvE,IAAI,MAAM,mBAAmB,QAAQ,KAAK;GAC1C,OAAO,8BAA8B,aAAa;GAClD,OAAO;GACP,OAAO;GACP,OAAO;GACP,OAAO;GACP,OAAO;GACP,OAAO;GAEP,OAAO;GACP,OAAO,2BAA2B,QAAQ,KAAK,QAAQ,UAAU;GACjE,OAAO,mBAAmB,QAAQ,KAAK;GACvC,OAAO,GAAG,QAAQ,KAAK,GAAG,QAAQ,MAAM,OAAO,UAAU;GACzD,OAAO;GACP,OAAO,oBAAoB,aAAa;GAExC,OAAO;EACT;EAGA,IAAI,MAAM,2BAA2B,QAAQ,KAAK,QAAQ,UAAU;EACpE,OAAO,mBAAmB,QAAQ,KAAK;EACvC,OAAO,GAAG,QAAQ,KAAK,GAAG,QAAQ,MAAM,OAAO,UAAU;EACzD,OAAO;EAEP,IAAI,QAAQ,WACV,OAAO,SAAS,QAAQ,UAAU;EAKpC,IAAI,QAAQ,KAAK,SAAS,SAAS,GACjC,OAAO,QAAQ;OAGf,OAAO,oBAAoB,QAAQ;EAGrC,OAAO,GAAG,IAAI;CAChB;;;;CAKA,mBAA4B;EAC1B,OAAO;CACT;;;;;CAMA,uBAAgC;EAC9B,OAAO;CACT;AACF"}
|
|
1
|
+
{"version":3,"file":"postgres-strategy.js","names":[],"sources":["../../../src/schema/ddl/postgres-strategy.ts"],"sourcesContent":["/**\n * PostgreSQL DDL Strategy\n *\n * PostgreSQL-specific DDL generation with the following characteristics:\n * - JSONB type for JSON columns (more efficient than JSON)\n * - Native BOOLEAN type\n * - Full trigger support with PL/pgSQL functions\n * - UNIQUE can be inline or separate indexes\n * - Supports CAST in DEFAULT values\n */\n\nimport { shortenIdentifier } from '../index-utils.js';\nimport type { SQLDataType, TriggerDefinition } from '../types.js';\nimport { BaseDDLStrategy } from './base-strategy.js';\nimport type { DatabaseEngine } from './types.js';\n\nexport class PostgresStrategy extends BaseDDLStrategy {\n readonly engine: DatabaseEngine = 'postgres';\n\n /**\n * Map types for PostgreSQL\n * - JSON → JSONB (more efficient, supports indexing)\n * - TIMESTAMP → TIMESTAMP WITH TIME ZONE (best practice)\n */\n mapType(type: SQLDataType): string {\n switch (type) {\n case 'INTEGER':\n return 'BIGINT';\n case 'BLOB':\n return 'BYTEA';\n case 'JSON':\n return 'JSONB'; // PostgreSQL JSONB is more efficient\n case 'TIMESTAMP':\n // JavaScript Date represents an instant. Preserve that contract in\n // PostgreSQL instead of discarding the ISO offset in a timezone-naive\n // TIMESTAMP column and reinterpreting the wall time at hydration.\n return 'TIMESTAMPTZ';\n case 'REAL':\n return 'DOUBLE PRECISION'; // PostgreSQL convention\n case 'UUID':\n return 'uuid'; // Native 16-byte uuid (R11) — vs 37-byte text\n default:\n return super.mapType(type);\n }\n }\n\n /**\n * Generate trigger for PostgreSQL\n *\n * PostgreSQL triggers require a separate function, then the trigger.\n * For updated_at timestamps, we generate both.\n */\n protected generateTriggerStatement(\n tableName: string,\n trigger: TriggerDefinition,\n ): string {\n // For simple triggers, we need to create a function first\n // This is PostgreSQL's two-step trigger process\n\n // Check if this is an updated_at trigger\n if (trigger.name.includes('updated_at')) {\n // Generate the function and trigger for updated_at. The function name is\n // a PostgreSQL identifier like any other, so it is subject to the same\n // 63-byte limit — and unlike an index it is *referenced* by the trigger\n // below, so a truncation that CREATE FUNCTION accepts would leave\n // EXECUTE FUNCTION pointing at a name PostgreSQL never stored (#2374).\n const functionName = shortenIdentifier(`update_${tableName}_updated_at`);\n\n let sql = `-- Function for ${trigger.name}\\n`;\n sql += `CREATE OR REPLACE FUNCTION ${functionName}()\\n`;\n sql += `RETURNS TRIGGER AS $$\\n`;\n sql += `BEGIN\\n`;\n sql += ` NEW.updated_at = CURRENT_TIMESTAMP;\\n`;\n sql += ` RETURN NEW;\\n`;\n sql += `END;\\n`;\n sql += `$$ LANGUAGE plpgsql;\\n\\n`;\n\n sql += `-- Trigger\\n`;\n sql += `DROP TRIGGER IF EXISTS \"${trigger.name}\" ON \"${tableName}\";\\n`;\n sql += `CREATE TRIGGER \"${trigger.name}\"\\n`;\n sql += `${trigger.when} ${trigger.event} ON \"${tableName}\"\\n`;\n sql += `FOR EACH ROW\\n`;\n sql += `EXECUTE FUNCTION ${functionName}();`;\n\n return sql;\n }\n\n // For custom triggers, use the provided body\n let sql = `DROP TRIGGER IF EXISTS \"${trigger.name}\" ON \"${tableName}\";\\n`;\n sql += `CREATE TRIGGER \"${trigger.name}\"\\n`;\n sql += `${trigger.when} ${trigger.event} ON \"${tableName}\"\\n`;\n sql += `FOR EACH ROW\\n`;\n\n if (trigger.condition) {\n sql += `WHEN (${trigger.condition})\\n`;\n }\n\n // PostgreSQL triggers need EXECUTE FUNCTION or EXECUTE PROCEDURE\n // If body contains a function call, use it directly\n if (trigger.body.includes('EXECUTE')) {\n sql += trigger.body;\n } else {\n // Wrap in anonymous DO block or assume it's a function name\n sql += `EXECUTE FUNCTION ${trigger.body}`;\n }\n\n return `${sql};`;\n }\n\n /**\n * PostgreSQL supports triggers\n */\n supportsTriggers(): boolean {\n return true;\n }\n\n /**\n * PostgreSQL doesn't require inline UNIQUE for UPSERT\n * Both inline and separate indexes work with ON CONFLICT\n */\n requiresInlineUnique(): boolean {\n return false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,IAAa,mBAAb,cAAsC,gBAAgB;CACpD,SAAkC;;;;;;CAOlC,QAAQ,MAA2B;EACjC,QAAQ,MAAR;GACE,KAAK,WACH,OAAO;GACT,KAAK,QACH,OAAO;GACT,KAAK,QACH,OAAO;GACT,KAAK,aAIH,OAAO;GACT,KAAK,QACH,OAAO;GACT,KAAK,QACH,OAAO;GACT,SACE,OAAO,MAAM,QAAQ,IAAI;EAC7B;CACF;;;;;;;CAQA,yBACE,WACA,SACQ;EAKR,IAAI,QAAQ,KAAK,SAAS,YAAY,GAAG;GAMvC,MAAM,eAAe,kBAAkB,UAAU,UAAU,YAAY;GAEvE,IAAI,MAAM,mBAAmB,QAAQ,KAAK;GAC1C,OAAO,8BAA8B,aAAa;GAClD,OAAO;GACP,OAAO;GACP,OAAO;GACP,OAAO;GACP,OAAO;GACP,OAAO;GAEP,OAAO;GACP,OAAO,2BAA2B,QAAQ,KAAK,QAAQ,UAAU;GACjE,OAAO,mBAAmB,QAAQ,KAAK;GACvC,OAAO,GAAG,QAAQ,KAAK,GAAG,QAAQ,MAAM,OAAO,UAAU;GACzD,OAAO;GACP,OAAO,oBAAoB,aAAa;GAExC,OAAO;EACT;EAGA,IAAI,MAAM,2BAA2B,QAAQ,KAAK,QAAQ,UAAU;EACpE,OAAO,mBAAmB,QAAQ,KAAK;EACvC,OAAO,GAAG,QAAQ,KAAK,GAAG,QAAQ,MAAM,OAAO,UAAU;EACzD,OAAO;EAEP,IAAI,QAAQ,WACV,OAAO,SAAS,QAAQ,UAAU;EAKpC,IAAI,QAAQ,KAAK,SAAS,SAAS,GACjC,OAAO,QAAQ;OAGf,OAAO,oBAAoB,QAAQ;EAGrC,OAAO,GAAG,IAAI;CAChB;;;;CAKA,mBAA4B;EAC1B,OAAO;CACT;;;;;CAMA,uBAAgC;EAC9B,OAAO;CACT;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FieldDefinition, FieldMeta, ManifestSchema,
|
|
1
|
+
import { FieldDefinition, FieldMeta, ManifestSchema, SmartObjectManifest } from '../scanner/types.js';
|
|
2
2
|
import { DatabaseEngine } from './ddl/types.js';
|
|
3
3
|
import { DeclaredIndexDefinition, SchemaDefinition } from './types.js';
|
|
4
4
|
/**
|
|
@@ -61,10 +61,6 @@ type SchemaGeneratorConfig = {
|
|
|
61
61
|
};
|
|
62
62
|
};
|
|
63
63
|
export declare class SchemaGenerator {
|
|
64
|
-
/**
|
|
65
|
-
* Generate schema definition from SMRT object definition
|
|
66
|
-
*/
|
|
67
|
-
generateSchema(objectDef: SmartObjectDefinition): SchemaDefinition;
|
|
68
64
|
/**
|
|
69
65
|
* Convert field type to SQL data type
|
|
70
66
|
*/
|
|
@@ -75,10 +71,6 @@ export declare class SchemaGenerator {
|
|
|
75
71
|
private shouldEmitDefault;
|
|
76
72
|
private getRegistryTargetIdColumnType;
|
|
77
73
|
private reconcileRegistryForeignKeyColumnTypes;
|
|
78
|
-
/**
|
|
79
|
-
* Generate column definitions
|
|
80
|
-
*/
|
|
81
|
-
private generateColumns;
|
|
82
74
|
/**
|
|
83
75
|
* Whether an existing index already leads with `leadingColumns`, in order.
|
|
84
76
|
*
|
|
@@ -336,38 +328,14 @@ export declare class SchemaGenerator {
|
|
|
336
328
|
* `unique: true` for that column, in hierarchy order (base first).
|
|
337
329
|
*/
|
|
338
330
|
private emitStiUniqueIndexes;
|
|
339
|
-
/**
|
|
340
|
-
* Generate index definitions
|
|
341
|
-
*/
|
|
342
|
-
private generateIndexes;
|
|
343
|
-
/**
|
|
344
|
-
* Generate trigger definitions for automatic timestamp updates
|
|
345
|
-
*/
|
|
346
|
-
private generateTriggers;
|
|
347
331
|
/**
|
|
348
332
|
* Extract foreign key definitions
|
|
349
333
|
*/
|
|
350
334
|
private extractForeignKeys;
|
|
351
|
-
/**
|
|
352
|
-
* Extract schema dependencies from foreign keys and inheritance
|
|
353
|
-
*/
|
|
354
|
-
private extractDependencies;
|
|
355
|
-
/**
|
|
356
|
-
* Generate version hash for schema
|
|
357
|
-
*/
|
|
358
|
-
private generateVersion;
|
|
359
|
-
/**
|
|
360
|
-
* Get table name from object definition
|
|
361
|
-
*/
|
|
362
|
-
private getTableName;
|
|
363
335
|
/**
|
|
364
336
|
* Convert class name to table name (camelCase to snake_case, pluralized)
|
|
365
337
|
*/
|
|
366
338
|
private classNameToTableName;
|
|
367
|
-
/**
|
|
368
|
-
* Extract package name from file path
|
|
369
|
-
*/
|
|
370
|
-
private extractPackageName;
|
|
371
339
|
/**
|
|
372
340
|
* Generate schema definition from ObjectRegistry fields (runtime)
|
|
373
341
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/schema/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EAGT,cAAc,EACd,
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/schema/generator.ts"],"names":[],"mappings":"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"}
|
package/dist/schema/generator.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { classnameToTablename } from "../utils/naming.js";
|
|
2
2
|
import { formatDefaultValue, quoteIdentifier, quoteStringLiteral } from "./sql-identifiers.js";
|
|
3
|
-
import { assertIdentifierFits, enforceIdentifierLimits
|
|
3
|
+
import { assertIdentifierFits, enforceIdentifierLimits } from "./index-utils.js";
|
|
4
4
|
import { getDDLStrategy } from "./ddl/index.js";
|
|
5
5
|
import { conflictIndexName, resolveConflictColumns, resolveTenantColumn, servesSlugLookup } from "./conflict-target.js";
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
@@ -10,34 +10,6 @@ import { createHash } from "node:crypto";
|
|
|
10
10
|
* Converts AST field definitions to database schema definitions
|
|
11
11
|
*/
|
|
12
12
|
var SchemaGenerator = class {
|
|
13
|
-
/**
|
|
14
|
-
* Generate schema definition from SMRT object definition
|
|
15
|
-
*/
|
|
16
|
-
generateSchema(objectDef) {
|
|
17
|
-
const tableName = this.getTableName(objectDef);
|
|
18
|
-
const columns = this.generateColumns(objectDef.fields, objectDef.decoratorConfig);
|
|
19
|
-
const indexes = this.generateIndexes(objectDef, columns);
|
|
20
|
-
const triggers = this.generateTriggers(objectDef, tableName);
|
|
21
|
-
const foreignKeys = this.extractForeignKeys(columns);
|
|
22
|
-
const dependencies = this.extractDependencies(objectDef, foreignKeys);
|
|
23
|
-
const version = this.generateVersion(objectDef);
|
|
24
|
-
this.ensureDefaultListOrderingIndex(indexes, columns, tableName);
|
|
25
|
-
this.ensurePolymorphicAssociationIndex(indexes, columns, tableName);
|
|
26
|
-
this.ensureReferenceColumnIndexes(indexes, columns, tableName);
|
|
27
|
-
enforceIdentifierLimits(tableName, indexes);
|
|
28
|
-
for (const trigger of triggers) trigger.name = shortenIdentifier(trigger.name);
|
|
29
|
-
return {
|
|
30
|
-
tableName,
|
|
31
|
-
columns,
|
|
32
|
-
indexes,
|
|
33
|
-
triggers,
|
|
34
|
-
foreignKeys,
|
|
35
|
-
dependencies,
|
|
36
|
-
version,
|
|
37
|
-
packageName: this.extractPackageName(objectDef.filePath),
|
|
38
|
-
baseClass: objectDef.extends
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
13
|
/**
|
|
42
14
|
* Convert field type to SQL data type
|
|
43
15
|
*/
|
|
@@ -96,57 +68,6 @@ var SchemaGenerator = class {
|
|
|
96
68
|
}
|
|
97
69
|
}
|
|
98
70
|
/**
|
|
99
|
-
* Generate column definitions
|
|
100
|
-
*/
|
|
101
|
-
generateColumns(fields, config) {
|
|
102
|
-
const columns = {};
|
|
103
|
-
columns.id = {
|
|
104
|
-
type: this.getIdColumnType(config),
|
|
105
|
-
primaryKey: true,
|
|
106
|
-
referenceKind: "id",
|
|
107
|
-
notNull: true,
|
|
108
|
-
description: "Primary identifier"
|
|
109
|
-
};
|
|
110
|
-
columns.created_at = {
|
|
111
|
-
type: "TIMESTAMP",
|
|
112
|
-
notNull: true,
|
|
113
|
-
defaultValue: "current_timestamp",
|
|
114
|
-
description: "Creation timestamp"
|
|
115
|
-
};
|
|
116
|
-
columns.updated_at = {
|
|
117
|
-
type: "TIMESTAMP",
|
|
118
|
-
notNull: true,
|
|
119
|
-
defaultValue: "current_timestamp",
|
|
120
|
-
description: "Last update timestamp"
|
|
121
|
-
};
|
|
122
|
-
for (const [fieldName, fieldDef] of Object.entries(fields)) {
|
|
123
|
-
if (fieldName === "id" || fieldName === "created_at" || fieldName === "updated_at") continue;
|
|
124
|
-
if (fieldDef.transient || fieldDef._meta?.transient) continue;
|
|
125
|
-
if (fieldDef.type === "oneToMany" || fieldDef.type === "manyToMany") continue;
|
|
126
|
-
if (fieldDef.type === "meta") continue;
|
|
127
|
-
const column = {
|
|
128
|
-
type: this.getRelationshipColumnType(fieldDef),
|
|
129
|
-
referenceKind: this.getReferenceKind(fieldDef),
|
|
130
|
-
notNull: fieldDef._meta?.nullable ? false : fieldDef.required || false,
|
|
131
|
-
unique: fieldDef._meta?.unique || false,
|
|
132
|
-
description: fieldDef.description
|
|
133
|
-
};
|
|
134
|
-
if (fieldDef.default !== void 0 && this.shouldEmitDefault(fieldDef, fieldDef.default)) column.defaultValue = fieldDef.default;
|
|
135
|
-
if (fieldDef.type === "foreignKey" && fieldDef.related) {
|
|
136
|
-
const [table, columnName = "id"] = fieldDef.related.split(".");
|
|
137
|
-
column.foreignKey = {
|
|
138
|
-
table,
|
|
139
|
-
column: columnName,
|
|
140
|
-
onDelete: "CASCADE",
|
|
141
|
-
onUpdate: "CASCADE"
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
if (fieldName === "slug" || fieldName === "email") column.unique = true;
|
|
145
|
-
columns[fieldName] = column;
|
|
146
|
-
}
|
|
147
|
-
return columns;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
71
|
* Whether an existing index already leads with `leadingColumns`, in order.
|
|
151
72
|
*
|
|
152
73
|
* Only an UNQUALIFIED index (no partial `WHERE`, no JSON-path expression)
|
|
@@ -553,43 +474,6 @@ var SchemaGenerator = class {
|
|
|
553
474
|
}
|
|
554
475
|
}
|
|
555
476
|
/**
|
|
556
|
-
* Generate index definitions
|
|
557
|
-
*/
|
|
558
|
-
generateIndexes(objectDef, columns) {
|
|
559
|
-
const indexes = [];
|
|
560
|
-
const tableName = this.getTableName(objectDef);
|
|
561
|
-
for (const [columnName, columnDef] of Object.entries(columns)) if (columnDef.foreignKey) indexes.push({
|
|
562
|
-
name: `idx_${tableName}_${columnName}`,
|
|
563
|
-
columns: [columnName],
|
|
564
|
-
description: `Index for foreign key ${columnName}`
|
|
565
|
-
});
|
|
566
|
-
indexes.push({
|
|
567
|
-
name: `idx_${tableName}_updated_at`,
|
|
568
|
-
columns: ["updated_at"],
|
|
569
|
-
description: "Index for timestamp queries"
|
|
570
|
-
});
|
|
571
|
-
for (const [columnName, columnDef] of Object.entries(columns)) if (columnDef.unique && !columnDef.primaryKey) indexes.push({
|
|
572
|
-
name: `idx_${tableName}_${columnName}_unique`,
|
|
573
|
-
columns: [columnName],
|
|
574
|
-
unique: true,
|
|
575
|
-
description: `Unique index for ${columnName}`
|
|
576
|
-
});
|
|
577
|
-
this.appendDeclaredIndexes(indexes, objectDef.decoratorConfig?.indexes, columns, tableName);
|
|
578
|
-
return indexes;
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* Generate trigger definitions for automatic timestamp updates
|
|
582
|
-
*/
|
|
583
|
-
generateTriggers(_objectDef, tableName) {
|
|
584
|
-
return [{
|
|
585
|
-
name: `trg_${tableName}_updated_at`,
|
|
586
|
-
when: "BEFORE",
|
|
587
|
-
event: "UPDATE",
|
|
588
|
-
body: `UPDATE ${quoteIdentifier(tableName)} SET "updated_at" = current_timestamp WHERE "id" = NEW."id";`,
|
|
589
|
-
description: "Automatically update updated_at timestamp"
|
|
590
|
-
}];
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
477
|
* Extract foreign key definitions
|
|
594
478
|
*/
|
|
595
479
|
extractForeignKeys(columns) {
|
|
@@ -604,45 +488,12 @@ var SchemaGenerator = class {
|
|
|
604
488
|
return foreignKeys;
|
|
605
489
|
}
|
|
606
490
|
/**
|
|
607
|
-
* Extract schema dependencies from foreign keys and inheritance
|
|
608
|
-
*/
|
|
609
|
-
extractDependencies(objectDef, foreignKeys) {
|
|
610
|
-
const dependencies = /* @__PURE__ */ new Set();
|
|
611
|
-
for (const fk of foreignKeys) dependencies.add(fk.referencesTable);
|
|
612
|
-
if (objectDef.extends && objectDef.extends !== "SmrtObject" && objectDef.extends !== "SmrtCollection") dependencies.add(this.classNameToTableName(objectDef.extends));
|
|
613
|
-
return Array.from(dependencies);
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Generate version hash for schema
|
|
617
|
-
*/
|
|
618
|
-
generateVersion(objectDef) {
|
|
619
|
-
const content = JSON.stringify({
|
|
620
|
-
className: objectDef.className,
|
|
621
|
-
fields: objectDef.fields,
|
|
622
|
-
extends: objectDef.extends
|
|
623
|
-
});
|
|
624
|
-
return createHash("sha256").update(content).digest("hex").substring(0, 8);
|
|
625
|
-
}
|
|
626
|
-
/**
|
|
627
|
-
* Get table name from object definition
|
|
628
|
-
*/
|
|
629
|
-
getTableName(objectDef) {
|
|
630
|
-
return this.classNameToTableName(objectDef.className);
|
|
631
|
-
}
|
|
632
|
-
/**
|
|
633
491
|
* Convert class name to table name (camelCase to snake_case, pluralized)
|
|
634
492
|
*/
|
|
635
493
|
classNameToTableName(className) {
|
|
636
494
|
return classnameToTablename(className);
|
|
637
495
|
}
|
|
638
496
|
/**
|
|
639
|
-
* Extract package name from file path
|
|
640
|
-
*/
|
|
641
|
-
extractPackageName(filePath) {
|
|
642
|
-
const match = filePath.match(/packages\/([^/]+)/);
|
|
643
|
-
return match ? match[1] : "unknown";
|
|
644
|
-
}
|
|
645
|
-
/**
|
|
646
497
|
* Generate schema definition from ObjectRegistry fields (runtime)
|
|
647
498
|
*
|
|
648
499
|
* This method builds a SchemaDefinition from ObjectRegistry cached fields,
|