@happyvertical/smrt-core 0.40.69 → 0.41.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 +29 -4
- package/README.md +20 -1
- package/agents/change-feed.md +1 -1
- package/agents/query-bounds.md +45 -0
- package/agents/schema-paths.md +786 -0
- package/dist/browser.d.ts +1 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +5 -3
- package/dist/cascade.d.ts +120 -0
- package/dist/cascade.d.ts.map +1 -0
- package/dist/cascade.js +430 -0
- package/dist/cascade.js.map +1 -0
- package/dist/change-feed.d.ts +34 -2
- package/dist/change-feed.d.ts.map +1 -1
- package/dist/change-feed.js +52 -11
- package/dist/change-feed.js.map +1 -1
- package/dist/class.d.ts +36 -3
- package/dist/class.d.ts.map +1 -1
- package/dist/class.js +87 -9
- package/dist/class.js.map +1 -1
- package/dist/collection-cache.js +0 -0
- package/dist/collection-cache.js.map +1 -1
- package/dist/collection.d.ts +130 -2
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +290 -57
- package/dist/collection.js.map +1 -1
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/database.d.ts +8 -0
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +16 -8
- package/dist/database.js.map +1 -1
- package/dist/db-errors.d.ts +105 -0
- package/dist/db-errors.d.ts.map +1 -0
- package/dist/db-errors.js +382 -0
- package/dist/db-errors.js.map +1 -0
- package/dist/decorators/index.d.ts +80 -6
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/index.js +102 -12
- package/dist/decorators/index.js.map +1 -1
- package/dist/dispatch/bus.d.ts.map +1 -1
- package/dist/dispatch/bus.js +4 -3
- package/dist/dispatch/bus.js.map +1 -1
- package/dist/dispatch/collections/Dispatches.d.ts.map +1 -1
- package/dist/dispatch/collections/Dispatches.js +19 -4
- package/dist/dispatch/collections/Dispatches.js.map +1 -1
- package/dist/dispatch/types.d.ts +5 -0
- package/dist/dispatch/types.d.ts.map +1 -1
- package/dist/embedded-write-queue.d.ts +46 -0
- package/dist/embedded-write-queue.d.ts.map +1 -0
- package/dist/embedded-write-queue.js +66 -0
- package/dist/embedded-write-queue.js.map +1 -0
- package/dist/embeddings/storage.d.ts +7 -0
- package/dist/embeddings/storage.d.ts.map +1 -1
- package/dist/embeddings/storage.js +29 -12
- package/dist/embeddings/storage.js.map +1 -1
- package/dist/errors.d.ts +31 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +34 -2
- package/dist/errors.js.map +1 -1
- package/dist/generators/changes-route.d.ts.map +1 -1
- package/dist/generators/changes-route.js +6 -3
- package/dist/generators/changes-route.js.map +1 -1
- package/dist/generators/mcp-runtime-template.d.ts +8 -0
- package/dist/generators/mcp-runtime-template.d.ts.map +1 -1
- package/dist/generators/mcp-runtime-template.js +38 -4
- package/dist/generators/mcp-runtime-template.js.map +1 -1
- package/dist/generators/mcp.d.ts +16 -0
- package/dist/generators/mcp.d.ts.map +1 -1
- package/dist/generators/mcp.js +41 -3
- package/dist/generators/mcp.js.map +1 -1
- package/dist/generators/rest.d.ts +22 -0
- package/dist/generators/rest.d.ts.map +1 -1
- package/dist/generators/rest.js +34 -3
- package/dist/generators/rest.js.map +1 -1
- package/dist/hierarchical.js +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -5
- package/dist/interceptors.d.ts +21 -0
- package/dist/interceptors.d.ts.map +1 -1
- package/dist/interceptors.js +27 -1
- package/dist/interceptors.js.map +1 -1
- package/dist/manifest/generator.d.ts.map +1 -1
- package/dist/manifest/generator.js +4 -7
- package/dist/manifest/generator.js.map +1 -1
- package/dist/manifest/static-manifest.js +10 -10
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest/store.js.map +1 -1
- package/dist/manifest.json +19 -19
- package/dist/migrations/differ.d.ts +211 -9
- package/dist/migrations/differ.d.ts.map +1 -1
- package/dist/migrations/differ.js +613 -50
- package/dist/migrations/differ.js.map +1 -1
- package/dist/migrations/generator.d.ts +31 -4
- package/dist/migrations/generator.d.ts.map +1 -1
- package/dist/migrations/generator.js +49 -5
- package/dist/migrations/generator.js.map +1 -1
- package/dist/migrations/index.d.ts +4 -2
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +6 -3
- package/dist/migrations/minor-units.d.ts +162 -0
- package/dist/migrations/minor-units.d.ts.map +1 -0
- package/dist/migrations/minor-units.js +381 -0
- package/dist/migrations/minor-units.js.map +1 -0
- package/dist/migrations/orchestrate.js +35 -6
- package/dist/migrations/orchestrate.js.map +1 -1
- package/dist/migrations/sqlite-rebuild.d.ts +142 -0
- package/dist/migrations/sqlite-rebuild.d.ts.map +1 -0
- package/dist/migrations/sqlite-rebuild.js +514 -0
- package/dist/migrations/sqlite-rebuild.js.map +1 -0
- package/dist/migrations/tracker.d.ts +114 -1
- package/dist/migrations/tracker.d.ts.map +1 -1
- package/dist/migrations/tracker.js +331 -16
- package/dist/migrations/tracker.js.map +1 -1
- package/dist/migrations/types.d.ts +19 -4
- package/dist/migrations/types.d.ts.map +1 -1
- package/dist/migrations.js +6 -3
- package/dist/object.d.ts +142 -10
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +196 -41
- package/dist/object.js.map +1 -1
- package/dist/postgres-timeouts.d.ts +240 -0
- package/dist/postgres-timeouts.d.ts.map +1 -0
- package/dist/postgres-timeouts.js +204 -0
- package/dist/postgres-timeouts.js.map +1 -0
- package/dist/query-bounds.d.ts +101 -0
- package/dist/query-bounds.d.ts.map +1 -0
- package/dist/query-bounds.js +177 -0
- package/dist/query-bounds.js.map +1 -0
- package/dist/registry/class-registration.d.ts.map +1 -1
- package/dist/registry/class-registration.js +3 -1
- package/dist/registry/class-registration.js.map +1 -1
- package/dist/registry/manifest-field-merge.d.ts +12 -0
- package/dist/registry/manifest-field-merge.d.ts.map +1 -1
- package/dist/registry/manifest-field-merge.js +14 -2
- package/dist/registry/manifest-field-merge.js.map +1 -1
- package/dist/registry/schema-builder.d.ts +22 -1
- package/dist/registry/schema-builder.d.ts.map +1 -1
- package/dist/registry/schema-builder.js +205 -165
- package/dist/registry/schema-builder.js.map +1 -1
- package/dist/registry/types.d.ts +35 -3
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry.d.ts +41 -46
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +61 -83
- package/dist/registry.js.map +1 -1
- package/dist/scanner/manifest-generator.d.ts +45 -0
- package/dist/scanner/manifest-generator.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.js +92 -28
- package/dist/scanner/manifest-generator.js.map +1 -1
- package/dist/scanner/types.d.ts +5 -0
- package/dist/scanner/types.d.ts.map +1 -1
- package/dist/scanner/types.js.map +1 -1
- package/dist/schema/conflict-target.d.ts +104 -0
- package/dist/schema/conflict-target.d.ts.map +1 -0
- package/dist/schema/conflict-target.js +129 -0
- package/dist/schema/conflict-target.js.map +1 -0
- package/dist/schema/ddl/base-strategy.d.ts.map +1 -1
- package/dist/schema/ddl/base-strategy.js +2 -2
- package/dist/schema/ddl/base-strategy.js.map +1 -1
- package/dist/schema/ddl/duckdb-strategy.d.ts.map +1 -1
- package/dist/schema/ddl/duckdb-strategy.js +2 -1
- 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 +12 -1
- package/dist/schema/ddl/postgres-strategy.js.map +1 -1
- package/dist/schema/generator.d.ts +307 -6
- package/dist/schema/generator.d.ts.map +1 -1
- package/dist/schema/generator.js +510 -87
- package/dist/schema/generator.js.map +1 -1
- package/dist/schema/index-utils.d.ts +120 -0
- package/dist/schema/index-utils.d.ts.map +1 -1
- package/dist/schema/index-utils.js +242 -1
- package/dist/schema/index-utils.js.map +1 -1
- package/dist/schema/index.d.ts +3 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +4 -1
- package/dist/schema/live-parity.d.ts +90 -0
- package/dist/schema/live-parity.d.ts.map +1 -0
- package/dist/schema/live-parity.js +602 -0
- package/dist/schema/live-parity.js.map +1 -0
- package/dist/schema/manifest-schema.d.ts +121 -0
- package/dist/schema/manifest-schema.d.ts.map +1 -0
- package/dist/schema/manifest-schema.js +267 -0
- package/dist/schema/manifest-schema.js.map +1 -0
- package/dist/schema/schema-aggregator.d.ts +24 -10
- package/dist/schema/schema-aggregator.d.ts.map +1 -1
- package/dist/schema/schema-aggregator.js +35 -90
- package/dist/schema/schema-aggregator.js.map +1 -1
- package/dist/schema/system-table-shapes.d.ts +65 -0
- package/dist/schema/system-table-shapes.d.ts.map +1 -0
- package/dist/schema/system-table-shapes.js +187 -0
- package/dist/schema/system-table-shapes.js.map +1 -0
- package/dist/schema/types.d.ts +103 -4
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/utils.d.ts +2 -1
- package/dist/schema/utils.d.ts.map +1 -1
- package/dist/schema/utils.js +5 -3
- package/dist/schema/utils.js.map +1 -1
- package/dist/schema.js +4 -1
- package/dist/smrt-knowledge.json +20 -8
- package/dist/sync/apply.d.ts.map +1 -1
- package/dist/sync/apply.js +9 -16
- package/dist/sync/apply.js.map +1 -1
- package/dist/system/compatibility.d.ts +42 -0
- package/dist/system/compatibility.d.ts.map +1 -1
- package/dist/system/compatibility.js +182 -9
- package/dist/system/compatibility.js.map +1 -1
- package/dist/system/index.d.ts +1 -0
- package/dist/system/index.d.ts.map +1 -1
- package/dist/system/index.js +3 -2
- package/dist/system/retention.d.ts +237 -0
- package/dist/system/retention.d.ts.map +1 -0
- package/dist/system/retention.js +497 -0
- package/dist/system/retention.js.map +1 -0
- package/dist/system/schema.d.ts +100 -15
- package/dist/system/schema.d.ts.map +1 -1
- package/dist/system/schema.js +81 -45
- package/dist/system/schema.js.map +1 -1
- package/dist/system/types.d.ts +0 -2
- package/dist/system/types.d.ts.map +1 -1
- package/dist/testing/database.d.ts.map +1 -1
- package/dist/testing/database.js +1 -0
- package/dist/testing/database.js.map +1 -1
- package/dist/vite-plugin/index.d.ts.map +1 -1
- package/dist/vite-plugin/index.js +4 -9
- package/dist/vite-plugin/index.js.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.js +71 -5
- package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
- package/dist/vite-plugin/web-collections.d.ts.map +1 -1
- package/dist/vite-plugin/web-collections.js +6 -4
- package/dist/vite-plugin/web-collections.js.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-builder.d.ts","sourceRoot":"","sources":["../../src/registry/schema-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"schema-builder.d.ts","sourceRoot":"","sources":["../../src/registry/schema-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAM7D,OAAO,KAAK,EACV,gBAAgB,EAEhB,gBAAgB,EAChB,WAAW,EACZ,MAAM,oBAAoB,CAAC;AAmL5B;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAIpE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,cAAc,GACtB,MAAM,GAAG,SAAS,CAWpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAkB7D;AAwTD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAC3B,MAAM,CAAC,EAAE,cAAc,GACtB,MAAM,CAAC,MAAM,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAmFxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAsC7E;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACzC,KAAK,UAAQ,EACb,MAAM,CAAC,EAAE,cAAc,GACtB,MAAM,CAwDR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACpC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAwFlC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,eAAe,CAAC,MAAM,CAAC,GACjC,WAAW,CAqBb"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { classnameToTablename, toSnakeCase } from "../utils/naming.js";
|
|
1
2
|
import { formatDefaultValue as formatDefaultValue$1, quoteIdentifier } from "../schema/sql-identifiers.js";
|
|
3
|
+
import { shortenIdentifier } from "../schema/index-utils.js";
|
|
2
4
|
import { getDDLStrategy } from "../schema/ddl/index.js";
|
|
3
5
|
import { getClasses, getCollectionTableNames } from "./shared-state.js";
|
|
4
6
|
import { findClass } from "./name-resolver.js";
|
|
5
|
-
import {
|
|
7
|
+
import { conflictIndexName } from "../schema/conflict-target.js";
|
|
6
8
|
import "../utils.js";
|
|
9
|
+
import { readFieldAttribute } from "./manifest-field-merge.js";
|
|
7
10
|
import { isCollectionRegistration } from "./collection-resolution.js";
|
|
8
11
|
import { ObjectRegistry } from "../registry.js";
|
|
9
12
|
//#region src/registry/schema-builder.ts
|
|
@@ -34,10 +37,10 @@ function applyDecoratorSqlTypeOverrides(className, columns) {
|
|
|
34
37
|
}
|
|
35
38
|
return columns;
|
|
36
39
|
}
|
|
37
|
-
function mergeRuntimeFieldColumns(className, schemaColumns, fields) {
|
|
40
|
+
function mergeRuntimeFieldColumns(className, schemaColumns, fields, options) {
|
|
38
41
|
const columnsToUse = { ...schemaColumns || {} };
|
|
39
42
|
if (fields.size > 0) {
|
|
40
|
-
const fieldColumns = fieldsToColumns(fields);
|
|
43
|
+
const fieldColumns = fieldsToColumns(fields, options);
|
|
41
44
|
for (const [columnName, columnDef] of Object.entries(fieldColumns)) if (!columnsToUse[columnName]) columnsToUse[columnName] = columnDef;
|
|
42
45
|
for (const [fieldName, fieldDef] of fields) {
|
|
43
46
|
const columnName = toSnakeCase(fieldName);
|
|
@@ -60,24 +63,58 @@ function getReferenceKind(fieldDef) {
|
|
|
60
63
|
if (fieldDef.type === "foreignKey") return "foreignKey";
|
|
61
64
|
if (fieldDef.type === "crossPackageRef") return "crossPackageRef";
|
|
62
65
|
}
|
|
63
|
-
function shouldEmitDefault(fieldDef, sqlType) {
|
|
64
|
-
return !(getReferenceKind(fieldDef) === "tenantId" && sqlType === "UUID" &&
|
|
66
|
+
function shouldEmitDefault(fieldDef, sqlType, defaultValue) {
|
|
67
|
+
return !(getReferenceKind(fieldDef) === "tenantId" && sqlType === "UUID" && defaultValue === "");
|
|
65
68
|
}
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Fallback base columns for a table whose contributing class carries no
|
|
71
|
+
* manifest columns.
|
|
72
|
+
*
|
|
73
|
+
* These mirror what the manifest schema generators emit for the same table
|
|
74
|
+
* (`generateSchemaFromManifest` / `generateSTISchemaFromManifest`), so a table
|
|
75
|
+
* assembled from runtime field metadata alone has the same NOT NULL and
|
|
76
|
+
* DEFAULT shape as one assembled from a manifest. Divergence here is what made
|
|
77
|
+
* the merged table shape depend on which class registered first (#2372).
|
|
78
|
+
*/
|
|
79
|
+
function createBaseColumns(registered, isSTI) {
|
|
80
|
+
const baseColumns = {
|
|
68
81
|
id: {
|
|
69
82
|
type: registered.config?.idType === "text" ? "TEXT" : "UUID",
|
|
70
83
|
primaryKey: true,
|
|
84
|
+
notNull: true,
|
|
71
85
|
referenceKind: "id"
|
|
72
86
|
},
|
|
73
87
|
slug: {
|
|
74
88
|
type: "TEXT",
|
|
75
89
|
notNull: true
|
|
76
90
|
},
|
|
77
|
-
context: {
|
|
78
|
-
|
|
79
|
-
|
|
91
|
+
context: {
|
|
92
|
+
type: "TEXT",
|
|
93
|
+
notNull: true,
|
|
94
|
+
defaultValue: ""
|
|
95
|
+
},
|
|
96
|
+
created_at: {
|
|
97
|
+
type: "TIMESTAMP",
|
|
98
|
+
notNull: true,
|
|
99
|
+
defaultValue: "current_timestamp"
|
|
100
|
+
},
|
|
101
|
+
updated_at: {
|
|
102
|
+
type: "TIMESTAMP",
|
|
103
|
+
notNull: true,
|
|
104
|
+
defaultValue: "current_timestamp"
|
|
105
|
+
}
|
|
80
106
|
};
|
|
107
|
+
if (isSTI) {
|
|
108
|
+
baseColumns._meta_type = {
|
|
109
|
+
type: "TEXT",
|
|
110
|
+
notNull: true
|
|
111
|
+
};
|
|
112
|
+
baseColumns._meta_data = {
|
|
113
|
+
type: "JSON",
|
|
114
|
+
notNull: false
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return baseColumns;
|
|
81
118
|
}
|
|
82
119
|
/**
|
|
83
120
|
* Get cached schema definition for a registered class
|
|
@@ -139,14 +176,151 @@ function getTableName(name) {
|
|
|
139
176
|
}
|
|
140
177
|
function withConflictIndex(tableName, columns, indexes, conflictColumns) {
|
|
141
178
|
if (conflictColumns.length === 0 || !conflictColumns.every((column) => columns[column])) return indexes;
|
|
179
|
+
const primaryKeyColumns = Object.entries(columns).filter(([, column]) => column.primaryKey === true).map(([name]) => name);
|
|
180
|
+
if (primaryKeyColumns.length > 0 && primaryKeyColumns.length === conflictColumns.length && primaryKeyColumns.every((column) => conflictColumns.includes(column))) return indexes;
|
|
142
181
|
if (indexes.some((index) => index.unique === true && !index.where && !index.jsonPath && index.columns.length === conflictColumns.length && index.columns.every((column) => conflictColumns.includes(column)))) return indexes;
|
|
143
|
-
const
|
|
144
|
-
const name =
|
|
145
|
-
|
|
182
|
+
const tenantColumn = Object.entries(columns).find(([, column]) => column.referenceKind === "tenantId")?.[0];
|
|
183
|
+
const name = shortenIdentifier(conflictIndexName(tableName, conflictColumns, tenantColumn));
|
|
184
|
+
const conflictIndex = {
|
|
146
185
|
name,
|
|
147
186
|
columns: conflictColumns,
|
|
148
187
|
unique: true
|
|
149
|
-
}
|
|
188
|
+
};
|
|
189
|
+
if (indexes.some((index) => index.name === name)) return indexes.map((index) => index.name === name ? conflictIndex : index);
|
|
190
|
+
return [...indexes, conflictIndex];
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Resolve the physical table a registered class writes to.
|
|
194
|
+
*
|
|
195
|
+
* STI subclasses are folded onto their base's table. Returns `undefined` when
|
|
196
|
+
* the class has no table (for example an unresolvable manifest stub).
|
|
197
|
+
*
|
|
198
|
+
* R5-canon: STI lookups use the qualified key so a colliding simple name in
|
|
199
|
+
* another package cannot yield the wrong table strategy or STI base and move
|
|
200
|
+
* this class's columns under that other package's table.
|
|
201
|
+
*/
|
|
202
|
+
function resolveContributorTable(registered, fallbackName) {
|
|
203
|
+
const simpleName = registered.name || fallbackName;
|
|
204
|
+
const qualifiedName = registered.qualifiedName ?? simpleName;
|
|
205
|
+
if (!registered.schema?.tableName && registered.extends) {
|
|
206
|
+
if (ObjectRegistry.getTableStrategy(qualifiedName) === "sti") {
|
|
207
|
+
const stiBaseName = ObjectRegistry.getSTIBase(qualifiedName);
|
|
208
|
+
if (stiBaseName && stiBaseName !== qualifiedName) {
|
|
209
|
+
const stiBaseClass = findClass(stiBaseName);
|
|
210
|
+
if (stiBaseClass?.schema?.tableName) {
|
|
211
|
+
if (!registered.schema) registered.schema = {
|
|
212
|
+
tableName: "",
|
|
213
|
+
ddl: "",
|
|
214
|
+
columns: {},
|
|
215
|
+
indexes: [],
|
|
216
|
+
triggers: [],
|
|
217
|
+
foreignKeys: [],
|
|
218
|
+
dependencies: [],
|
|
219
|
+
version: ""
|
|
220
|
+
};
|
|
221
|
+
registered.schema.tableName = stiBaseClass.schema.tableName;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!registered.schema?.tableName) return;
|
|
227
|
+
let tableName = registered.schema.tableName;
|
|
228
|
+
const isSTI = ObjectRegistry.getTableStrategy(qualifiedName) === "sti";
|
|
229
|
+
let isSTIBase = isSTI;
|
|
230
|
+
let conflictKey = qualifiedName;
|
|
231
|
+
if (isSTI) {
|
|
232
|
+
const stiBaseName = ObjectRegistry.getSTIBase(qualifiedName);
|
|
233
|
+
if (stiBaseName) {
|
|
234
|
+
conflictKey = stiBaseName;
|
|
235
|
+
if (stiBaseName !== qualifiedName) {
|
|
236
|
+
isSTIBase = false;
|
|
237
|
+
const stiBaseClass = findClass(stiBaseName);
|
|
238
|
+
if (stiBaseClass?.schema?.tableName) tableName = stiBaseClass.schema.tableName;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
tableName,
|
|
244
|
+
contributor: {
|
|
245
|
+
registered,
|
|
246
|
+
simpleName,
|
|
247
|
+
qualifiedName,
|
|
248
|
+
isSTI,
|
|
249
|
+
isSTIBase,
|
|
250
|
+
depth: ObjectRegistry.getInheritanceChain(qualifiedName).length,
|
|
251
|
+
conflictKey
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Order the classes that share one table deterministically.
|
|
257
|
+
*
|
|
258
|
+
* The first contributor seeds the table: it supplies the base columns, the
|
|
259
|
+
* `idType`, the conflict columns and the cached DDL, and its columns win every
|
|
260
|
+
* merge conflict. Registration order must not decide that, or the same
|
|
261
|
+
* hierarchy yields a different table shape depending on which class a manifest
|
|
262
|
+
* happens to list first — child-first dropped NOT NULL and DEFAULT from the
|
|
263
|
+
* base columns (#2372).
|
|
264
|
+
*
|
|
265
|
+
* Order: the STI base first, then ancestors before descendants, then by
|
|
266
|
+
* qualified name so the result is a total order.
|
|
267
|
+
*/
|
|
268
|
+
function sortTableContributors(contributors) {
|
|
269
|
+
return [...contributors].sort((a, b) => {
|
|
270
|
+
if (a.isSTIBase !== b.isSTIBase) return a.isSTIBase ? -1 : 1;
|
|
271
|
+
if (a.depth !== b.depth) return a.depth - b.depth;
|
|
272
|
+
return a.qualifiedName.localeCompare(b.qualifiedName);
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Assemble every physical table from the classes that contribute to it.
|
|
277
|
+
*
|
|
278
|
+
* Shared by {@link getAllSchemas} and {@link getAllSchemasAsDefinitions} so
|
|
279
|
+
* both produce the same merged shape. The result depends only on what is
|
|
280
|
+
* registered, never on the order it was registered in.
|
|
281
|
+
*/
|
|
282
|
+
function buildMergedTableSchemas() {
|
|
283
|
+
const contributorsByTable = /* @__PURE__ */ new Map();
|
|
284
|
+
for (const [className, registered] of getClasses()) {
|
|
285
|
+
if (isCollectionRegistration(className, registered, collectionRegistrationLookup)) continue;
|
|
286
|
+
const resolved = resolveContributorTable(registered, className);
|
|
287
|
+
if (!resolved) continue;
|
|
288
|
+
const existing = contributorsByTable.get(resolved.tableName);
|
|
289
|
+
if (existing) existing.push(resolved.contributor);
|
|
290
|
+
else contributorsByTable.set(resolved.tableName, [resolved.contributor]);
|
|
291
|
+
}
|
|
292
|
+
const tableSchemas = {};
|
|
293
|
+
for (const [tableName, contributors] of contributorsByTable) for (const contributor of sortTableContributors(contributors)) {
|
|
294
|
+
const { registered, simpleName, isSTI } = contributor;
|
|
295
|
+
const columnsToUse = mergeRuntimeFieldColumns(simpleName, registered.schema?.columns, registered.fields, { stiUnionColumns: isSTI });
|
|
296
|
+
let tableSchema = tableSchemas[tableName];
|
|
297
|
+
if (!tableSchema) {
|
|
298
|
+
tableSchema = {
|
|
299
|
+
tableName,
|
|
300
|
+
columns: {
|
|
301
|
+
...createBaseColumns(registered, isSTI),
|
|
302
|
+
...columnsToUse
|
|
303
|
+
},
|
|
304
|
+
indexes: [],
|
|
305
|
+
ddl: registered.schema?.ddl || "",
|
|
306
|
+
isSTI,
|
|
307
|
+
conflictColumns: ObjectRegistry.getConflictColumns(contributor.conflictKey)
|
|
308
|
+
};
|
|
309
|
+
tableSchemas[tableName] = tableSchema;
|
|
310
|
+
} else for (const [colName, colDef] of Object.entries(columnsToUse)) if (!tableSchema.columns[colName]) tableSchema.columns[colName] = colDef;
|
|
311
|
+
const schemaIndexes = registered.schema?.indexes;
|
|
312
|
+
if (schemaIndexes && schemaIndexes.length > 0) {
|
|
313
|
+
const existingNames = new Set(tableSchema.indexes.map((index) => index.name));
|
|
314
|
+
for (const index of schemaIndexes) {
|
|
315
|
+
if (typeof index === "string") continue;
|
|
316
|
+
if (!existingNames.has(index.name)) {
|
|
317
|
+
tableSchema.indexes.push(index);
|
|
318
|
+
existingNames.add(index.name);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return tableSchemas;
|
|
150
324
|
}
|
|
151
325
|
/**
|
|
152
326
|
* Get all pre-generated schemas for explicit adapter bootstrap paths.
|
|
@@ -164,81 +338,7 @@ function withConflictIndex(tableName, columns, indexes, conflictColumns) {
|
|
|
164
338
|
* ```
|
|
165
339
|
*/
|
|
166
340
|
function getAllSchemas(engine) {
|
|
167
|
-
const tableSchemas =
|
|
168
|
-
for (const [_className, registered] of getClasses()) {
|
|
169
|
-
if (isCollectionRegistration(_className, registered, collectionRegistrationLookup)) continue;
|
|
170
|
-
const simpleName = registered.name || _className;
|
|
171
|
-
if (!registered.schema?.tableName && registered.extends) {
|
|
172
|
-
const qualifiedName = registered.qualifiedName ?? simpleName;
|
|
173
|
-
const lookupKey = qualifiedName;
|
|
174
|
-
if (ObjectRegistry.getTableStrategy(lookupKey) === "sti") {
|
|
175
|
-
const stiBaseName = ObjectRegistry.getSTIBase(lookupKey);
|
|
176
|
-
if (stiBaseName && stiBaseName !== qualifiedName) {
|
|
177
|
-
const stiBaseClass = findClass(stiBaseName);
|
|
178
|
-
if (stiBaseClass?.schema?.tableName) {
|
|
179
|
-
if (!registered.schema) registered.schema = {
|
|
180
|
-
tableName: "",
|
|
181
|
-
ddl: "",
|
|
182
|
-
columns: {},
|
|
183
|
-
indexes: [],
|
|
184
|
-
triggers: [],
|
|
185
|
-
foreignKeys: [],
|
|
186
|
-
dependencies: [],
|
|
187
|
-
version: ""
|
|
188
|
-
};
|
|
189
|
-
registered.schema.tableName = stiBaseClass.schema.tableName;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
if (registered.schema?.tableName) {
|
|
195
|
-
let tableName = registered.schema.tableName;
|
|
196
|
-
const qualifiedName = registered.qualifiedName ?? simpleName;
|
|
197
|
-
const lookupKey = qualifiedName;
|
|
198
|
-
const tableStrategy = ObjectRegistry.getTableStrategy(lookupKey);
|
|
199
|
-
if (tableStrategy === "sti") {
|
|
200
|
-
const stiBaseName = ObjectRegistry.getSTIBase(lookupKey);
|
|
201
|
-
if (stiBaseName && stiBaseName !== qualifiedName) {
|
|
202
|
-
const stiBaseClass = findClass(stiBaseName);
|
|
203
|
-
if (stiBaseClass?.schema?.tableName) tableName = stiBaseClass.schema.tableName;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
const columnsToUse = mergeRuntimeFieldColumns(simpleName, registered.schema.columns, registered.fields);
|
|
207
|
-
if (!tableSchemas[tableName]) {
|
|
208
|
-
const baseColumns = createBaseColumns(registered);
|
|
209
|
-
const isSTI = tableStrategy === "sti";
|
|
210
|
-
if (isSTI) {
|
|
211
|
-
baseColumns._meta_type = {
|
|
212
|
-
type: "TEXT",
|
|
213
|
-
notNull: true,
|
|
214
|
-
defaultValue: ""
|
|
215
|
-
};
|
|
216
|
-
baseColumns._meta_data = { type: "JSON" };
|
|
217
|
-
}
|
|
218
|
-
tableSchemas[tableName] = {
|
|
219
|
-
tableName,
|
|
220
|
-
columns: {
|
|
221
|
-
...baseColumns,
|
|
222
|
-
...columnsToUse
|
|
223
|
-
},
|
|
224
|
-
indexes: [],
|
|
225
|
-
ddl: registered.schema.ddl || "",
|
|
226
|
-
isSTI,
|
|
227
|
-
conflictColumns: ObjectRegistry.getConflictColumns(isSTI ? ObjectRegistry.getSTIBase(lookupKey) || lookupKey : lookupKey)
|
|
228
|
-
};
|
|
229
|
-
} else for (const [colName, colDef] of Object.entries(columnsToUse)) if (!tableSchemas[tableName].columns[colName]) tableSchemas[tableName].columns[colName] = colDef;
|
|
230
|
-
if (registered.schema.indexes && registered.schema.indexes.length > 0) {
|
|
231
|
-
const existingNames = new Set(tableSchemas[tableName].indexes.map((idx) => typeof idx === "string" ? idx : idx.name));
|
|
232
|
-
for (const idx of registered.schema.indexes) {
|
|
233
|
-
const indexName = typeof idx === "string" ? idx : idx.name;
|
|
234
|
-
if (!existingNames.has(indexName)) if (typeof idx === "string") {} else {
|
|
235
|
-
tableSchemas[tableName].indexes.push(idx);
|
|
236
|
-
existingNames.add(idx.name);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
341
|
+
const tableSchemas = buildMergedTableSchemas();
|
|
242
342
|
const schemas = {};
|
|
243
343
|
for (const [tableName, tableSchema] of Object.entries(tableSchemas)) {
|
|
244
344
|
const engineIndexes = engine ? withConflictIndex(tableName, tableSchema.columns, tableSchema.indexes, tableSchema.conflictColumns) : tableSchema.indexes;
|
|
@@ -285,77 +385,7 @@ function getAllSchemas(engine) {
|
|
|
285
385
|
* @returns Map of tableName to SchemaDefinition
|
|
286
386
|
*/
|
|
287
387
|
function getAllSchemasAsDefinitions() {
|
|
288
|
-
const tableSchemas =
|
|
289
|
-
for (const [_className, registered] of getClasses()) {
|
|
290
|
-
if (isCollectionRegistration(_className, registered, collectionRegistrationLookup)) continue;
|
|
291
|
-
const simpleName = registered.name || _className;
|
|
292
|
-
if (!registered.schema?.tableName && registered.extends) {
|
|
293
|
-
const qualifiedName = registered.qualifiedName ?? simpleName;
|
|
294
|
-
const lookupKey = qualifiedName;
|
|
295
|
-
if (ObjectRegistry.getTableStrategy(lookupKey) === "sti") {
|
|
296
|
-
const stiBaseName = ObjectRegistry.getSTIBase(lookupKey);
|
|
297
|
-
if (stiBaseName && stiBaseName !== qualifiedName) {
|
|
298
|
-
const stiBaseClass = findClass(stiBaseName);
|
|
299
|
-
if (stiBaseClass?.schema?.tableName) {
|
|
300
|
-
if (!registered.schema) registered.schema = {
|
|
301
|
-
tableName: "",
|
|
302
|
-
ddl: "",
|
|
303
|
-
columns: {},
|
|
304
|
-
indexes: [],
|
|
305
|
-
triggers: [],
|
|
306
|
-
foreignKeys: [],
|
|
307
|
-
dependencies: [],
|
|
308
|
-
version: ""
|
|
309
|
-
};
|
|
310
|
-
registered.schema.tableName = stiBaseClass.schema.tableName;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
if (registered.schema?.tableName) {
|
|
316
|
-
let tableName = registered.schema.tableName;
|
|
317
|
-
const qualifiedName = registered.qualifiedName ?? simpleName;
|
|
318
|
-
const lookupKey = qualifiedName;
|
|
319
|
-
const tableStrategy = ObjectRegistry.getTableStrategy(lookupKey);
|
|
320
|
-
if (tableStrategy === "sti") {
|
|
321
|
-
const stiBaseName = ObjectRegistry.getSTIBase(lookupKey);
|
|
322
|
-
if (stiBaseName && stiBaseName !== qualifiedName) {
|
|
323
|
-
const stiBaseClass = findClass(stiBaseName);
|
|
324
|
-
if (stiBaseClass?.schema?.tableName) tableName = stiBaseClass.schema.tableName;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
const columnsToUse = mergeRuntimeFieldColumns(simpleName, registered.schema.columns, registered.fields);
|
|
328
|
-
if (!tableSchemas[tableName]) {
|
|
329
|
-
const baseColumns = createBaseColumns(registered);
|
|
330
|
-
const isSTI = tableStrategy === "sti";
|
|
331
|
-
if (isSTI) {
|
|
332
|
-
baseColumns._meta_type = {
|
|
333
|
-
type: "TEXT",
|
|
334
|
-
notNull: true,
|
|
335
|
-
defaultValue: ""
|
|
336
|
-
};
|
|
337
|
-
baseColumns._meta_data = { type: "JSON" };
|
|
338
|
-
}
|
|
339
|
-
tableSchemas[tableName] = {
|
|
340
|
-
tableName,
|
|
341
|
-
columns: {
|
|
342
|
-
...baseColumns,
|
|
343
|
-
...columnsToUse
|
|
344
|
-
},
|
|
345
|
-
indexes: [],
|
|
346
|
-
isSTI,
|
|
347
|
-
conflictColumns: ObjectRegistry.getConflictColumns(isSTI ? ObjectRegistry.getSTIBase(lookupKey) || lookupKey : lookupKey)
|
|
348
|
-
};
|
|
349
|
-
} else for (const [colName, colDef] of Object.entries(columnsToUse)) if (!tableSchemas[tableName].columns[colName]) tableSchemas[tableName].columns[colName] = colDef;
|
|
350
|
-
if (registered.schema.indexes && registered.schema.indexes.length > 0) {
|
|
351
|
-
const existingNames = new Set(tableSchemas[tableName].indexes.map((idx) => idx.name));
|
|
352
|
-
for (const idx of registered.schema.indexes) if (!existingNames.has(idx.name)) {
|
|
353
|
-
tableSchemas[tableName].indexes.push(idx);
|
|
354
|
-
existingNames.add(idx.name);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|
|
388
|
+
const tableSchemas = buildMergedTableSchemas();
|
|
359
389
|
const schemas = {};
|
|
360
390
|
for (const [tableName, tableSchema] of Object.entries(tableSchemas)) {
|
|
361
391
|
if (Object.keys(tableSchema.columns).length === 0) continue;
|
|
@@ -427,11 +457,17 @@ function formatDefaultValue(value, type) {
|
|
|
427
457
|
* Used by getAllSchemas() to generate columns from fields when a class
|
|
428
458
|
* has no pre-generated schema (e.g., STI subclasses registered from manifest).
|
|
429
459
|
*
|
|
460
|
+
* `required`, `default`, and `description` are read from either the top level
|
|
461
|
+
* or `_meta`: registry-sourced fields normalize them into `_meta`, so reading
|
|
462
|
+
* only the top level dropped NOT NULL and DEFAULT for every such field
|
|
463
|
+
* (#2372).
|
|
464
|
+
*
|
|
430
465
|
* @param fields - Map of field name to field definition
|
|
466
|
+
* @param options - Table-shape options (see {@link FieldsToColumnsOptions})
|
|
431
467
|
* @returns Record of column name to column definition
|
|
432
468
|
* @private
|
|
433
469
|
*/
|
|
434
|
-
function fieldsToColumns(fields) {
|
|
470
|
+
function fieldsToColumns(fields, options) {
|
|
435
471
|
const columns = {};
|
|
436
472
|
for (const [fieldName, fieldDef] of fields) {
|
|
437
473
|
if (fieldName === "id" || fieldName === "created_at" || fieldName === "updated_at" || fieldName === "slug" || fieldName === "context") continue;
|
|
@@ -440,14 +476,18 @@ function fieldsToColumns(fields) {
|
|
|
440
476
|
if (fieldDef.type === "meta") continue;
|
|
441
477
|
const sqlType = fieldDef._meta?.sqlType || (fieldDef.type === "crossPackageRef" && (fieldDef._meta?.idType === "text" || fieldDef.idType === "text") ? "TEXT" : mapFieldTypeToSQL(fieldDef.type));
|
|
442
478
|
const normalizedSqlType = String(sqlType).toUpperCase();
|
|
479
|
+
const referenceKind = getReferenceKind(fieldDef);
|
|
480
|
+
const required = readFieldAttribute(fieldDef, "required");
|
|
481
|
+
const defaultValue = readFieldAttribute(fieldDef, "default");
|
|
482
|
+
const description = readFieldAttribute(fieldDef, "description");
|
|
443
483
|
const column = {
|
|
444
484
|
type: normalizedSqlType,
|
|
445
|
-
referenceKind
|
|
446
|
-
notNull: fieldDef._meta?.nullable ? false :
|
|
485
|
+
referenceKind,
|
|
486
|
+
notNull: options?.stiUnionColumns ? false : fieldDef._meta?.nullable ? false : Boolean(required),
|
|
447
487
|
unique: fieldDef._meta?.unique || false,
|
|
448
|
-
description
|
|
488
|
+
description
|
|
449
489
|
};
|
|
450
|
-
if (
|
|
490
|
+
if (defaultValue !== void 0 && shouldEmitDefault(fieldDef, normalizedSqlType, defaultValue)) column.defaultValue = defaultValue;
|
|
451
491
|
if (fieldDef.type === "foreignKey" && fieldDef.related) {
|
|
452
492
|
const [table, columnName = "id"] = fieldDef.related.split(".");
|
|
453
493
|
const fieldMeta = fieldDef._meta;
|