@happyvertical/smrt-core 0.43.9 → 0.43.10
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 +24 -1
- package/agents/generators.md +8 -5
- package/dist/change-feed.d.ts +4 -0
- package/dist/change-feed.d.ts.map +1 -1
- package/dist/change-feed.js +8 -4
- package/dist/change-feed.js.map +1 -1
- package/dist/collection.d.ts +10 -0
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +145 -18
- package/dist/collection.js.map +1 -1
- package/dist/embedded-write-queue.d.ts +17 -29
- package/dist/embedded-write-queue.d.ts.map +1 -1
- package/dist/embedded-write-queue.js +44 -6
- package/dist/embedded-write-queue.js.map +1 -1
- package/dist/generators/mcp-emit.d.ts +6 -7
- package/dist/generators/mcp-emit.d.ts.map +1 -1
- package/dist/generators/mcp-emit.js +17 -29
- package/dist/generators/mcp-emit.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/manifest/static-manifest.d.ts.map +1 -1
- package/dist/manifest/static-manifest.js +30 -2
- 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 +36 -2
- package/dist/object.d.ts +44 -2
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +207 -18
- package/dist/object.js.map +1 -1
- package/dist/smrt-knowledge.json +31 -9
- package/package.json +6 -5
package/dist/collection.js
CHANGED
|
@@ -16,6 +16,78 @@ import { createLogger } from "@happyvertical/logger";
|
|
|
16
16
|
import { buildWhere } from "@happyvertical/sql";
|
|
17
17
|
//#region src/collection.ts
|
|
18
18
|
var logger = createLogger({ level: "info" });
|
|
19
|
+
/** SQL words outside comments and quoted literals/identifiers. */
|
|
20
|
+
function executableSqlWords(sql) {
|
|
21
|
+
const words = [];
|
|
22
|
+
let index = 0;
|
|
23
|
+
while (index < sql.length) {
|
|
24
|
+
const character = sql[index];
|
|
25
|
+
const next = sql[index + 1];
|
|
26
|
+
if (character === "-" && next === "-") {
|
|
27
|
+
index = sql.indexOf("\n", index + 2);
|
|
28
|
+
if (index === -1) break;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (character === "/" && next === "*") {
|
|
32
|
+
let depth = 1;
|
|
33
|
+
index += 2;
|
|
34
|
+
while (index < sql.length && depth > 0) if (sql[index] === "/" && sql[index + 1] === "*") {
|
|
35
|
+
depth += 1;
|
|
36
|
+
index += 2;
|
|
37
|
+
} else if (sql[index] === "*" && sql[index + 1] === "/") {
|
|
38
|
+
depth -= 1;
|
|
39
|
+
index += 2;
|
|
40
|
+
} else index += 1;
|
|
41
|
+
if (depth > 0) break;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (character === "'" || character === "\"" || character === "`") {
|
|
45
|
+
const quote = character;
|
|
46
|
+
const backslashEscapes = quote === "'" && index > 0 && /[eE]/.test(sql[index - 1]) && (index === 1 || !/[A-Za-z0-9_$]/.test(sql[index - 2]));
|
|
47
|
+
index += 1;
|
|
48
|
+
while (index < sql.length) {
|
|
49
|
+
if (backslashEscapes && sql[index] === "\\") {
|
|
50
|
+
index += 2;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (sql[index] === quote) {
|
|
54
|
+
if (sql[index + 1] === quote) {
|
|
55
|
+
index += 2;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
index += 1;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
index += 1;
|
|
62
|
+
}
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (character === "$") {
|
|
66
|
+
const tag = sql.slice(index).match(/^\$[A-Za-z_][A-Za-z0-9_]*\$|^\$\$/)?.[0];
|
|
67
|
+
if (tag) {
|
|
68
|
+
const end = sql.indexOf(tag, index + tag.length);
|
|
69
|
+
if (end === -1) break;
|
|
70
|
+
index = end + tag.length;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (/[A-Za-z_]/.test(character)) {
|
|
75
|
+
const start = index;
|
|
76
|
+
index += 1;
|
|
77
|
+
while (index < sql.length && /[A-Za-z0-9_$]/.test(sql[index])) index += 1;
|
|
78
|
+
words.push(sql.slice(start, index).toLowerCase());
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
index += 1;
|
|
82
|
+
}
|
|
83
|
+
return words;
|
|
84
|
+
}
|
|
85
|
+
function isMutatingSql(words) {
|
|
86
|
+
return words.some((word, index) => {
|
|
87
|
+
const next = words[index + 1];
|
|
88
|
+
return word === "update" || word === "insert" && next === "into" || word === "delete" && next === "from" || word === "merge" && next === "into" || word === "truncate" && next === "table" || word === "replace" && next === "into";
|
|
89
|
+
});
|
|
90
|
+
}
|
|
19
91
|
/**
|
|
20
92
|
* `_smrt_contexts.owner_id` value for collection-level (as opposed to
|
|
21
93
|
* per-object) memory. Tenant-scoped collections suffix the active tenant id
|
|
@@ -450,6 +522,26 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
450
522
|
const isDuckDbConnection = (db.client?.constructor?.name?.toLowerCase() ?? "").includes("duckdb") || typeof db.exportTable === "function" && db.client !== void 0 && "connection" in db.client;
|
|
451
523
|
return detectEngine(db.url || db.config?.url || "", this.getDatabaseEngineHint() || db.type || db.config?.type || (isDuckDbConnection ? "duckdb" : void 0));
|
|
452
524
|
}
|
|
525
|
+
getHydrationSelectSql(schema = ObjectRegistry.getSchema(this.getResolvedItemQualifiedName()) ?? ObjectRegistry.getSchema(this.getResolvedItemClassName())) {
|
|
526
|
+
if (this.getDatabaseEngine() !== "duckdb") return "*";
|
|
527
|
+
const registeredFields = ObjectRegistry.getFields(this.getResolvedItemQualifiedName()).size > 0 ? ObjectRegistry.getFields(this.getResolvedItemQualifiedName()) : ObjectRegistry.getFields(this.getResolvedItemClassName());
|
|
528
|
+
const itemColumns = /* @__PURE__ */ new Set(["id", ...Array.from(registeredFields.keys(), (fieldName) => this.toDbColumnName(fieldName))]);
|
|
529
|
+
const uuidColumns = Object.entries(schema?.columns ?? {}).filter(([columnName, column]) => itemColumns.has(columnName) && String(column.type).toUpperCase() === "UUID").map(([columnName]) => columnName);
|
|
530
|
+
if (uuidColumns.length === 0) return "*";
|
|
531
|
+
return `* REPLACE (${uuidColumns.map((columnName) => {
|
|
532
|
+
const quoted = this.quoteProjectionIdentifier(columnName);
|
|
533
|
+
return `CAST(${quoted} AS VARCHAR) AS ${quoted}`;
|
|
534
|
+
}).join(", ")})`;
|
|
535
|
+
}
|
|
536
|
+
hasDuckDbUuidColumnsOutsideHydrationSelect() {
|
|
537
|
+
if (this.getDatabaseEngine() !== "duckdb") return false;
|
|
538
|
+
const qualifiedName = this.getResolvedItemQualifiedName();
|
|
539
|
+
const className = this.getResolvedItemClassName();
|
|
540
|
+
const schema = ObjectRegistry.getSchema(qualifiedName) ?? ObjectRegistry.getSchema(className);
|
|
541
|
+
const registeredFields = ObjectRegistry.getFields(qualifiedName).size > 0 ? ObjectRegistry.getFields(qualifiedName) : ObjectRegistry.getFields(className);
|
|
542
|
+
const selectedColumns = /* @__PURE__ */ new Set(["id", ...Array.from(registeredFields.keys(), (fieldName) => this.toDbColumnName(fieldName))]);
|
|
543
|
+
return Object.entries(schema?.columns ?? {}).some(([columnName, column]) => !selectedColumns.has(columnName) && String(column.type).toUpperCase() === "UUID");
|
|
544
|
+
}
|
|
453
545
|
isOmittedCustomPrimaryKeySystemField(fieldName, hasCustomPrimaryKey, explicitFieldNames) {
|
|
454
546
|
return hasCustomPrimaryKey && !explicitFieldNames.has(fieldName) && (fieldName === "id" || fieldName === "slug" || fieldName === "context");
|
|
455
547
|
}
|
|
@@ -489,7 +581,9 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
489
581
|
const isTransient = fieldDef?.transient === true || fieldDef?._meta?.transient === true;
|
|
490
582
|
if (fieldType === "meta" || isTransient || fieldType === "oneToMany" || fieldType === "manyToMany") throw new Error(`Invalid select field: '${fieldName}' is not a column-backed field on ${itemClassName}.`);
|
|
491
583
|
const columnName = this.toDbColumnName(fieldName);
|
|
492
|
-
|
|
584
|
+
const quotedColumn = this.quoteProjectionIdentifier(columnName);
|
|
585
|
+
const selectValue = this.getDatabaseEngine() === "duckdb" && String(schema?.columns[columnName]?.type).toUpperCase() === "UUID" ? `CAST(${quotedColumn} AS VARCHAR)` : quotedColumn;
|
|
586
|
+
selectExpressions.push(`${selectValue} AS ${this.quoteProjectionIdentifier(fieldName)}`);
|
|
493
587
|
outputFields.push(fieldName);
|
|
494
588
|
}
|
|
495
589
|
return {
|
|
@@ -603,7 +697,10 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
603
697
|
while (occupiedParentIdentifiers.has(alias) || [...relatedFieldAliases.values()].includes(alias));
|
|
604
698
|
relatedFieldAliases.set(fieldName, alias);
|
|
605
699
|
}
|
|
606
|
-
const parentSelectSql = parentColumnNames.length > 0 ? parentColumnNames.map((columnName) =>
|
|
700
|
+
const parentSelectSql = parentColumnNames.length > 0 ? parentColumnNames.map((columnName) => {
|
|
701
|
+
const quoted = this.quoteProjectionIdentifier(columnName);
|
|
702
|
+
return this.getDatabaseEngine() === "duckdb" && String(parentSchema?.columns[columnName]?.type).toUpperCase() === "UUID" ? `CAST(${quoted} AS VARCHAR) AS ${quoted}` : quoted;
|
|
703
|
+
}).join(", ") : "*";
|
|
607
704
|
const relatedAlias = (fieldName) => {
|
|
608
705
|
const alias = relatedFieldAliases.get(fieldName);
|
|
609
706
|
if (!alias) throw new Error(`Missing latest-related alias for '${fieldName}'.`);
|
|
@@ -612,12 +709,15 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
612
709
|
const relatedSelectExpressions = Array.from(relatedOutputFields).map((fieldName) => {
|
|
613
710
|
const column = relatedFieldColumns.get(fieldName) ?? relatedCollection.toDbColumnName(fieldName);
|
|
614
711
|
const alias = relatedAlias(fieldName);
|
|
615
|
-
|
|
712
|
+
const quotedColumn = relatedCollection.quoteProjectionIdentifier(column);
|
|
713
|
+
const relatedSchema = ObjectRegistry.getSchema(relatedQualifiedName) ?? ObjectRegistry.getSchema(relatedItemClassName);
|
|
714
|
+
const source = `r.${quotedColumn}`;
|
|
715
|
+
return `${relatedCollection.getDatabaseEngine() === "duckdb" && String(relatedSchema?.columns[column]?.type).toUpperCase() === "UUID" ? `CAST(${source} AS VARCHAR)` : source} AS ${relatedCollection.quoteProjectionIdentifier(alias)}`;
|
|
616
716
|
});
|
|
617
717
|
const relatedRankOrder = [relatedCollection.qualifyLatestOrderTerms("r", relatedOrderTerms), `r.${relatedCollection.quoteProjectionIdentifier(relatedPrimaryKey.column)} DESC`].filter(Boolean).join(", ");
|
|
618
718
|
const latestRankAlias = relatedCollection.quoteProjectionIdentifier("__smrt_latest_rank");
|
|
619
719
|
const latestRelatedAlias = (fieldName) => relatedCollection.quoteProjectionIdentifier(relatedAlias(fieldName));
|
|
620
|
-
const relatedCte = `WITH ranked_latest_related AS (SELECT ${relatedSelectExpressions.
|
|
720
|
+
const relatedCte = `WITH ranked_latest_related AS (SELECT ${relatedSelectExpressions.join(", ")}, ROW_NUMBER() OVER (PARTITION BY r.${relatedCollection.quoteProjectionIdentifier(relatedCollection.toDbColumnName(inverseForeignKey.fieldName))} ORDER BY ${relatedRankOrder}) AS ${latestRankAlias} FROM ${relatedCollection.tableName} r${relatedWhereSql ? ` ${relatedWhereSql}` : ""}) `;
|
|
621
721
|
const { sql: rawWhereSql, values: parentWhereValues } = buildWhere(this.convertWhereKeys(where || {}));
|
|
622
722
|
const parentWhereSql = rawWhereSql.replace(/\$(\d+)/g, (_match, index) => `$${Number(index) + relatedWhereValues.length}`);
|
|
623
723
|
const relatedJoinConditions = [`rr.${latestRankAlias} = 1`, `rr.${latestRelatedAlias(inverseForeignKey.fieldName)} = ${this.quoteProjectionIdentifier(parentPrimaryKey.column)}`];
|
|
@@ -647,16 +747,21 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
647
747
|
limitOffsetValues.push(boundedOffset);
|
|
648
748
|
}
|
|
649
749
|
const sql = `${relatedCte}SELECT ${parentSelectSql}, ${Array.from(relatedOutputFields).map((fieldName) => `rr.${latestRelatedAlias(fieldName)} AS ${this.quoteProjectionIdentifier(relatedAlias(fieldName))}`).join(", ")} FROM ${this.quoteProjectionIdentifier(this.tableName)} LEFT JOIN ranked_latest_related rr ON ${relatedJoinConditions.join(" AND ")} ${parentWhereSql} ${orderFragments.length > 0 ? `ORDER BY ${orderFragments.join(", ")}` : ""}${limitOffsetSql}`;
|
|
650
|
-
const
|
|
750
|
+
const queryValues = [
|
|
751
|
+
...relatedWhereValues,
|
|
752
|
+
...parentWhereValues,
|
|
753
|
+
...limitOffsetValues
|
|
754
|
+
];
|
|
755
|
+
const rows = await this.queryDuckDbCanonicalSelectRows(sql, queryValues);
|
|
651
756
|
const instances = [];
|
|
652
757
|
const relatedAliasNames = new Set(relatedFieldAliases.values());
|
|
653
758
|
const polymorphicFields = /* @__PURE__ */ new Map();
|
|
654
|
-
for (const row of rows
|
|
759
|
+
for (const row of rows) {
|
|
655
760
|
const parentRow = Object.fromEntries(Object.entries(row).filter(([key]) => !relatedAliasNames.has(key)));
|
|
656
761
|
instances.push(await this.hydrateResultRow(parentRow, parentFields, isSTI, polymorphicFields));
|
|
657
762
|
}
|
|
658
763
|
const relatedByParentId = /* @__PURE__ */ new Map();
|
|
659
|
-
for (const row of rows
|
|
764
|
+
for (const row of rows) {
|
|
660
765
|
const parentId = row[parentPrimaryKey.column];
|
|
661
766
|
if (parentId === null || parentId === void 0) continue;
|
|
662
767
|
const relatedRow = Object.fromEntries(relatedProjection.outputFields.map((fieldName) => [fieldName, row[relatedAlias(fieldName)]]));
|
|
@@ -937,8 +1042,8 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
937
1042
|
* differently-scoped queries can never share an entry. Cached values are
|
|
938
1043
|
* raw rows; callers still run their normal post-query formatting path.
|
|
939
1044
|
*/
|
|
940
|
-
async queryRowsWithCache(sql, params, cacheConfig) {
|
|
941
|
-
if (!cacheConfig) return
|
|
1045
|
+
async queryRowsWithCache(sql, params, cacheConfig, describeUuidOutputs) {
|
|
1046
|
+
if (!cacheConfig) return await this.queryDuckDbCanonicalSelectRows(sql, params, describeUuidOutputs);
|
|
942
1047
|
const dbKey = resolveDbCacheKey(this.db);
|
|
943
1048
|
const queryKey = buildQueryCacheKey(sql, params);
|
|
944
1049
|
if (cacheConfig.crossProcess) {
|
|
@@ -948,9 +1053,31 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
948
1053
|
const cached = getCachedRows(dbKey, this.tableName, queryKey);
|
|
949
1054
|
if (cached) return cached;
|
|
950
1055
|
const generation = getCacheGeneration(dbKey, this.tableName);
|
|
951
|
-
const
|
|
952
|
-
setCachedRows(dbKey, this.tableName, queryKey,
|
|
953
|
-
return
|
|
1056
|
+
const rows = await this.queryDuckDbCanonicalSelectRows(sql, params, describeUuidOutputs);
|
|
1057
|
+
setCachedRows(dbKey, this.tableName, queryKey, rows, cacheConfig.ttl, generation);
|
|
1058
|
+
return rows;
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Describe a native DuckDB SELECT before executing it, then cast UUID output
|
|
1062
|
+
* columns in the one data-bearing execution. DuckDB's JavaScript binding
|
|
1063
|
+
* exposes UUID values as lossy HUGEINT wrappers, so they cannot be repaired
|
|
1064
|
+
* from the first result without replaying volatile SELECT expressions or
|
|
1065
|
+
* combining two different database snapshots.
|
|
1066
|
+
*/
|
|
1067
|
+
async queryDuckDbCanonicalSelectRows(sql, params, describeUuidOutputs = true) {
|
|
1068
|
+
if (this.getDatabaseEngine() !== "duckdb" || !describeUuidOutputs) return (await this.db.query(sql, ...params)).rows;
|
|
1069
|
+
const readSql = sql.trim().replace(/;$/, "");
|
|
1070
|
+
const words = executableSqlWords(readSql);
|
|
1071
|
+
if (isMutatingSql(words)) return (await this.db.query(sql, ...params)).rows;
|
|
1072
|
+
if (words[0] !== "select" && words[0] !== "with") return (await this.db.query(sql, ...params)).rows;
|
|
1073
|
+
const uuidColumns = (await this.db.query(`DESCRIBE ${readSql}`, ...params)).rows.filter((row) => String(row.column_type).toUpperCase() === "UUID").map((row) => String(row.column_name));
|
|
1074
|
+
if (uuidColumns.length === 0) return (await this.db.query(sql, ...params)).rows;
|
|
1075
|
+
const alias = this.quoteProjectionIdentifier("__smrt_uuid_rows");
|
|
1076
|
+
const replacements = uuidColumns.map((column) => {
|
|
1077
|
+
const quoted = this.quoteProjectionIdentifier(column);
|
|
1078
|
+
return `CAST(${alias}.${quoted} AS VARCHAR) AS ${quoted}`;
|
|
1079
|
+
}).join(", ");
|
|
1080
|
+
return (await this.db.query(`SELECT ${alias}.* REPLACE (${replacements}) FROM (${readSql}) AS ${alias}`, ...params)).rows;
|
|
954
1081
|
}
|
|
955
1082
|
/**
|
|
956
1083
|
* Retrieves a single object from the collection by ID, slug, or a custom filter.
|
|
@@ -1005,8 +1132,8 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
1005
1132
|
};
|
|
1006
1133
|
}
|
|
1007
1134
|
const { sql: whereSql, values: whereValues } = buildWhere(this.convertWhereKeys(where));
|
|
1008
|
-
const fullSQL = `SELECT
|
|
1009
|
-
const rows = await this.queryRowsWithCache(fullSQL, whereValues, this.resolveReadCacheConfig(options.cache));
|
|
1135
|
+
const fullSQL = `SELECT ${this.getHydrationSelectSql()} FROM ${this.tableName} ${whereSql} LIMIT 1`;
|
|
1136
|
+
const rows = await this.queryRowsWithCache(fullSQL, whereValues, this.resolveReadCacheConfig(options.cache), this.hasDuckDbUuidColumnsOutsideHydrationSelect());
|
|
1010
1137
|
if (!rows?.[0]) return await GlobalInterceptors.executeAfterGet(itemClassName, null, interceptorContext);
|
|
1011
1138
|
const fields = this.getFieldsSync();
|
|
1012
1139
|
const instance = await this.hydrateResultRow(rows[0], fields, isSTI);
|
|
@@ -1040,9 +1167,9 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
1040
1167
|
limitOffsetSql += ` OFFSET $${paramIndex++}`;
|
|
1041
1168
|
limitOffsetValues.push(boundedOffset);
|
|
1042
1169
|
}
|
|
1043
|
-
const sql = `SELECT ${projection ? projection.sql :
|
|
1170
|
+
const sql = `SELECT ${projection ? projection.sql : this.getHydrationSelectSql()} FROM ${this.tableName} ${whereSql} ${orderBySql} ${limitOffsetSql}`;
|
|
1044
1171
|
const params = [...whereValues, ...limitOffsetValues];
|
|
1045
|
-
const rows = await this.queryRowsWithCache(sql, params, this.resolveReadCacheConfig(interceptedOptions.cache));
|
|
1172
|
+
const rows = await this.queryRowsWithCache(sql, params, this.resolveReadCacheConfig(interceptedOptions.cache), !projection && this.hasDuckDbUuidColumnsOutsideHydrationSelect());
|
|
1046
1173
|
if (projection) return rows.map((item) => this.formatProjectionRow(item, fields, projection.outputFields));
|
|
1047
1174
|
const instances = await this.hydrateResultRows(rows, fields, isSTI);
|
|
1048
1175
|
if (interceptedOptions.include && interceptedOptions.include.length > 0) await this.eagerLoadRelationships(instances, interceptedOptions.include);
|
|
@@ -1753,11 +1880,11 @@ var SmrtCollection = class SmrtCollection extends SmrtClass {
|
|
|
1753
1880
|
params,
|
|
1754
1881
|
allowRawOnTenantScoped: options.allowRawOnTenantScoped
|
|
1755
1882
|
}, interceptorContext);
|
|
1756
|
-
const
|
|
1883
|
+
const rows = await this.queryDuckDbCanonicalSelectRows(interceptedQuery.sql, interceptedQuery.params);
|
|
1757
1884
|
if (/\b(?:insert|update|delete|merge|truncate|replace)\b/i.test(interceptedQuery.sql)) invalidateCollectionCache(resolveDbCacheKey(this.db), this.tableName);
|
|
1758
1885
|
const fields = this.getFieldsSync();
|
|
1759
1886
|
const isSTI = ObjectRegistry.getTableStrategy(this.getResolvedItemQualifiedName()) === "sti";
|
|
1760
|
-
const instances = await this.hydrateResultRows(
|
|
1887
|
+
const instances = await this.hydrateResultRows(rows, fields, isSTI);
|
|
1761
1888
|
return await GlobalInterceptors.executeAfterQuery(this._itemClass.name, instances, interceptorContext);
|
|
1762
1889
|
}
|
|
1763
1890
|
async hydrateResultRow(row, fields, isSTI, polymorphicFields = /* @__PURE__ */ new Map()) {
|