@warlock.js/cascade 5.5.0 → 5.7.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/CHANGELOG.md +13 -0
- package/cjs/index.cjs +74 -36
- package/cjs/index.cjs.map +1 -1
- package/esm/database-dirty-tracker.d.mts.map +1 -1
- package/esm/database-dirty-tracker.mjs +4 -1
- package/esm/database-dirty-tracker.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.mjs +1 -0
- package/esm/drivers/mongodb/mongodb-migration-driver.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.mjs +2 -4
- package/esm/drivers/mongodb/mongodb-query-builder.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-parser.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-parser.mjs +21 -7
- package/esm/drivers/mongodb/mongodb-query-parser.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-blueprint.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-blueprint.mjs +1 -2
- package/esm/drivers/postgres/postgres-blueprint.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-driver.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-driver.mjs +1 -1
- package/esm/drivers/postgres/postgres-driver.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-migration-driver.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-migration-driver.mjs +1 -2
- package/esm/drivers/postgres/postgres-migration-driver.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-query-builder.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-query-builder.mjs +5 -6
- package/esm/drivers/postgres/postgres-query-builder.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.mjs +2 -0
- package/esm/drivers/postgres/postgres-query-parser.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-sql-serializer.mjs +1 -1
- package/esm/drivers/postgres/postgres-sql-serializer.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-sync-adapter.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-sync-adapter.mjs +2 -2
- package/esm/drivers/postgres/postgres-sync-adapter.mjs.map +1 -1
- package/esm/migration/parse-created-at.mjs +1 -0
- package/esm/migration/parse-created-at.mjs.map +1 -1
- package/esm/query-builder/query-builder.d.mts.map +1 -1
- package/esm/query-builder/query-builder.mjs +27 -9
- package/esm/query-builder/query-builder.mjs.map +1 -1
- package/esm/relations/relation-loader.d.mts.map +1 -1
- package/esm/relations/relation-loader.mjs +1 -0
- package/esm/relations/relation-loader.mjs.map +1 -1
- package/esm/utils/is-valid-date-value.mjs +4 -1
- package/esm/utils/is-valid-date-value.mjs.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to `@warlock.js/cascade` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.7.0 - 2026-09-11
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- The Postgres query builder could quote a malformed or empty field path straight into generated SQL, producing a syntactically valid query against the wrong identifier; it now throws naming the offending field path instead.
|
|
12
|
+
- The MongoDB pipeline builder could build `$group`, `$lookup`, `$limit`/`$skip`/`$setWindowFields` stages from an empty operation group, producing malformed stages (e.g. `{ $limit: undefined }`, a `$lookup` with no `from`/`localField`/`foreignField`) that MongoDB rejected only at query execution. These now resolve to the documented safe defaults (`null`/skip) instead.
|
|
13
|
+
- The dirty-change tracker and the MongoDB migration driver could write or delete the literal key `"undefined"` on a document when a dirty-path segment was missing, instead of leaving the real field untouched.
|
|
14
|
+
- The query builder's count and JSON-projection handling could dereference an absent regex capture and throw, instead of falling back to the same empty result its other branches already return.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Internal type-safety hardening elsewhere; no other behaviour change.
|
|
19
|
+
|
|
7
20
|
## 5.5.0 - 2026-09-07
|
|
8
21
|
|
|
9
22
|
### Fixed
|
package/cjs/index.cjs
CHANGED
|
@@ -794,10 +794,13 @@ var DatabaseDirtyTracker = class {
|
|
|
794
794
|
let container = this.currentRaw;
|
|
795
795
|
for (let index = 0; index < segments.length - 1; index += 1) {
|
|
796
796
|
if (container === void 0 || container === null) return;
|
|
797
|
-
|
|
797
|
+
const segment = segments[index];
|
|
798
|
+
if (segment === void 0) return;
|
|
799
|
+
container = this.resolveSegment(container, segment);
|
|
798
800
|
}
|
|
799
801
|
if (container === void 0 || container === null) return;
|
|
800
802
|
const lastSegment = segments[segments.length - 1];
|
|
803
|
+
if (lastSegment === void 0) return;
|
|
801
804
|
if (Array.isArray(container)) {
|
|
802
805
|
const numericIndex = Number(lastSegment);
|
|
803
806
|
if (!Number.isNaN(numericIndex)) container.splice(numericIndex, 1);
|
|
@@ -1702,6 +1705,7 @@ var RelationLoader = class RelationLoader {
|
|
|
1702
1705
|
async loadRelation(name, constraint) {
|
|
1703
1706
|
const path = this.parseNestedRelation(name);
|
|
1704
1707
|
const rootRelation = path[0];
|
|
1708
|
+
if (rootRelation === void 0) throw new Error(`Relation name "${name}" could not be parsed into a relation path on model "${this.modelClass.name}".`);
|
|
1705
1709
|
const definition = this.getRelationDefinition(rootRelation);
|
|
1706
1710
|
if (!definition) throw new Error(`Relation "${rootRelation}" is not defined on model "${this.modelClass.name}". Make sure to define it in the static 'relations' property.`);
|
|
1707
1711
|
switch (definition.type) {
|
|
@@ -7701,7 +7705,10 @@ function isValidDateValue(value) {
|
|
|
7701
7705
|
if (!isoRegex.test(value)) return false;
|
|
7702
7706
|
const date = new Date(value);
|
|
7703
7707
|
if (Number.isNaN(date.getTime())) return false;
|
|
7704
|
-
const
|
|
7708
|
+
const datePart = value.split("T")[0];
|
|
7709
|
+
if (datePart === void 0) return false;
|
|
7710
|
+
const [y, m, d] = datePart.split("-").map(Number);
|
|
7711
|
+
if (y === void 0 || m === void 0 || d === void 0) return false;
|
|
7705
7712
|
return date.getUTCFullYear() === y && date.getUTCMonth() + 1 === m && date.getUTCDate() === d;
|
|
7706
7713
|
}
|
|
7707
7714
|
|
|
@@ -8180,6 +8187,7 @@ var MongoMigrationDriver = class {
|
|
|
8180
8187
|
const indexSpec = {};
|
|
8181
8188
|
for (let i = 0; i < index.columns.length; i++) {
|
|
8182
8189
|
const column = index.columns[i];
|
|
8190
|
+
if (column === void 0) continue;
|
|
8183
8191
|
indexSpec[column] = index.directions?.[i] === "desc" ? -1 : 1;
|
|
8184
8192
|
}
|
|
8185
8193
|
const options = {};
|
|
@@ -8594,12 +8602,22 @@ var QueryBuilder = class QueryBuilder {
|
|
|
8594
8602
|
* builder.getOps("where", "orWhere", "whereIn")
|
|
8595
8603
|
*/
|
|
8596
8604
|
getOps(...types) {
|
|
8597
|
-
if (types.length === 1)
|
|
8605
|
+
if (types.length === 1) {
|
|
8606
|
+
const type = types[0];
|
|
8607
|
+
if (type === void 0) return [];
|
|
8608
|
+
return (this.opIndex.get(type) ?? []).flatMap((index) => {
|
|
8609
|
+
const operation = this.operations[index];
|
|
8610
|
+
return operation === void 0 ? [] : [operation];
|
|
8611
|
+
});
|
|
8612
|
+
}
|
|
8598
8613
|
const result = [];
|
|
8599
|
-
for (const type of types) for (const idx of this.opIndex.get(type) ?? [])
|
|
8600
|
-
idx
|
|
8601
|
-
|
|
8602
|
-
|
|
8614
|
+
for (const type of types) for (const idx of this.opIndex.get(type) ?? []) {
|
|
8615
|
+
const operation = this.operations[idx];
|
|
8616
|
+
if (operation !== void 0) result.push({
|
|
8617
|
+
idx,
|
|
8618
|
+
op: operation
|
|
8619
|
+
});
|
|
8620
|
+
}
|
|
8603
8621
|
return result.sort((a, b) => a.idx - b.idx).map((r) => r.op);
|
|
8604
8622
|
}
|
|
8605
8623
|
/**
|
|
@@ -8611,7 +8629,9 @@ var QueryBuilder = class QueryBuilder {
|
|
|
8611
8629
|
rebuildIndex() {
|
|
8612
8630
|
this.opIndex = /* @__PURE__ */ new Map();
|
|
8613
8631
|
for (let i = 0; i < this.operations.length; i++) {
|
|
8614
|
-
const
|
|
8632
|
+
const operation = this.operations[i];
|
|
8633
|
+
if (operation === void 0) continue;
|
|
8634
|
+
const type = operation.type;
|
|
8615
8635
|
const list = this.opIndex.get(type);
|
|
8616
8636
|
if (list) list.push(i);
|
|
8617
8637
|
else this.opIndex.set(type, [i]);
|
|
@@ -9298,9 +9318,15 @@ var QueryBuilder = class QueryBuilder {
|
|
|
9298
9318
|
relation: trimmed,
|
|
9299
9319
|
alias: `${trimmed}Count`
|
|
9300
9320
|
};
|
|
9321
|
+
const relation = match[1];
|
|
9322
|
+
const alias = match[2];
|
|
9323
|
+
if (relation === void 0 || alias === void 0) return {
|
|
9324
|
+
relation: trimmed,
|
|
9325
|
+
alias: `${trimmed}Count`
|
|
9326
|
+
};
|
|
9301
9327
|
return {
|
|
9302
|
-
relation:
|
|
9303
|
-
alias:
|
|
9328
|
+
relation: relation.trim(),
|
|
9329
|
+
alias: alias.trim()
|
|
9304
9330
|
};
|
|
9305
9331
|
}
|
|
9306
9332
|
/**
|
|
@@ -9427,7 +9453,7 @@ var QueryBuilder = class QueryBuilder {
|
|
|
9427
9453
|
/** JSON path extraction as a projected field. */
|
|
9428
9454
|
selectJson(path, alias) {
|
|
9429
9455
|
const parts = path.split("->");
|
|
9430
|
-
const column = parts[0];
|
|
9456
|
+
const column = parts[0] ?? "";
|
|
9431
9457
|
const jsonPath = parts.slice(1).join("->");
|
|
9432
9458
|
const expr = jsonPath ? `${column}->>'${jsonPath}'` : column;
|
|
9433
9459
|
return alias ? this.selectAs(expr, alias) : this.selectRaw(expr);
|
|
@@ -10135,6 +10161,7 @@ var MongoQueryParser = class {
|
|
|
10135
10161
|
trackGroupFieldNames(stage, operations, stageIndex) {
|
|
10136
10162
|
if (stage === "$group") {
|
|
10137
10163
|
const op = operations[0];
|
|
10164
|
+
if (op === void 0) return;
|
|
10138
10165
|
if (op.type === "groupByWithAggregates" && op.data.fields) {
|
|
10139
10166
|
const fieldNames = this.extractGroupFieldNames(op.data.fields);
|
|
10140
10167
|
if (fieldNames) this.groupFieldNames.set(stageIndex, fieldNames);
|
|
@@ -10215,7 +10242,7 @@ var MongoQueryParser = class {
|
|
|
10215
10242
|
let output = "MongoDB Aggregation Pipeline:\n";
|
|
10216
10243
|
output += "═".repeat(50) + "\n";
|
|
10217
10244
|
pipeline.forEach((stage, index) => {
|
|
10218
|
-
const stageName = Object.keys(stage)[0];
|
|
10245
|
+
const stageName = Object.keys(stage)[0] ?? "<empty stage>";
|
|
10219
10246
|
const stageData = stage[stageName];
|
|
10220
10247
|
if (index > 0) output += "\n";
|
|
10221
10248
|
output += `Stage ${index + 1}: ${_mongez_copper.colors.redBright(stageName)}\n`;
|
|
@@ -10272,9 +10299,18 @@ var MongoQueryParser = class {
|
|
|
10272
10299
|
case "$sort": return this.buildSortStage(operations);
|
|
10273
10300
|
case "$group": return this.buildGroupStage(operations);
|
|
10274
10301
|
case "$lookup": return this.buildLookupStage(operations);
|
|
10275
|
-
case "$limit":
|
|
10276
|
-
|
|
10277
|
-
|
|
10302
|
+
case "$limit": {
|
|
10303
|
+
const [first] = operations;
|
|
10304
|
+
return first === void 0 ? null : { $limit: first.data.value };
|
|
10305
|
+
}
|
|
10306
|
+
case "$skip": {
|
|
10307
|
+
const [first] = operations;
|
|
10308
|
+
return first === void 0 ? null : { $skip: first.data.value };
|
|
10309
|
+
}
|
|
10310
|
+
case "$setWindowFields": {
|
|
10311
|
+
const [first] = operations;
|
|
10312
|
+
return first === void 0 ? null : { $setWindowFields: first.data.spec };
|
|
10313
|
+
}
|
|
10278
10314
|
default: return null;
|
|
10279
10315
|
}
|
|
10280
10316
|
}
|
|
@@ -10794,8 +10830,9 @@ var MongoQueryParser = class {
|
|
|
10794
10830
|
return this.resolveProjectionExpression(value);
|
|
10795
10831
|
}
|
|
10796
10832
|
inferJsonAlias(path) {
|
|
10797
|
-
const
|
|
10798
|
-
|
|
10833
|
+
const normalized = this.normalizePath(path);
|
|
10834
|
+
const segments = normalized.split(".");
|
|
10835
|
+
return segments[segments.length - 1] ?? normalized;
|
|
10799
10836
|
}
|
|
10800
10837
|
buildConcatExpression(values) {
|
|
10801
10838
|
return { $concat: values.map((value) => this.normalizeFieldReference(value)) };
|
|
@@ -10901,6 +10938,7 @@ var MongoQueryParser = class {
|
|
|
10901
10938
|
*/
|
|
10902
10939
|
buildGroupStage(operations) {
|
|
10903
10940
|
const op = operations[0];
|
|
10941
|
+
if (op === void 0) return null;
|
|
10904
10942
|
switch (op.type) {
|
|
10905
10943
|
case "groupBy": {
|
|
10906
10944
|
const stage = this.buildGroupByStage(op.data.fields);
|
|
@@ -11086,7 +11124,9 @@ var MongoQueryParser = class {
|
|
|
11086
11124
|
* @returns The $lookup stage or null
|
|
11087
11125
|
*/
|
|
11088
11126
|
buildLookupStage(operations) {
|
|
11089
|
-
const
|
|
11127
|
+
const op = operations[0];
|
|
11128
|
+
if (op === void 0) return null;
|
|
11129
|
+
const options = op.data;
|
|
11090
11130
|
return { $lookup: {
|
|
11091
11131
|
from: options.table,
|
|
11092
11132
|
localField: options.localField,
|
|
@@ -12468,8 +12508,7 @@ var MongoQueryBuilder = class MongoQueryBuilder extends QueryBuilder {
|
|
|
12468
12508
|
* @returns the first document or null
|
|
12469
12509
|
*/
|
|
12470
12510
|
async first() {
|
|
12471
|
-
|
|
12472
|
-
return results.length > 0 ? results[0] : null;
|
|
12511
|
+
return (await this.limit(1).get())[0] ?? null;
|
|
12473
12512
|
}
|
|
12474
12513
|
/**
|
|
12475
12514
|
* Executes the query and returns the first matching document, throwing if none found.
|
|
@@ -12500,8 +12539,7 @@ var MongoQueryBuilder = class MongoQueryBuilder extends QueryBuilder {
|
|
|
12500
12539
|
async count() {
|
|
12501
12540
|
const pipeline = this.buildPipeline();
|
|
12502
12541
|
pipeline.push({ $count: "total" });
|
|
12503
|
-
|
|
12504
|
-
return results.length > 0 ? results[0].total : 0;
|
|
12542
|
+
return (await this.execute(pipeline))[0]?.total ?? 0;
|
|
12505
12543
|
}
|
|
12506
12544
|
/**
|
|
12507
12545
|
* Calculates the sum of a numeric field across matching documents.
|
|
@@ -13846,8 +13884,7 @@ var PostgresBlueprint = class {
|
|
|
13846
13884
|
AND tablename = $1`, [table])).rows.map((row) => {
|
|
13847
13885
|
const isUnique = row.indexdef.includes("UNIQUE");
|
|
13848
13886
|
const isPrimary = row.indexname.endsWith("_pkey");
|
|
13849
|
-
const
|
|
13850
|
-
const columns = columnsMatch ? columnsMatch[1].split(",").map((c) => c.trim().replace(/"/g, "")) : [];
|
|
13887
|
+
const columns = (row.indexdef.match(/\(([^)]+)\)/)?.[1] ?? "").split(",").map((c) => c.trim().replace(/"/g, "")).filter(Boolean);
|
|
13851
13888
|
let type = "btree";
|
|
13852
13889
|
if (row.indexdef.includes("USING GIN")) type = "gin";
|
|
13853
13890
|
else if (row.indexdef.includes("USING GIST")) type = "gist";
|
|
@@ -14675,8 +14712,7 @@ var PostgresMigrationDriver = class {
|
|
|
14675
14712
|
return (await this.driver.query(`SELECT indexname, indexdef FROM pg_indexes WHERE schemaname = 'public' AND tablename = $1`, [table])).rows.map((row) => {
|
|
14676
14713
|
const isUnique = row.indexdef.includes("UNIQUE");
|
|
14677
14714
|
const isPrimary = row.indexname.endsWith("_pkey");
|
|
14678
|
-
const
|
|
14679
|
-
const columns = columnsMatch ? columnsMatch[1].split(",").map((c) => c.trim().replace(/"/g, "")) : [];
|
|
14715
|
+
const columns = (row.indexdef.match(/\(([^)]+)\)/)?.[1] ?? "").split(",").map((c) => c.trim().replace(/"/g, "")).filter(Boolean);
|
|
14680
14716
|
let type = "btree";
|
|
14681
14717
|
if (row.indexdef.includes("USING GIN")) type = "gin";
|
|
14682
14718
|
else if (row.indexdef.includes("USING GIST")) type = "gist";
|
|
@@ -15616,10 +15652,12 @@ var PostgresQueryParser = class PostgresQueryParser {
|
|
|
15616
15652
|
if (parts.length === 1) expression = `${this.dialect.quoteIdentifier(effectiveTable)}.${this.dialect.quoteIdentifier(field)}`;
|
|
15617
15653
|
else if (parts.length === 2) {
|
|
15618
15654
|
const [first, second] = parts;
|
|
15655
|
+
if (first === void 0 || second === void 0) throw new Error(`Cannot parse field path "${field}": expected two non-empty segments.`);
|
|
15619
15656
|
if (this.isTableReference(first)) expression = `${this.dialect.quoteIdentifier(first)}.${this.dialect.quoteIdentifier(second)}`;
|
|
15620
15657
|
else expression = this.buildJsonbPath(effectiveTable, first, [second]);
|
|
15621
15658
|
} else {
|
|
15622
15659
|
const [first, second, ...rest] = parts;
|
|
15660
|
+
if (first === void 0 || second === void 0) throw new Error(`Cannot parse field path "${field}": expected at least three non-empty segments.`);
|
|
15623
15661
|
if (this.isTableReference(first)) expression = this.buildJsonbPath(first, second, rest);
|
|
15624
15662
|
else expression = this.buildJsonbPath(effectiveTable, first, [second, ...rest]);
|
|
15625
15663
|
}
|
|
@@ -16116,8 +16154,7 @@ var PostgresQueryBuilder = class PostgresQueryBuilder extends QueryBuilder {
|
|
|
16116
16154
|
const segments = path.split(".");
|
|
16117
16155
|
let currentModel = this.modelClass;
|
|
16118
16156
|
let currentPath = "";
|
|
16119
|
-
for (
|
|
16120
|
-
const rawSeg = segments[i];
|
|
16157
|
+
for (const [i, rawSeg] of segments.entries()) {
|
|
16121
16158
|
const colonIdx = rawSeg.indexOf(":");
|
|
16122
16159
|
const segName = colonIdx === -1 ? rawSeg : rawSeg.slice(0, colonIdx);
|
|
16123
16160
|
const segColumns = colonIdx === -1 ? void 0 : rawSeg.slice(colonIdx + 1).split(",").filter(Boolean);
|
|
@@ -16276,7 +16313,7 @@ var PostgresQueryBuilder = class PostgresQueryBuilder extends QueryBuilder {
|
|
|
16276
16313
|
async distinct(field) {
|
|
16277
16314
|
this.hydrateCallback = void 0;
|
|
16278
16315
|
this.distinctValues(field);
|
|
16279
|
-
return (await this.get()).map((row) => row[field]);
|
|
16316
|
+
return (await this.get()).map((row) => row[field]).filter((value) => value !== void 0);
|
|
16280
16317
|
}
|
|
16281
16318
|
/** Get array of all values for a single field. */
|
|
16282
16319
|
async pluck(field) {
|
|
@@ -16503,7 +16540,7 @@ var PostgresQueryBuilder = class PostgresQueryBuilder extends QueryBuilder {
|
|
|
16503
16540
|
}
|
|
16504
16541
|
/** Pluck scalar values for a single field (alias for pluck). */
|
|
16505
16542
|
async pluckOne(field) {
|
|
16506
|
-
return (await this.select([field]).get()).map((row) => row[field]);
|
|
16543
|
+
return (await this.select([field]).get()).map((row) => row[field]).filter((value) => value !== void 0);
|
|
16507
16544
|
}
|
|
16508
16545
|
/**
|
|
16509
16546
|
* Before `get()` runs the parser, consume any joinWith ops recorded by the base
|
|
@@ -16803,7 +16840,7 @@ var PostgresQueryBuilder = class PostgresQueryBuilder extends QueryBuilder {
|
|
|
16803
16840
|
bindings: []
|
|
16804
16841
|
};
|
|
16805
16842
|
return {
|
|
16806
|
-
fragment: match[1].replace(/\$\d+/g, "?"),
|
|
16843
|
+
fragment: (match[1] ?? "").replace(/\$\d+/g, "?"),
|
|
16807
16844
|
bindings: bindings ?? []
|
|
16808
16845
|
};
|
|
16809
16846
|
}
|
|
@@ -16904,7 +16941,7 @@ var PostgresQueryBuilder = class PostgresQueryBuilder extends QueryBuilder {
|
|
|
16904
16941
|
}
|
|
16905
16942
|
const RelatedModel = resolveModelClass(config.model);
|
|
16906
16943
|
if (!RelatedModel) continue;
|
|
16907
|
-
const childKeys = Array.from(this.joinRelations.keys()).filter((p) => p.startsWith(`${path}.`)).map((p) => p.split(".")[path.split(".").length]);
|
|
16944
|
+
const childKeys = Array.from(this.joinRelations.keys()).filter((p) => p.startsWith(`${path}.`)).map((p) => p.split(".")[path.split(".").length]).filter((segment) => segment !== void 0);
|
|
16908
16945
|
if (config.type === "hasMany") attachLoadedRelation(model, key, (Array.isArray(data) ? data : []).map((row) => {
|
|
16909
16946
|
const rowData = { ...row };
|
|
16910
16947
|
for (const childKey of childKeys) delete rowData[childKey];
|
|
@@ -17095,7 +17132,7 @@ var PostgresSQLSerializer = class extends SQLSerializer {
|
|
|
17095
17132
|
const statements = [sql];
|
|
17096
17133
|
if (column.checkConstraint) statements.push(this.addCheck(table, column.checkConstraint.name, column.checkConstraint.expression));
|
|
17097
17134
|
if (column.type === "vector") return ["CREATE EXTENSION IF NOT EXISTS vector", ...statements];
|
|
17098
|
-
return statements.length === 1 ? statements[0] : statements;
|
|
17135
|
+
return statements.length === 1 ? statements[0] ?? statements : statements;
|
|
17099
17136
|
}
|
|
17100
17137
|
dropColumn(table, column) {
|
|
17101
17138
|
return `ALTER TABLE ${this.dialect.quoteIdentifier(table)} DROP COLUMN ${this.dialect.quoteIdentifier(column)}`;
|
|
@@ -17319,7 +17356,7 @@ var PostgresSyncAdapter = class {
|
|
|
17319
17356
|
let paramIndex = 1;
|
|
17320
17357
|
for (const [path, value] of Object.entries(update)) if (path.includes(".")) {
|
|
17321
17358
|
const [column, ...pathParts] = path.split(".");
|
|
17322
|
-
const quotedColumn = this.driver.dialect.quoteIdentifier(column);
|
|
17359
|
+
const quotedColumn = this.driver.dialect.quoteIdentifier(column ?? path);
|
|
17323
17360
|
const jsonPath = `{${pathParts.join(",")}}`;
|
|
17324
17361
|
const placeholder = this.driver.dialect.placeholder(paramIndex++);
|
|
17325
17362
|
params.push(JSON.stringify(value));
|
|
@@ -17333,7 +17370,7 @@ var PostgresSyncAdapter = class {
|
|
|
17333
17370
|
const whereClauses = [];
|
|
17334
17371
|
for (const [key, value] of Object.entries(filter)) if (key.includes(".")) {
|
|
17335
17372
|
const [column, ...pathParts] = key.split(".");
|
|
17336
|
-
const quotedColumn = this.driver.dialect.quoteIdentifier(column);
|
|
17373
|
+
const quotedColumn = this.driver.dialect.quoteIdentifier(column ?? key);
|
|
17337
17374
|
const intermediateExpr = pathParts.slice(0, -1).map((p) => `->'${p}'`).join("");
|
|
17338
17375
|
const finalExpr = `->>'${pathParts[pathParts.length - 1]}'`;
|
|
17339
17376
|
const placeholder = this.driver.dialect.placeholder(paramIndex++);
|
|
@@ -17764,7 +17801,7 @@ var PostgresDriver = class {
|
|
|
17764
17801
|
const nums = new Array(parts.length);
|
|
17765
17802
|
let isNumericVector = parts.length > 0;
|
|
17766
17803
|
for (let i = 0; i < parts.length; i++) {
|
|
17767
|
-
const n = +parts[i];
|
|
17804
|
+
const n = +(parts[i] ?? "");
|
|
17768
17805
|
if (!Number.isFinite(n)) {
|
|
17769
17806
|
isNumericVector = false;
|
|
17770
17807
|
break;
|
|
@@ -22010,6 +22047,7 @@ function parseCreatedAt(createdAt) {
|
|
|
22010
22047
|
const match = createdAt.match(/^(\d{2})-(\d{2})-(\d{4})_(\d{2})-(\d{2})-(\d{2})$/);
|
|
22011
22048
|
if (match) {
|
|
22012
22049
|
const [, first, second, year, hour, minute, second_time] = match;
|
|
22050
|
+
if (first === void 0 || second === void 0 || year === void 0 || hour === void 0 || minute === void 0 || second_time === void 0) return;
|
|
22013
22051
|
const firstNum = parseInt(first);
|
|
22014
22052
|
const secondNum = parseInt(second);
|
|
22015
22053
|
let month, day;
|