bun-query-builder 0.1.58 → 0.1.60
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/dist/bin/cli.js +345 -220
- package/dist/db.d.ts +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/inflect.d.ts +29 -0
- package/dist/orm.d.ts +67 -8
- package/dist/src/index.js +350 -222
- package/dist/type-inference.d.ts +112 -25
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
package/dist/src/index.js
CHANGED
|
@@ -12061,6 +12061,13 @@ function createSQLiteSQL(filename) {
|
|
|
12061
12061
|
sqlFunction._wrapper = wrapper;
|
|
12062
12062
|
return sqlFunction;
|
|
12063
12063
|
}
|
|
12064
|
+
function sqliteFileFromUrl(url) {
|
|
12065
|
+
const stripped = url.replace(/^(?:sqlite|sqlite3|file):/i, "");
|
|
12066
|
+
if (stripped === url)
|
|
12067
|
+
return url;
|
|
12068
|
+
const path = stripped.startsWith("///") ? stripped.slice(2) : stripped.startsWith("//") ? stripped.slice(2) : stripped;
|
|
12069
|
+
return path || ":memory:";
|
|
12070
|
+
}
|
|
12064
12071
|
function createConnectionString(dialect, dbConfig) {
|
|
12065
12072
|
if ((dialect === "postgres" || dialect === "mysql" || dialect === "singlestore") && process19.env.DB_CONNECTION === dialect) {
|
|
12066
12073
|
const e = process19.env;
|
|
@@ -12074,7 +12081,7 @@ function createConnectionString(dialect, dbConfig) {
|
|
|
12074
12081
|
return `${scheme}://${envUser}:${envPass}@${envHost}${envPort ? `:${envPort}` : ""}/${envDb}${ssl2}`;
|
|
12075
12082
|
}
|
|
12076
12083
|
if (dbConfig.url) {
|
|
12077
|
-
return dbConfig.url;
|
|
12084
|
+
return dialect === "sqlite" ? sqliteFileFromUrl(dbConfig.url) : dbConfig.url;
|
|
12078
12085
|
}
|
|
12079
12086
|
const { database, username, password, host = "localhost", port, ssl } = dbConfig;
|
|
12080
12087
|
const sslQ = ssl || process19.env.DB_SSL === "true" || process19.env.DB_SSL === "1" ? "?ssl=true" : "";
|
|
@@ -12350,9 +12357,37 @@ var init_benchmark = __esm(() => {
|
|
|
12350
12357
|
init_src2();
|
|
12351
12358
|
});
|
|
12352
12359
|
|
|
12360
|
+
// src/inflect.ts
|
|
12361
|
+
function stripTrailingS(name) {
|
|
12362
|
+
return name.endsWith("s") ? name.slice(0, -1) : name;
|
|
12363
|
+
}
|
|
12364
|
+
function inflectSingular(name) {
|
|
12365
|
+
if (name.endsWith("ies") && name.length > 3) {
|
|
12366
|
+
const stem = name.slice(0, -3);
|
|
12367
|
+
const prev = stem[stem.length - 1];
|
|
12368
|
+
if (prev && !"aeiou".includes(prev))
|
|
12369
|
+
return `${stem}y`;
|
|
12370
|
+
}
|
|
12371
|
+
if (name.endsWith("es") && name.length > 2) {
|
|
12372
|
+
const stem = name.slice(0, -2);
|
|
12373
|
+
if (stem.endsWith("s") || stem.endsWith("x") || stem.endsWith("ch") || stem.endsWith("sh"))
|
|
12374
|
+
return stem;
|
|
12375
|
+
}
|
|
12376
|
+
if (name.endsWith("s") && !name.endsWith("ss") && !name.endsWith("us") && !name.endsWith("is"))
|
|
12377
|
+
return name.slice(0, -1);
|
|
12378
|
+
return name;
|
|
12379
|
+
}
|
|
12380
|
+
function singularizerFor(strategy) {
|
|
12381
|
+
if (strategy === "none")
|
|
12382
|
+
return (name) => name;
|
|
12383
|
+
if (strategy === "inflect")
|
|
12384
|
+
return inflectSingular;
|
|
12385
|
+
return stripTrailingS;
|
|
12386
|
+
}
|
|
12387
|
+
|
|
12353
12388
|
// src/pivot.ts
|
|
12354
12389
|
function defaultSingularize(name) {
|
|
12355
|
-
return
|
|
12390
|
+
return singularizerFor(config5.relations?.singularizeStrategy)(name);
|
|
12356
12391
|
}
|
|
12357
12392
|
function resolvePivot(meta, parentTable, relationKey, options = {}) {
|
|
12358
12393
|
const singularize = options.singularize ?? defaultSingularize;
|
|
@@ -12429,6 +12464,9 @@ function* iterateAllPivots(meta, options = {}) {
|
|
|
12429
12464
|
}
|
|
12430
12465
|
}
|
|
12431
12466
|
}
|
|
12467
|
+
var init_pivot = __esm(() => {
|
|
12468
|
+
init_config();
|
|
12469
|
+
});
|
|
12432
12470
|
|
|
12433
12471
|
// src/client.ts
|
|
12434
12472
|
function isRawExpression(expr) {
|
|
@@ -12609,7 +12647,13 @@ class QueryCache {
|
|
|
12609
12647
|
this.cache.clear();
|
|
12610
12648
|
}
|
|
12611
12649
|
setMaxSize(size) {
|
|
12612
|
-
this.maxSize = size;
|
|
12650
|
+
this.maxSize = Math.max(0, Math.floor(size));
|
|
12651
|
+
while (this.cache.size > this.maxSize) {
|
|
12652
|
+
const lruKey = this.cache.keys().next().value;
|
|
12653
|
+
if (lruKey === undefined)
|
|
12654
|
+
break;
|
|
12655
|
+
this.cache.delete(lruKey);
|
|
12656
|
+
}
|
|
12613
12657
|
}
|
|
12614
12658
|
}
|
|
12615
12659
|
function isRetriableTxError(err) {
|
|
@@ -12714,8 +12758,7 @@ function computeBackoffMs(attempt, cfg) {
|
|
|
12714
12758
|
const max = Math.max(base, cfg?.maxMs ?? 2000);
|
|
12715
12759
|
let ms = Math.min(max, base * factor ** Math.max(0, attempt - 1));
|
|
12716
12760
|
if (cfg?.jitter) {
|
|
12717
|
-
|
|
12718
|
-
ms = ms - jitter / 2;
|
|
12761
|
+
ms = Math.min(max, ms * (0.9 + Math.random() * 0.2));
|
|
12719
12762
|
}
|
|
12720
12763
|
return Math.floor(ms);
|
|
12721
12764
|
}
|
|
@@ -12967,11 +13010,7 @@ function createQueryBuilder(state) {
|
|
|
12967
13010
|
const pivotColumns = new Map;
|
|
12968
13011
|
const pivotConfigRelations = new Set;
|
|
12969
13012
|
let cacheTtl = 60000;
|
|
12970
|
-
const singularize = (name) =>
|
|
12971
|
-
if (config5.relations.singularizeStrategy === "none")
|
|
12972
|
-
return name;
|
|
12973
|
-
return name.endsWith("s") ? name.slice(0, -1) : name;
|
|
12974
|
-
};
|
|
13013
|
+
const singularize = (name) => singularizerFor(config5.relations.singularizeStrategy)(name);
|
|
12975
13014
|
const resolvePivotLocal = (relationKey) => {
|
|
12976
13015
|
if (!meta)
|
|
12977
13016
|
return null;
|
|
@@ -15447,6 +15486,7 @@ function createQueryBuilder(state) {
|
|
|
15447
15486
|
const colCount = keys.length;
|
|
15448
15487
|
const totalParams = rowCount * colCount;
|
|
15449
15488
|
params.length = totalParams;
|
|
15489
|
+
const columnList = isPostgres ? keys.map((k) => quoteId(k)).join(",") : keys.join(",");
|
|
15450
15490
|
if (rowCount === 1) {
|
|
15451
15491
|
if (!isPostgres) {
|
|
15452
15492
|
let cols = quoteId(keys[0]);
|
|
@@ -15459,7 +15499,6 @@ function createQueryBuilder(state) {
|
|
|
15459
15499
|
}
|
|
15460
15500
|
sqlText = `INSERT INTO ${quoteId(table)}(${cols})VALUES(${placeholders})`;
|
|
15461
15501
|
} else {
|
|
15462
|
-
const columnList = keys.map((k) => quoteId(k)).join(",");
|
|
15463
15502
|
sqlText = `INSERT INTO ${quoteId(table)}(${columnList})VALUES(`;
|
|
15464
15503
|
for (let c = 0;c < colCount; c++) {
|
|
15465
15504
|
if (c > 0)
|
|
@@ -15470,8 +15509,8 @@ function createQueryBuilder(state) {
|
|
|
15470
15509
|
sqlText += ")";
|
|
15471
15510
|
}
|
|
15472
15511
|
} else {
|
|
15473
|
-
const
|
|
15474
|
-
sqlText = `INSERT INTO ${quoteId(table)}(${
|
|
15512
|
+
const columnList2 = keys.map((k) => quoteId(k)).join(",");
|
|
15513
|
+
sqlText = `INSERT INTO ${quoteId(table)}(${columnList2})VALUES`;
|
|
15475
15514
|
let pidx = 0;
|
|
15476
15515
|
for (let r = 0;r < rowCount; r++) {
|
|
15477
15516
|
const row = rows[r];
|
|
@@ -16027,11 +16066,13 @@ function createQueryBuilder(state) {
|
|
|
16027
16066
|
}
|
|
16028
16067
|
},
|
|
16029
16068
|
async savepoint(fn) {
|
|
16069
|
+
if (state?.inTransaction !== true)
|
|
16070
|
+
throw new Error("savepoint() must be called inside a transaction");
|
|
16030
16071
|
const s = _sql;
|
|
16031
16072
|
if (!s || typeof s.savepoint !== "function")
|
|
16032
|
-
throw new Error("savepoint()
|
|
16073
|
+
throw new Error("savepoint() is not supported by the active connection");
|
|
16033
16074
|
return await s.savepoint(async (sp) => {
|
|
16034
|
-
const qb = createQueryBuilder({ sql: sp, meta, schema });
|
|
16075
|
+
const qb = createQueryBuilder({ sql: sp, meta, schema, inTransaction: true });
|
|
16035
16076
|
return await fn(qb);
|
|
16036
16077
|
});
|
|
16037
16078
|
},
|
|
@@ -16448,6 +16489,7 @@ var SQL_PATTERNS, SAFE_WHERE_OPERATORS, warnedSqlFragmentContexts, queryCache, r
|
|
|
16448
16489
|
var init_client = __esm(() => {
|
|
16449
16490
|
init_config();
|
|
16450
16491
|
init_db();
|
|
16492
|
+
init_pivot();
|
|
16451
16493
|
SQL_PATTERNS = {
|
|
16452
16494
|
SELECT_STAR: /^SELECT\s+\*/i,
|
|
16453
16495
|
SELECT: /^SELECT\s+/i,
|
|
@@ -17048,7 +17090,7 @@ var init_db_info = __esm(() => {
|
|
|
17048
17090
|
// src/actions/db-optimize.ts
|
|
17049
17091
|
import process22 from "process";
|
|
17050
17092
|
async function dbOptimize(options = {}) {
|
|
17051
|
-
const dialect = options.dialect || process22.env.DB_DIALECT || "postgres";
|
|
17093
|
+
const dialect = options.dialect || process22.env.DB_DIALECT || config5.dialect || "postgres";
|
|
17052
17094
|
const aggressive = options.aggressive || false;
|
|
17053
17095
|
if (options.verbose) {
|
|
17054
17096
|
console.log(`Optimizing ${dialect} database${aggressive ? " (aggressive mode)" : ""}...`);
|
|
@@ -17143,7 +17185,7 @@ var init_db_optimize = __esm(() => {
|
|
|
17143
17185
|
// src/actions/db-wipe.ts
|
|
17144
17186
|
import process23 from "process";
|
|
17145
17187
|
async function dbWipe(options = {}) {
|
|
17146
|
-
const dialect = options.dialect || process23.env.DB_DIALECT || "postgres";
|
|
17188
|
+
const dialect = options.dialect || process23.env.DB_DIALECT || config5.dialect || "postgres";
|
|
17147
17189
|
if (options.verbose) {
|
|
17148
17190
|
console.log(`Wiping all tables from ${dialect} database...`);
|
|
17149
17191
|
}
|
|
@@ -18761,7 +18803,7 @@ async function resetDatabase(dir, opts = {}) {
|
|
|
18761
18803
|
if (!dir) {
|
|
18762
18804
|
dir = join9(process25.cwd(), "app/Models");
|
|
18763
18805
|
}
|
|
18764
|
-
const dialect = opts.dialect || "postgres";
|
|
18806
|
+
const dialect = opts.dialect || config5.dialect || "postgres";
|
|
18765
18807
|
const driver = getDialectDriver(dialect);
|
|
18766
18808
|
const workspaceRoot = getWorkspaceRoot();
|
|
18767
18809
|
try {
|
|
@@ -18861,7 +18903,7 @@ async function deleteMigrationFiles(dir, workspaceRoot, opts = {}) {
|
|
|
18861
18903
|
if (!workspaceRoot) {
|
|
18862
18904
|
workspaceRoot = getWorkspaceRoot();
|
|
18863
18905
|
}
|
|
18864
|
-
const dialect = String(opts.dialect || "postgres");
|
|
18906
|
+
const dialect = String(opts.dialect || config5.dialect || "postgres");
|
|
18865
18907
|
const snapshotPath = getSnapshotPath(workspaceRoot, dialect);
|
|
18866
18908
|
if (existsSync16(snapshotPath)) {
|
|
18867
18909
|
unlinkSync(snapshotPath);
|
|
@@ -20017,6 +20059,23 @@ var init_actions = __esm(() => {
|
|
|
20017
20059
|
init_wait_ready();
|
|
20018
20060
|
});
|
|
20019
20061
|
|
|
20062
|
+
// src/relation-utils.ts
|
|
20063
|
+
function normalizeRelationEntry(entry) {
|
|
20064
|
+
if (typeof entry === "string")
|
|
20065
|
+
return { model: entry };
|
|
20066
|
+
if (entry && typeof entry === "object" && typeof entry.model === "string") {
|
|
20067
|
+
const e = entry;
|
|
20068
|
+
return { model: e.model, foreignKey: e.foreignKey, onDelete: e.onDelete };
|
|
20069
|
+
}
|
|
20070
|
+
return null;
|
|
20071
|
+
}
|
|
20072
|
+
function normalizeRelationList(rel) {
|
|
20073
|
+
if (!rel)
|
|
20074
|
+
return [];
|
|
20075
|
+
const entries = Array.isArray(rel) ? rel : typeof rel === "object" ? Object.values(rel) : [];
|
|
20076
|
+
return entries.map(normalizeRelationEntry).filter((x) => x !== null);
|
|
20077
|
+
}
|
|
20078
|
+
|
|
20020
20079
|
// ../../node_modules/@stacksjs/ts-faker/dist/chunk-aggdkeg4.js
|
|
20021
20080
|
import { existsSync as zS } from "fs";
|
|
20022
20081
|
import { join as YS } from "path";
|
|
@@ -24675,6 +24734,13 @@ function normalizeAttributeKeys(data) {
|
|
|
24675
24734
|
}
|
|
24676
24735
|
return result;
|
|
24677
24736
|
}
|
|
24737
|
+
function normalizeAttributeKeysInPlace(data) {
|
|
24738
|
+
for (const key in data) {
|
|
24739
|
+
if (toSnakeCase(key) !== key)
|
|
24740
|
+
return normalizeAttributeKeys(data);
|
|
24741
|
+
}
|
|
24742
|
+
return data;
|
|
24743
|
+
}
|
|
24678
24744
|
function findAttributeDef(attrs, key) {
|
|
24679
24745
|
if (attrs[key])
|
|
24680
24746
|
return attrs[key];
|
|
@@ -24696,7 +24762,7 @@ class ModelInstance {
|
|
|
24696
24762
|
_relations = {};
|
|
24697
24763
|
constructor(definition, attributes = {}) {
|
|
24698
24764
|
this._definition = definition;
|
|
24699
|
-
this._attributes =
|
|
24765
|
+
this._attributes = normalizeAttributeKeysInPlace({ ...attributes });
|
|
24700
24766
|
this._original = null;
|
|
24701
24767
|
const btmKeys = collectBelongsToManyKeys(definition);
|
|
24702
24768
|
if (btmKeys.size === 0)
|
|
@@ -24752,12 +24818,12 @@ class ModelInstance {
|
|
|
24752
24818
|
only(keys) {
|
|
24753
24819
|
const out = {};
|
|
24754
24820
|
for (const k2 of keys) {
|
|
24755
|
-
out[k2] = this._attributes[k2];
|
|
24821
|
+
out[k2] = this._attributes[toSnakeCase(k2)];
|
|
24756
24822
|
}
|
|
24757
24823
|
return out;
|
|
24758
24824
|
}
|
|
24759
24825
|
except(keys) {
|
|
24760
|
-
const drop = new Set(keys.map((k2) => k2));
|
|
24826
|
+
const drop = new Set(keys.map((k2) => toSnakeCase(k2)));
|
|
24761
24827
|
const out = {};
|
|
24762
24828
|
for (const k2 of Object.keys(this._attributes)) {
|
|
24763
24829
|
if (!drop.has(k2))
|
|
@@ -24785,7 +24851,8 @@ class ModelInstance {
|
|
|
24785
24851
|
if (this._original === null)
|
|
24786
24852
|
return false;
|
|
24787
24853
|
if (column) {
|
|
24788
|
-
|
|
24854
|
+
const key = toSnakeCase(column);
|
|
24855
|
+
return this._attributes[key] !== this._original[key];
|
|
24789
24856
|
}
|
|
24790
24857
|
return Object.keys(this._attributes).some((k2) => this._attributes[k2] !== this._original[k2]);
|
|
24791
24858
|
}
|
|
@@ -24794,7 +24861,7 @@ class ModelInstance {
|
|
|
24794
24861
|
}
|
|
24795
24862
|
getOriginal(column) {
|
|
24796
24863
|
const orig = this.getOriginalAttributes();
|
|
24797
|
-
return orig[column];
|
|
24864
|
+
return orig[toSnakeCase(column)];
|
|
24798
24865
|
}
|
|
24799
24866
|
getChanges() {
|
|
24800
24867
|
if (this._original === null)
|
|
@@ -24833,7 +24900,7 @@ class ModelInstance {
|
|
|
24833
24900
|
const setters = this._definition.set || {};
|
|
24834
24901
|
for (const [key, setter] of Object.entries(setters)) {
|
|
24835
24902
|
if (this.isDirty(key)) {
|
|
24836
|
-
this._attributes[key] = setter(this._attributes);
|
|
24903
|
+
this._attributes[toSnakeCase(key)] = setter(this._attributes);
|
|
24837
24904
|
}
|
|
24838
24905
|
}
|
|
24839
24906
|
if (this._attributes[pk]) {
|
|
@@ -24996,6 +25063,9 @@ class ModelInstance {
|
|
|
24996
25063
|
return json;
|
|
24997
25064
|
}
|
|
24998
25065
|
}
|
|
25066
|
+
function sqlColumn(name) {
|
|
25067
|
+
return toSnakeCase(name);
|
|
25068
|
+
}
|
|
24999
25069
|
function toSnakeCase(str) {
|
|
25000
25070
|
let cached = snakeCaseCache.get(str);
|
|
25001
25071
|
if (cached !== undefined)
|
|
@@ -25044,6 +25114,34 @@ function resolveRelation(definition, relationName) {
|
|
|
25044
25114
|
}
|
|
25045
25115
|
return null;
|
|
25046
25116
|
}
|
|
25117
|
+
function findBelongsToEntry() {
|
|
25118
|
+
const rel = definition.belongsTo;
|
|
25119
|
+
if (!rel)
|
|
25120
|
+
return null;
|
|
25121
|
+
const lower = relationName.toLowerCase();
|
|
25122
|
+
const unwrap = (entry) => {
|
|
25123
|
+
if (typeof entry === "string")
|
|
25124
|
+
return { model: entry };
|
|
25125
|
+
if (entry && typeof entry === "object" && typeof entry.model === "string")
|
|
25126
|
+
return { model: entry.model, foreignKey: entry.foreignKey };
|
|
25127
|
+
return null;
|
|
25128
|
+
};
|
|
25129
|
+
if (Array.isArray(rel)) {
|
|
25130
|
+
for (const item of rel) {
|
|
25131
|
+
const e2 = unwrap(item);
|
|
25132
|
+
if (e2 && e2.model.toLowerCase() === lower)
|
|
25133
|
+
return e2;
|
|
25134
|
+
}
|
|
25135
|
+
return null;
|
|
25136
|
+
}
|
|
25137
|
+
if (typeof rel === "object") {
|
|
25138
|
+
for (const [key, value] of Object.entries(rel)) {
|
|
25139
|
+
if (key === relationName || key.toLowerCase() === lower)
|
|
25140
|
+
return unwrap(value);
|
|
25141
|
+
}
|
|
25142
|
+
}
|
|
25143
|
+
return null;
|
|
25144
|
+
}
|
|
25047
25145
|
function findBelongsToManyEntry() {
|
|
25048
25146
|
const rel = definition.belongsToMany;
|
|
25049
25147
|
if (!rel)
|
|
@@ -25083,12 +25181,13 @@ function resolveRelation(definition, relationName) {
|
|
|
25083
25181
|
const foreignKey = toSnakeCase(parentName) + "_id";
|
|
25084
25182
|
return { type: "hasOne", relatedModelName: hasOneModel, relatedTable, foreignKey, localKey: parentPk };
|
|
25085
25183
|
}
|
|
25086
|
-
const
|
|
25087
|
-
if (
|
|
25184
|
+
const belongsToEntry = findBelongsToEntry();
|
|
25185
|
+
if (belongsToEntry) {
|
|
25186
|
+
const belongsToModel = belongsToEntry.model;
|
|
25088
25187
|
const relatedModel = getModelFromRegistry(belongsToModel);
|
|
25089
25188
|
const relatedTable = relatedModel?.getTable?.() || toTableName(belongsToModel);
|
|
25090
25189
|
const relatedPk = relatedModel?.getDefinition?.()?.primaryKey || "id";
|
|
25091
|
-
const foreignKey = toSnakeCase(belongsToModel)
|
|
25190
|
+
const foreignKey = belongsToEntry.foreignKey || `${toSnakeCase(belongsToModel)}_id`;
|
|
25092
25191
|
return { type: "belongsTo", relatedModelName: belongsToModel, relatedTable, foreignKey, localKey: relatedPk };
|
|
25093
25192
|
}
|
|
25094
25193
|
const found = findBelongsToManyEntry();
|
|
@@ -25110,12 +25209,12 @@ function resolveRelation(definition, relationName) {
|
|
|
25110
25209
|
}
|
|
25111
25210
|
pivotTable = throughModel.getTable?.() || throughModel.getDefinition?.()?.table || toTableName(config6.through);
|
|
25112
25211
|
} else {
|
|
25113
|
-
const a2 =
|
|
25114
|
-
const b2 =
|
|
25212
|
+
const a2 = singularizeWord(parentTable);
|
|
25213
|
+
const b2 = singularizeWord(relatedTable);
|
|
25115
25214
|
pivotTable = [a2, b2].sort().join("_");
|
|
25116
25215
|
}
|
|
25117
|
-
const pivotFkParent = config6?.foreignKey || `${
|
|
25118
|
-
const pivotFkRelated = config6?.relatedKey || `${
|
|
25216
|
+
const pivotFkParent = config6?.foreignKey || `${singularizeWord(parentTable)}_id`;
|
|
25217
|
+
const pivotFkRelated = config6?.relatedKey || `${singularizeWord(relatedTable)}_id`;
|
|
25119
25218
|
const pivotColumns = [];
|
|
25120
25219
|
if (config6?.pivot?.columns) {
|
|
25121
25220
|
for (const k2 of Object.keys(config6.pivot.columns))
|
|
@@ -25183,8 +25282,17 @@ function resolveRelation(definition, relationName) {
|
|
|
25183
25282
|
return hot;
|
|
25184
25283
|
return null;
|
|
25185
25284
|
}
|
|
25285
|
+
function distinctParentIds(instances, pk) {
|
|
25286
|
+
const seen = new Set;
|
|
25287
|
+
for (const i2 of instances) {
|
|
25288
|
+
const v2 = i2.get(pk);
|
|
25289
|
+
if (v2 != null)
|
|
25290
|
+
seen.add(v2);
|
|
25291
|
+
}
|
|
25292
|
+
return [...seen];
|
|
25293
|
+
}
|
|
25186
25294
|
function singularizeWord(table) {
|
|
25187
|
-
return
|
|
25295
|
+
return singularizerFor(config5.relations?.singularizeStrategy)(table);
|
|
25188
25296
|
}
|
|
25189
25297
|
|
|
25190
25298
|
class BelongsToManyRelationBuilder {
|
|
@@ -25587,7 +25695,7 @@ class ModelQueryBuilder {
|
|
|
25587
25695
|
}
|
|
25588
25696
|
whereNotBetween(column, range) {
|
|
25589
25697
|
assertValidIdentifier(column, "whereNotBetween(column)");
|
|
25590
|
-
const col = column;
|
|
25698
|
+
const col = sqlColumn(column);
|
|
25591
25699
|
this._wheres.push({
|
|
25592
25700
|
raw: `(${col} < ? OR ${col} > ?)`,
|
|
25593
25701
|
rawParams: [range[0], range[1]],
|
|
@@ -25633,7 +25741,10 @@ class ModelQueryBuilder {
|
|
|
25633
25741
|
return this;
|
|
25634
25742
|
}
|
|
25635
25743
|
with(...relations) {
|
|
25636
|
-
|
|
25744
|
+
for (const r2 of relations) {
|
|
25745
|
+
if (!this._withRelations.includes(r2))
|
|
25746
|
+
this._withRelations.push(r2);
|
|
25747
|
+
}
|
|
25637
25748
|
return this;
|
|
25638
25749
|
}
|
|
25639
25750
|
getWithRelations() {
|
|
@@ -25649,13 +25760,14 @@ class ModelQueryBuilder {
|
|
|
25649
25760
|
if (w.rawParams && w.rawParams.length > 0)
|
|
25650
25761
|
params.push(...w.rawParams);
|
|
25651
25762
|
} else if (w.value === null) {
|
|
25652
|
-
|
|
25763
|
+
const col = sqlColumn(w.column);
|
|
25764
|
+
clause = w.operator === "=" ? `${col} IS NULL` : `${col} IS NOT NULL`;
|
|
25653
25765
|
} else if (w.operator === "in" || w.operator === "not in") {
|
|
25654
25766
|
const arr = w.value;
|
|
25655
|
-
clause = `${w.column} ${w.operator.toUpperCase()} (${arr.map(() => "?").join(", ")})`;
|
|
25767
|
+
clause = `${sqlColumn(w.column)} ${w.operator.toUpperCase()} (${arr.map(() => "?").join(", ")})`;
|
|
25656
25768
|
params.push(...arr);
|
|
25657
25769
|
} else {
|
|
25658
|
-
clause = `${w.column} ${w.operator} ?`;
|
|
25770
|
+
clause = `${sqlColumn(w.column)} ${w.operator} ?`;
|
|
25659
25771
|
params.push(w.value);
|
|
25660
25772
|
}
|
|
25661
25773
|
clauses.push(i2 === 0 ? clause : `${w.boolean.toUpperCase()} ${clause}`);
|
|
@@ -25676,13 +25788,14 @@ class ModelQueryBuilder {
|
|
|
25676
25788
|
}
|
|
25677
25789
|
buildQuery() {
|
|
25678
25790
|
const params = [];
|
|
25679
|
-
|
|
25791
|
+
const cols = this._select.map((c2) => c2 === "*" ? c2 : sqlColumn(c2));
|
|
25792
|
+
let sql2 = `SELECT ${cols.join(", ")} FROM ${this._definition.table}`;
|
|
25680
25793
|
const whereBody = this.composeWhere(params);
|
|
25681
25794
|
if (whereBody) {
|
|
25682
25795
|
sql2 += ` WHERE ${whereBody}`;
|
|
25683
25796
|
}
|
|
25684
25797
|
if (this._orderBy.length > 0) {
|
|
25685
|
-
sql2 += ` ORDER BY ${this._orderBy.map((o2) => `${o2.column} ${o2.direction.toUpperCase()}`).join(", ")}`;
|
|
25798
|
+
sql2 += ` ORDER BY ${this._orderBy.map((o2) => `${sqlColumn(o2.column)} ${o2.direction.toUpperCase()}`).join(", ")}`;
|
|
25686
25799
|
}
|
|
25687
25800
|
if (this._limit !== undefined)
|
|
25688
25801
|
sql2 += ` LIMIT ${this._limit}`;
|
|
@@ -25696,165 +25809,168 @@ class ModelQueryBuilder {
|
|
|
25696
25809
|
async eagerLoadRelations(instances) {
|
|
25697
25810
|
if (instances.length === 0 || this._withRelations.length === 0)
|
|
25698
25811
|
return;
|
|
25812
|
+
await Promise.all(this._withRelations.map((r2) => this.eagerLoadRelation(r2, instances)));
|
|
25813
|
+
}
|
|
25814
|
+
async eagerLoadRelation(relationName, instances) {
|
|
25699
25815
|
const exec = getExecutor();
|
|
25700
25816
|
const pk = this._definition.primaryKey || "id";
|
|
25701
|
-
|
|
25702
|
-
|
|
25703
|
-
|
|
25704
|
-
|
|
25705
|
-
|
|
25706
|
-
|
|
25707
|
-
|
|
25708
|
-
|
|
25709
|
-
|
|
25710
|
-
|
|
25711
|
-
|
|
25712
|
-
|
|
25713
|
-
|
|
25714
|
-
|
|
25715
|
-
|
|
25716
|
-
|
|
25717
|
-
|
|
25718
|
-
|
|
25719
|
-
|
|
25720
|
-
|
|
25721
|
-
|
|
25722
|
-
|
|
25723
|
-
|
|
25724
|
-
|
|
25725
|
-
|
|
25726
|
-
grouped.get(fkVal).push(row);
|
|
25727
|
-
}
|
|
25728
|
-
for (const instance of instances) {
|
|
25729
|
-
const related = grouped.get(instance.get(pk)) || [];
|
|
25730
|
-
instance.setRelation(relationName, related.map((r2) => new ModelInstance(relDef, r2)));
|
|
25731
|
-
}
|
|
25732
|
-
} else {
|
|
25733
|
-
const byFk = new Map;
|
|
25734
|
-
for (const row of rows) {
|
|
25735
|
-
byFk.set(row[rel.foreignKey], row);
|
|
25736
|
-
}
|
|
25737
|
-
for (const instance of instances) {
|
|
25738
|
-
const row = byFk.get(instance.get(pk));
|
|
25739
|
-
instance.setRelation(relationName, row ? new ModelInstance(relDef, row) : null);
|
|
25740
|
-
}
|
|
25817
|
+
const cacheKey = `${this._definition.name}:${relationName}`;
|
|
25818
|
+
let rel = relationCache.get(cacheKey);
|
|
25819
|
+
if (rel === undefined) {
|
|
25820
|
+
rel = resolveRelation(this._definition, relationName);
|
|
25821
|
+
if (relationCache.size >= RELATION_CACHE_MAX)
|
|
25822
|
+
relationCache.clear();
|
|
25823
|
+
relationCache.set(cacheKey, rel);
|
|
25824
|
+
}
|
|
25825
|
+
if (!rel)
|
|
25826
|
+
return;
|
|
25827
|
+
if (rel.type === "hasMany" || rel.type === "hasOne") {
|
|
25828
|
+
const parentIds = distinctParentIds(instances, pk);
|
|
25829
|
+
if (parentIds.length === 0)
|
|
25830
|
+
return;
|
|
25831
|
+
const placeholders = parentIds.map(() => "?").join(", ");
|
|
25832
|
+
const rows = await exec.all(`SELECT * FROM ${rel.relatedTable} WHERE ${rel.foreignKey} IN (${placeholders})`, parentIds);
|
|
25833
|
+
const relatedModelDef = getModelFromRegistry(rel.relatedModelName);
|
|
25834
|
+
const relDef = relatedModelDef?.getDefinition?.() || relatedModelDef?.definition || this._definition;
|
|
25835
|
+
if (rel.type === "hasMany") {
|
|
25836
|
+
const grouped = new Map;
|
|
25837
|
+
for (const row of rows) {
|
|
25838
|
+
const fkVal = row[rel.foreignKey];
|
|
25839
|
+
if (!grouped.has(fkVal))
|
|
25840
|
+
grouped.set(fkVal, []);
|
|
25841
|
+
grouped.get(fkVal).push(row);
|
|
25741
25842
|
}
|
|
25742
|
-
|
|
25743
|
-
|
|
25744
|
-
|
|
25745
|
-
for (const i2 of instances) {
|
|
25746
|
-
const v2 = i2._attributes[rel.foreignKey];
|
|
25747
|
-
if (v2 != null)
|
|
25748
|
-
fkSet.add(v2);
|
|
25843
|
+
for (const instance of instances) {
|
|
25844
|
+
const related = grouped.get(instance.get(pk)) || [];
|
|
25845
|
+
instance.setRelation(relationName, related.map((r2) => new ModelInstance(relDef, r2)));
|
|
25749
25846
|
}
|
|
25750
|
-
|
|
25751
|
-
|
|
25752
|
-
continue;
|
|
25753
|
-
const placeholders = uniqueFkValues.map(() => "?").join(", ");
|
|
25754
|
-
const rows = await exec.all(`SELECT * FROM ${rel.relatedTable} WHERE ${rel.localKey} IN (${placeholders})`, uniqueFkValues);
|
|
25755
|
-
const relatedModelDef = getModelFromRegistry(rel.relatedModelName);
|
|
25756
|
-
const relDef = relatedModelDef?.getDefinition?.() || relatedModelDef?.definition || this._definition;
|
|
25757
|
-
const byPk = new Map;
|
|
25847
|
+
} else {
|
|
25848
|
+
const byFk = new Map;
|
|
25758
25849
|
for (const row of rows) {
|
|
25759
|
-
|
|
25850
|
+
const k2 = row[rel.foreignKey];
|
|
25851
|
+
if (!byFk.has(k2))
|
|
25852
|
+
byFk.set(k2, row);
|
|
25760
25853
|
}
|
|
25761
25854
|
for (const instance of instances) {
|
|
25762
|
-
const
|
|
25763
|
-
const row = byPk.get(fkVal);
|
|
25855
|
+
const row = byFk.get(instance.get(pk));
|
|
25764
25856
|
instance.setRelation(relationName, row ? new ModelInstance(relDef, row) : null);
|
|
25765
25857
|
}
|
|
25766
25858
|
}
|
|
25767
|
-
|
|
25768
|
-
|
|
25769
|
-
|
|
25770
|
-
|
|
25771
|
-
|
|
25772
|
-
|
|
25773
|
-
|
|
25774
|
-
const pivotRows = await exec.all(`SELECT * FROM ${rel.pivotTable} WHERE ${rel.pivotFkParent} IN (${pivotPlaceholders})`, parentIds);
|
|
25775
|
-
if (pivotRows.length === 0) {
|
|
25776
|
-
for (const instance of instances)
|
|
25777
|
-
instance.setRelation(relationName, []);
|
|
25778
|
-
continue;
|
|
25779
|
-
}
|
|
25780
|
-
const relatedIdSet = new Set;
|
|
25781
|
-
for (const p2 of pivotRows) {
|
|
25782
|
-
const v2 = p2[rel.pivotFkRelated];
|
|
25783
|
-
if (v2 != null)
|
|
25784
|
-
relatedIdSet.add(v2);
|
|
25785
|
-
}
|
|
25786
|
-
const relatedIds = [...relatedIdSet];
|
|
25787
|
-
const relatedModelDef = getModelFromRegistry(rel.relatedModelName);
|
|
25788
|
-
const relDef = relatedModelDef?.getDefinition?.() || relatedModelDef?.definition || this._definition;
|
|
25789
|
-
const relatedPk = relDef?.primaryKey || "id";
|
|
25790
|
-
let relatedRows = [];
|
|
25791
|
-
if (relatedIds.length > 0) {
|
|
25792
|
-
const relPlaceholders = relatedIds.map(() => "?").join(", ");
|
|
25793
|
-
relatedRows = await exec.all(`SELECT * FROM ${rel.relatedTable} WHERE ${relatedPk} IN (${relPlaceholders})`, relatedIds);
|
|
25794
|
-
}
|
|
25795
|
-
const relatedByPk = new Map;
|
|
25796
|
-
for (const r2 of relatedRows)
|
|
25797
|
-
relatedByPk.set(r2[relatedPk], r2);
|
|
25798
|
-
const pivotByParent = new Map;
|
|
25799
|
-
for (const p2 of pivotRows) {
|
|
25800
|
-
const key = p2[rel.pivotFkParent];
|
|
25801
|
-
if (!pivotByParent.has(key))
|
|
25802
|
-
pivotByParent.set(key, []);
|
|
25803
|
-
pivotByParent.get(key).push(p2);
|
|
25804
|
-
}
|
|
25805
|
-
const pivotKnownKeys = new Set([rel.pivotFkParent, rel.pivotFkRelated]);
|
|
25806
|
-
for (const instance of instances) {
|
|
25807
|
-
const parentVal = instance.get(pk);
|
|
25808
|
-
const myPivots = pivotByParent.get(parentVal) || [];
|
|
25809
|
-
const relatedInstances = myPivots.map((p2) => {
|
|
25810
|
-
const relRow = relatedByPk.get(p2[rel.pivotFkRelated]);
|
|
25811
|
-
if (!relRow)
|
|
25812
|
-
return null;
|
|
25813
|
-
const inst = new ModelInstance(relDef, relRow);
|
|
25814
|
-
const extras = {};
|
|
25815
|
-
for (const [k2, v2] of Object.entries(p2)) {
|
|
25816
|
-
if (!pivotKnownKeys.has(k2))
|
|
25817
|
-
extras[k2] = v2;
|
|
25818
|
-
}
|
|
25819
|
-
inst.pivot = extras;
|
|
25820
|
-
return inst;
|
|
25821
|
-
}).filter((x2) => x2 !== null);
|
|
25822
|
-
instance.setRelation(relationName, relatedInstances);
|
|
25823
|
-
}
|
|
25859
|
+
}
|
|
25860
|
+
if (rel.type === "belongsTo") {
|
|
25861
|
+
const fkSet = new Set;
|
|
25862
|
+
for (const i2 of instances) {
|
|
25863
|
+
const v2 = i2._attributes[rel.foreignKey];
|
|
25864
|
+
if (v2 != null)
|
|
25865
|
+
fkSet.add(v2);
|
|
25824
25866
|
}
|
|
25825
|
-
|
|
25826
|
-
|
|
25827
|
-
|
|
25828
|
-
|
|
25829
|
-
|
|
25830
|
-
|
|
25831
|
-
|
|
25832
|
-
|
|
25833
|
-
|
|
25834
|
-
|
|
25867
|
+
const uniqueFkValues = [...fkSet];
|
|
25868
|
+
if (uniqueFkValues.length === 0)
|
|
25869
|
+
return;
|
|
25870
|
+
const placeholders = uniqueFkValues.map(() => "?").join(", ");
|
|
25871
|
+
const rows = await exec.all(`SELECT * FROM ${rel.relatedTable} WHERE ${rel.localKey} IN (${placeholders})`, uniqueFkValues);
|
|
25872
|
+
const relatedModelDef = getModelFromRegistry(rel.relatedModelName);
|
|
25873
|
+
const relDef = relatedModelDef?.getDefinition?.() || relatedModelDef?.definition || this._definition;
|
|
25874
|
+
const byPk = new Map;
|
|
25875
|
+
for (const row of rows) {
|
|
25876
|
+
byPk.set(row[rel.localKey], row);
|
|
25877
|
+
}
|
|
25878
|
+
for (const instance of instances) {
|
|
25879
|
+
const fkVal = instance._attributes[rel.foreignKey];
|
|
25880
|
+
const row = byPk.get(fkVal);
|
|
25881
|
+
instance.setRelation(relationName, row ? new ModelInstance(relDef, row) : null);
|
|
25882
|
+
}
|
|
25883
|
+
}
|
|
25884
|
+
if (rel.type === "belongsToMany") {
|
|
25885
|
+
const parentIds = distinctParentIds(instances, pk);
|
|
25886
|
+
if (parentIds.length === 0)
|
|
25887
|
+
return;
|
|
25888
|
+
if (!rel.pivotTable || !rel.pivotFkParent || !rel.pivotFkRelated)
|
|
25889
|
+
return;
|
|
25890
|
+
const pivotPlaceholders = parentIds.map(() => "?").join(", ");
|
|
25891
|
+
const pivotRows = await exec.all(`SELECT * FROM ${rel.pivotTable} WHERE ${rel.pivotFkParent} IN (${pivotPlaceholders})`, parentIds);
|
|
25892
|
+
if (pivotRows.length === 0) {
|
|
25893
|
+
for (const instance of instances)
|
|
25894
|
+
instance.setRelation(relationName, []);
|
|
25895
|
+
return;
|
|
25896
|
+
}
|
|
25897
|
+
const relatedIdSet = new Set;
|
|
25898
|
+
for (const p2 of pivotRows) {
|
|
25899
|
+
const v2 = p2[rel.pivotFkRelated];
|
|
25900
|
+
if (v2 != null)
|
|
25901
|
+
relatedIdSet.add(v2);
|
|
25902
|
+
}
|
|
25903
|
+
const relatedIds = [...relatedIdSet];
|
|
25904
|
+
const relatedModelDef = getModelFromRegistry(rel.relatedModelName);
|
|
25905
|
+
const relDef = relatedModelDef?.getDefinition?.() || relatedModelDef?.definition || this._definition;
|
|
25906
|
+
const relatedPk = relDef?.primaryKey || "id";
|
|
25907
|
+
let relatedRows = [];
|
|
25908
|
+
if (relatedIds.length > 0) {
|
|
25909
|
+
const relPlaceholders = relatedIds.map(() => "?").join(", ");
|
|
25910
|
+
relatedRows = await exec.all(`SELECT * FROM ${rel.relatedTable} WHERE ${relatedPk} IN (${relPlaceholders})`, relatedIds);
|
|
25911
|
+
}
|
|
25912
|
+
const relatedByPk = new Map;
|
|
25913
|
+
for (const r2 of relatedRows)
|
|
25914
|
+
relatedByPk.set(r2[relatedPk], r2);
|
|
25915
|
+
const pivotByParent = new Map;
|
|
25916
|
+
for (const p2 of pivotRows) {
|
|
25917
|
+
const key = p2[rel.pivotFkParent];
|
|
25918
|
+
if (!pivotByParent.has(key))
|
|
25919
|
+
pivotByParent.set(key, []);
|
|
25920
|
+
pivotByParent.get(key).push(p2);
|
|
25921
|
+
}
|
|
25922
|
+
const pivotKnownKeys = new Set([rel.pivotFkParent, rel.pivotFkRelated]);
|
|
25923
|
+
for (const instance of instances) {
|
|
25924
|
+
const parentVal = instance.get(pk);
|
|
25925
|
+
const myPivots = pivotByParent.get(parentVal) || [];
|
|
25926
|
+
const relatedInstances = myPivots.map((p2) => {
|
|
25927
|
+
const relRow = relatedByPk.get(p2[rel.pivotFkRelated]);
|
|
25928
|
+
if (!relRow)
|
|
25929
|
+
return null;
|
|
25930
|
+
const inst = new ModelInstance(relDef, relRow);
|
|
25931
|
+
const extras = {};
|
|
25932
|
+
for (const [k2, v2] of Object.entries(p2)) {
|
|
25933
|
+
if (!pivotKnownKeys.has(k2))
|
|
25934
|
+
extras[k2] = v2;
|
|
25935
|
+
}
|
|
25936
|
+
inst.pivot = extras;
|
|
25937
|
+
return inst;
|
|
25938
|
+
}).filter((x2) => x2 !== null);
|
|
25939
|
+
instance.setRelation(relationName, relatedInstances);
|
|
25940
|
+
}
|
|
25941
|
+
}
|
|
25942
|
+
if (rel.type === "hasManyThrough" || rel.type === "hasOneThrough") {
|
|
25943
|
+
const parentIds = distinctParentIds(instances, pk);
|
|
25944
|
+
if (parentIds.length === 0)
|
|
25945
|
+
return;
|
|
25946
|
+
const throughPk = rel.throughLocalKey || "id";
|
|
25947
|
+
const throughPh = parentIds.map(() => "?").join(", ");
|
|
25948
|
+
const throughRows = await exec.all(`SELECT ${throughPk}, ${rel.throughForeignKey} FROM ${rel.throughTable} WHERE ${rel.throughForeignKey} IN (${throughPh})`, parentIds);
|
|
25949
|
+
if (throughRows.length === 0) {
|
|
25950
|
+
for (const instance of instances)
|
|
25951
|
+
instance.setRelation(relationName, rel.type === "hasManyThrough" ? [] : null);
|
|
25952
|
+
return;
|
|
25953
|
+
}
|
|
25954
|
+
const throughToParent = new Map;
|
|
25955
|
+
for (const t2 of throughRows)
|
|
25956
|
+
throughToParent.set(t2[throughPk], t2[rel.throughForeignKey]);
|
|
25957
|
+
const throughIds = [...new Set(throughRows.map((t2) => t2[throughPk]))];
|
|
25958
|
+
const targetPh = throughIds.map(() => "?").join(", ");
|
|
25959
|
+
const targetRows = await exec.all(`SELECT * FROM ${rel.relatedTable} WHERE ${rel.targetForeignKey} IN (${targetPh})`, throughIds);
|
|
25960
|
+
const relatedModelDef = getModelFromRegistry(rel.relatedModelName);
|
|
25961
|
+
const relDef = relatedModelDef?.getDefinition?.() || relatedModelDef?.definition || this._definition;
|
|
25962
|
+
const byParent = new Map;
|
|
25963
|
+
for (const row of targetRows) {
|
|
25964
|
+
const parentVal = throughToParent.get(row[rel.targetForeignKey]);
|
|
25965
|
+
if (parentVal == null)
|
|
25835
25966
|
continue;
|
|
25836
|
-
|
|
25837
|
-
|
|
25838
|
-
|
|
25839
|
-
|
|
25840
|
-
|
|
25841
|
-
const
|
|
25842
|
-
|
|
25843
|
-
const relatedModelDef = getModelFromRegistry(rel.relatedModelName);
|
|
25844
|
-
const relDef = relatedModelDef?.getDefinition?.() || relatedModelDef?.definition || this._definition;
|
|
25845
|
-
const byParent = new Map;
|
|
25846
|
-
for (const row of targetRows) {
|
|
25847
|
-
const parentVal = throughToParent.get(row[rel.targetForeignKey]);
|
|
25848
|
-
if (parentVal == null)
|
|
25849
|
-
continue;
|
|
25850
|
-
if (!byParent.has(parentVal))
|
|
25851
|
-
byParent.set(parentVal, []);
|
|
25852
|
-
byParent.get(parentVal).push(new ModelInstance(relDef, row));
|
|
25853
|
-
}
|
|
25854
|
-
for (const instance of instances) {
|
|
25855
|
-
const group = byParent.get(instance.get(pk)) || [];
|
|
25856
|
-
instance.setRelation(relationName, rel.type === "hasManyThrough" ? group : group[0] ?? null);
|
|
25857
|
-
}
|
|
25967
|
+
if (!byParent.has(parentVal))
|
|
25968
|
+
byParent.set(parentVal, []);
|
|
25969
|
+
byParent.get(parentVal).push(new ModelInstance(relDef, row));
|
|
25970
|
+
}
|
|
25971
|
+
for (const instance of instances) {
|
|
25972
|
+
const group = byParent.get(instance.get(pk)) || [];
|
|
25973
|
+
instance.setRelation(relationName, rel.type === "hasManyThrough" ? group : group[0] ?? null);
|
|
25858
25974
|
}
|
|
25859
25975
|
}
|
|
25860
25976
|
}
|
|
@@ -25914,7 +26030,8 @@ class ModelQueryBuilder {
|
|
|
25914
26030
|
assertValidIdentifier(column, "increment(column)");
|
|
25915
26031
|
const exec = getExecutor();
|
|
25916
26032
|
const params = [amount];
|
|
25917
|
-
|
|
26033
|
+
const incCol = sqlColumn(column);
|
|
26034
|
+
let sql2 = `UPDATE ${this._definition.table} SET ${incCol} = ${incCol} + ?`;
|
|
25918
26035
|
if (timestampsEnabled(this._definition)) {
|
|
25919
26036
|
sql2 += `, updated_at = ?`;
|
|
25920
26037
|
params.push(formatNow());
|
|
@@ -25972,26 +26089,27 @@ class ModelQueryBuilder {
|
|
|
25972
26089
|
assertValidIdentifier(column, "pluck(column)");
|
|
25973
26090
|
const exec = getExecutor();
|
|
25974
26091
|
const params = [];
|
|
25975
|
-
|
|
26092
|
+
const pluckCol = sqlColumn(column);
|
|
26093
|
+
let sql2 = `SELECT ${pluckCol} FROM ${this._definition.table}`;
|
|
25976
26094
|
const whereBody = this.composeWhere(params);
|
|
25977
26095
|
if (whereBody) {
|
|
25978
26096
|
sql2 += ` WHERE ${whereBody}`;
|
|
25979
26097
|
}
|
|
25980
26098
|
if (this._orderBy.length > 0) {
|
|
25981
|
-
sql2 += ` ORDER BY ${this._orderBy.map((o2) => `${o2.column} ${o2.direction.toUpperCase()}`).join(", ")}`;
|
|
26099
|
+
sql2 += ` ORDER BY ${this._orderBy.map((o2) => `${sqlColumn(o2.column)} ${o2.direction.toUpperCase()}`).join(", ")}`;
|
|
25982
26100
|
}
|
|
25983
26101
|
if (this._limit !== undefined)
|
|
25984
26102
|
sql2 += ` LIMIT ${this._limit}`;
|
|
25985
26103
|
if (this._offset !== undefined)
|
|
25986
26104
|
sql2 += ` OFFSET ${this._offset}`;
|
|
25987
26105
|
const rows = await exec.all(sql2, params);
|
|
25988
|
-
return rows.map((r2) => r2[
|
|
26106
|
+
return rows.map((r2) => r2[pluckCol]);
|
|
25989
26107
|
}
|
|
25990
26108
|
async aggregate(fn, column) {
|
|
25991
26109
|
assertValidIdentifier(column, `${fn}(column)`);
|
|
25992
26110
|
const exec = getExecutor();
|
|
25993
26111
|
const params = [];
|
|
25994
|
-
let sql2 = `SELECT ${fn}(${column}) as v FROM ${this._definition.table}`;
|
|
26112
|
+
let sql2 = `SELECT ${fn}(${sqlColumn(column)}) as v FROM ${this._definition.table}`;
|
|
25995
26113
|
const whereBody = this.composeWhere(params);
|
|
25996
26114
|
if (whereBody) {
|
|
25997
26115
|
sql2 += ` WHERE ${whereBody}`;
|
|
@@ -26030,7 +26148,7 @@ class ModelQueryBuilder {
|
|
|
26030
26148
|
async update(data) {
|
|
26031
26149
|
const exec = getExecutor();
|
|
26032
26150
|
const entries = Object.entries(data);
|
|
26033
|
-
const sets = entries.map(([k2]) => `${k2} = ?`).join(", ");
|
|
26151
|
+
const sets = entries.map(([k2]) => `${sqlColumn(k2)} = ?`).join(", ");
|
|
26034
26152
|
const params = entries.map(([, v2]) => v2);
|
|
26035
26153
|
if (timestampsEnabled(this._definition)) {
|
|
26036
26154
|
params.push(formatNow());
|
|
@@ -26192,12 +26310,19 @@ function createModel(definition) {
|
|
|
26192
26310
|
}
|
|
26193
26311
|
async function createTableFromModel(definition) {
|
|
26194
26312
|
const exec = getExecutor();
|
|
26195
|
-
const pk = definition.primaryKey || "id";
|
|
26313
|
+
const pk = toSnakeCase(definition.primaryKey || "id");
|
|
26196
26314
|
const columns = [];
|
|
26315
|
+
const emitted = new Set([pk]);
|
|
26197
26316
|
columns.push(definition.autoIncrement !== false ? `${pk} INTEGER PRIMARY KEY AUTOINCREMENT` : `${pk} INTEGER PRIMARY KEY`);
|
|
26198
|
-
if (definition.traits?.useUuid)
|
|
26317
|
+
if (definition.traits?.useUuid) {
|
|
26199
26318
|
columns.push("uuid TEXT UNIQUE");
|
|
26200
|
-
|
|
26319
|
+
emitted.add("uuid");
|
|
26320
|
+
}
|
|
26321
|
+
for (const [attrName, attr] of Object.entries(definition.attributes)) {
|
|
26322
|
+
const name = toSnakeCase(attrName);
|
|
26323
|
+
if (emitted.has(name))
|
|
26324
|
+
continue;
|
|
26325
|
+
emitted.add(name);
|
|
26201
26326
|
let colType = "TEXT";
|
|
26202
26327
|
if (attr.type === "number")
|
|
26203
26328
|
colType = "INTEGER";
|
|
@@ -26218,10 +26343,23 @@ async function createTableFromModel(definition) {
|
|
|
26218
26343
|
}
|
|
26219
26344
|
columns.push(colDef);
|
|
26220
26345
|
}
|
|
26346
|
+
for (const rel of normalizeRelationList(definition.belongsTo)) {
|
|
26347
|
+
const name = rel.foreignKey ?? `${toSnakeCase(rel.model)}_id`;
|
|
26348
|
+
if (emitted.has(name))
|
|
26349
|
+
continue;
|
|
26350
|
+
emitted.add(name);
|
|
26351
|
+
columns.push(`${name} INTEGER`);
|
|
26352
|
+
}
|
|
26221
26353
|
if (timestampsEnabled(definition)) {
|
|
26222
|
-
|
|
26354
|
+
for (const c2 of ["created_at", "updated_at"]) {
|
|
26355
|
+
if (emitted.has(c2))
|
|
26356
|
+
continue;
|
|
26357
|
+
emitted.add(c2);
|
|
26358
|
+
columns.push(`${c2} TEXT`);
|
|
26359
|
+
}
|
|
26223
26360
|
}
|
|
26224
|
-
if (softDeletesEnabled(definition)) {
|
|
26361
|
+
if (softDeletesEnabled(definition) && !emitted.has("deleted_at")) {
|
|
26362
|
+
emitted.add("deleted_at");
|
|
26225
26363
|
columns.push("deleted_at TEXT");
|
|
26226
26364
|
}
|
|
26227
26365
|
await exec.run(`CREATE TABLE IF NOT EXISTS ${definition.table} (${columns.join(", ")})`, []);
|
|
@@ -26264,7 +26402,7 @@ async function seedModel(definition, count, faker) {
|
|
|
26264
26402
|
const data = {};
|
|
26265
26403
|
for (const [name, attr] of Object.entries(definition.attributes)) {
|
|
26266
26404
|
if (attr.factory)
|
|
26267
|
-
data[name] = attr.factory(faker);
|
|
26405
|
+
data[toSnakeCase(name)] = attr.factory(faker);
|
|
26268
26406
|
}
|
|
26269
26407
|
if (timestampsEnabled(definition)) {
|
|
26270
26408
|
const now = formatNow();
|
|
@@ -27765,23 +27903,6 @@ async function loadModels(options) {
|
|
|
27765
27903
|
}
|
|
27766
27904
|
var init_loader = () => {};
|
|
27767
27905
|
|
|
27768
|
-
// src/relation-utils.ts
|
|
27769
|
-
function normalizeRelationEntry(entry) {
|
|
27770
|
-
if (typeof entry === "string")
|
|
27771
|
-
return { model: entry };
|
|
27772
|
-
if (entry && typeof entry === "object" && typeof entry.model === "string") {
|
|
27773
|
-
const e2 = entry;
|
|
27774
|
-
return { model: e2.model, foreignKey: e2.foreignKey, onDelete: e2.onDelete };
|
|
27775
|
-
}
|
|
27776
|
-
return null;
|
|
27777
|
-
}
|
|
27778
|
-
function normalizeRelationList(rel) {
|
|
27779
|
-
if (!rel)
|
|
27780
|
-
return [];
|
|
27781
|
-
const entries = Array.isArray(rel) ? rel : typeof rel === "object" ? Object.values(rel) : [];
|
|
27782
|
-
return entries.map(normalizeRelationEntry).filter((x2) => x2 !== null);
|
|
27783
|
-
}
|
|
27784
|
-
|
|
27785
27906
|
// src/meta.ts
|
|
27786
27907
|
function buildSchemaMeta(models) {
|
|
27787
27908
|
const modelToTable = {};
|
|
@@ -27876,6 +27997,9 @@ function info2(message) {
|
|
|
27876
27997
|
function snakeCase(str) {
|
|
27877
27998
|
return str.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").replace(/(\d)([A-Z])/gi, "$1_$2").toLowerCase();
|
|
27878
27999
|
}
|
|
28000
|
+
function singularizeTable(table) {
|
|
28001
|
+
return singularizerFor(config5.relations?.singularizeStrategy)(table);
|
|
28002
|
+
}
|
|
27879
28003
|
function findWorkspaceRoot6(startPath) {
|
|
27880
28004
|
let currentPath = startPath;
|
|
27881
28005
|
while (currentPath !== dirname12(currentPath)) {
|
|
@@ -28264,7 +28388,7 @@ function buildMigrationPlan2(models, options) {
|
|
|
28264
28388
|
const model = models[modelName];
|
|
28265
28389
|
const traits = model?.traits ?? {};
|
|
28266
28390
|
const modelTable = model.table || `${String(model.name).toLowerCase()}s`;
|
|
28267
|
-
const singular = modelTable
|
|
28391
|
+
const singular = singularizeTable(modelTable);
|
|
28268
28392
|
if (traits.likeable) {
|
|
28269
28393
|
const opts = typeof traits.likeable === "object" ? traits.likeable : {};
|
|
28270
28394
|
const likeTable = opts.table || `${modelTable}_likes`;
|
|
@@ -28331,7 +28455,7 @@ function buildMigrationPlan2(models, options) {
|
|
|
28331
28455
|
if (!btm || typeof btm !== "object" || Array.isArray(btm))
|
|
28332
28456
|
continue;
|
|
28333
28457
|
const parentTable = model.table || `${String(model.name).toLowerCase()}s`;
|
|
28334
|
-
const parentSingular = parentTable
|
|
28458
|
+
const parentSingular = singularizeTable(parentTable);
|
|
28335
28459
|
for (const [relKey, value] of Object.entries(btm)) {
|
|
28336
28460
|
const cfg = value;
|
|
28337
28461
|
if (!cfg || typeof cfg !== "object")
|
|
@@ -28344,7 +28468,7 @@ function buildMigrationPlan2(models, options) {
|
|
|
28344
28468
|
const relatedModelName = cfg.model;
|
|
28345
28469
|
const relatedRaw = models[relatedModelName];
|
|
28346
28470
|
const relatedTable = relatedRaw?.table || `${String(relatedModelName).toLowerCase()}s`;
|
|
28347
|
-
const relatedSingular = relatedTable
|
|
28471
|
+
const relatedSingular = singularizeTable(relatedTable);
|
|
28348
28472
|
const pivotTable = cfg.table || [parentSingular, relatedSingular].sort().join("_");
|
|
28349
28473
|
const fkParent = cfg.foreignKey || `${parentSingular}_id`;
|
|
28350
28474
|
const fkRelated = cfg.relatedKey || `${relatedSingular}_id`;
|
|
@@ -28962,14 +29086,14 @@ function defineSeeder(seederClass) {
|
|
|
28962
29086
|
return seederClass;
|
|
28963
29087
|
}
|
|
28964
29088
|
// src/index.ts
|
|
28965
|
-
var init_src2 = __esm(
|
|
29089
|
+
var init_src2 = __esm(() => {
|
|
28966
29090
|
init_model2();
|
|
28967
29091
|
init_model2();
|
|
28968
29092
|
init_actions();
|
|
28969
29093
|
init_browser();
|
|
28970
29094
|
init_client();
|
|
28971
29095
|
init_model2();
|
|
28972
|
-
|
|
29096
|
+
init_config();
|
|
28973
29097
|
init_drivers();
|
|
28974
29098
|
init_dynamodb_client();
|
|
28975
29099
|
init_dynamodb_single_table();
|
|
@@ -28978,10 +29102,11 @@ var init_src2 = __esm(async () => {
|
|
|
28978
29102
|
init_loader();
|
|
28979
29103
|
init_meta();
|
|
28980
29104
|
init_migrations();
|
|
29105
|
+
init_pivot();
|
|
28981
29106
|
init_orm();
|
|
28982
29107
|
init_sqlite_pragmas();
|
|
28983
29108
|
});
|
|
28984
|
-
|
|
29109
|
+
init_src2();
|
|
28985
29110
|
|
|
28986
29111
|
export {
|
|
28987
29112
|
dbWipe as wipeDatabase,
|
|
@@ -28993,10 +29118,12 @@ export {
|
|
|
28993
29118
|
toDynamoDBItem,
|
|
28994
29119
|
tinker,
|
|
28995
29120
|
tableInfo,
|
|
29121
|
+
stripTrailingS,
|
|
28996
29122
|
startConsole,
|
|
28997
29123
|
stacksModelToEntity,
|
|
28998
29124
|
sqlTypeToAttr,
|
|
28999
29125
|
sql,
|
|
29126
|
+
singularizerFor,
|
|
29000
29127
|
modelShow as showModel,
|
|
29001
29128
|
setQueryCacheMaxSize,
|
|
29002
29129
|
setConfig,
|
|
@@ -29036,6 +29163,7 @@ export {
|
|
|
29036
29163
|
introspectDatabase,
|
|
29037
29164
|
introspect,
|
|
29038
29165
|
inspectTable,
|
|
29166
|
+
inflectSingular,
|
|
29039
29167
|
importData,
|
|
29040
29168
|
hashTableDefinition,
|
|
29041
29169
|
hashMigrationPlan,
|