bun-query-builder 0.1.31 → 0.1.32
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 +147 -53
- package/dist/client.d.ts +31 -0
- package/dist/src/index.js +140 -45
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -12344,6 +12344,14 @@ function* iterateAllPivots(meta, options = {}) {
|
|
|
12344
12344
|
function isRawExpression(expr) {
|
|
12345
12345
|
return typeof expr === "object" && expr !== null && "raw" in expr && typeof expr.raw === "string";
|
|
12346
12346
|
}
|
|
12347
|
+
function raw(strings, ...values) {
|
|
12348
|
+
if (typeof strings === "string")
|
|
12349
|
+
return { raw: strings };
|
|
12350
|
+
let out = strings[0];
|
|
12351
|
+
for (let i = 0;i < values.length; i++)
|
|
12352
|
+
out += formatSubqueryValue(values[i]) + strings[i + 1];
|
|
12353
|
+
return { raw: out };
|
|
12354
|
+
}
|
|
12347
12355
|
function quoteInsertIdent(id) {
|
|
12348
12356
|
return config5.dialect === "mysql" ? `\`${id.replace(/`/g, "``")}\`` : `"${id.replace(/"/g, '""')}"`;
|
|
12349
12357
|
}
|
|
@@ -12412,13 +12420,31 @@ function validateQualifiedIdentifier(value, context) {
|
|
|
12412
12420
|
throw new TypeError(`[query-builder] ${context}: identifier segment '${part}' contains characters outside [A-Za-z0-9_]`);
|
|
12413
12421
|
}
|
|
12414
12422
|
}
|
|
12415
|
-
function
|
|
12416
|
-
if (fragment === null || fragment === undefined) {
|
|
12417
|
-
throw new TypeError(`[query-builder] ${context}: fragment must be a SqlFragment, got ${fragment}`);
|
|
12418
|
-
}
|
|
12423
|
+
function renderRawFragment(fragment, context) {
|
|
12419
12424
|
if (typeof fragment === "string") {
|
|
12420
12425
|
warnOnceBareSqlFragment(context);
|
|
12426
|
+
return fragment;
|
|
12421
12427
|
}
|
|
12428
|
+
if (fragment === null || fragment === undefined)
|
|
12429
|
+
throw new TypeError(`[query-builder] ${context}: fragment must be a SqlFragment, got ${fragment}`);
|
|
12430
|
+
if (isRawExpression(fragment))
|
|
12431
|
+
return fragment.raw;
|
|
12432
|
+
if (typeof fragment === "object") {
|
|
12433
|
+
const f = fragment;
|
|
12434
|
+
if (typeof f.raw === "string")
|
|
12435
|
+
return f.raw;
|
|
12436
|
+
if (typeof f.raw === "function") {
|
|
12437
|
+
const r = f.raw();
|
|
12438
|
+
if (typeof r === "string")
|
|
12439
|
+
return r;
|
|
12440
|
+
}
|
|
12441
|
+
if (typeof f.sql === "string")
|
|
12442
|
+
return f.sql;
|
|
12443
|
+
const s = String(fragment);
|
|
12444
|
+
if (s !== "[object Object]" && s !== "[object Promise]")
|
|
12445
|
+
return s;
|
|
12446
|
+
}
|
|
12447
|
+
throw new TypeError(`[query-builder] ${context}: cannot render this value as a SQL fragment. ` + `A Bun \`sql\`...\`\` query object cannot be converted to SQL text \u2014 pass a ` + `string, or use the exported \`raw\` helper: raw\`count(*) as c\` / raw('age > 18').`);
|
|
12422
12448
|
}
|
|
12423
12449
|
function warnOnceBareSqlFragment(context) {
|
|
12424
12450
|
if (warnedSqlFragmentContexts.has(context))
|
|
@@ -13093,12 +13119,12 @@ function createQueryBuilder(state) {
|
|
|
13093
13119
|
return this;
|
|
13094
13120
|
},
|
|
13095
13121
|
selectRaw(fragment) {
|
|
13096
|
-
|
|
13122
|
+
const frag = renderRawFragment(fragment, "selectRaw(fragment)");
|
|
13097
13123
|
const fromIdx = text.indexOf(" FROM ");
|
|
13098
13124
|
if (fromIdx !== -1) {
|
|
13099
|
-
text = `${text.substring(0, fromIdx)}, ${
|
|
13125
|
+
text = `${text.substring(0, fromIdx)}, ${frag}${text.substring(fromIdx)}`;
|
|
13100
13126
|
} else {
|
|
13101
|
-
text += `, ${
|
|
13127
|
+
text += `, ${frag}`;
|
|
13102
13128
|
}
|
|
13103
13129
|
built = null;
|
|
13104
13130
|
return this;
|
|
@@ -13211,12 +13237,15 @@ function createQueryBuilder(state) {
|
|
|
13211
13237
|
if (cols.length === 0)
|
|
13212
13238
|
return this;
|
|
13213
13239
|
const rendered = cols.map(renderSelectColumn);
|
|
13240
|
+
const distinctMatch = /^SELECT\s+(DISTINCT(?:\s+ON\s+\([^)]*\))?\s+)/i.exec(text);
|
|
13241
|
+
const distinctPrefix = distinctMatch ? distinctMatch[1] : "";
|
|
13214
13242
|
const fromIndex = text.indexOf(" FROM ");
|
|
13215
13243
|
if (fromIndex !== -1) {
|
|
13216
|
-
text = `SELECT ${rendered.join(", ")}${text.substring(fromIndex)}`;
|
|
13244
|
+
text = `SELECT ${distinctPrefix}${rendered.join(", ")}${text.substring(fromIndex)}`;
|
|
13217
13245
|
} else {
|
|
13218
|
-
text = `SELECT ${rendered.join(", ")} FROM ${table}`;
|
|
13246
|
+
text = `SELECT ${distinctPrefix}${rendered.join(", ")} FROM ${table}`;
|
|
13219
13247
|
}
|
|
13248
|
+
built = null;
|
|
13220
13249
|
return this;
|
|
13221
13250
|
},
|
|
13222
13251
|
addSelect(...columns2) {
|
|
@@ -14105,9 +14134,9 @@ function createQueryBuilder(state) {
|
|
|
14105
14134
|
return this;
|
|
14106
14135
|
},
|
|
14107
14136
|
whereRaw(fragment) {
|
|
14108
|
-
|
|
14137
|
+
const frag = renderRawFragment(fragment, "whereRaw(fragment)");
|
|
14109
14138
|
const keyword = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
|
|
14110
|
-
text += ` ${keyword} ${
|
|
14139
|
+
text += ` ${keyword} ${frag}`;
|
|
14111
14140
|
built = null;
|
|
14112
14141
|
return this;
|
|
14113
14142
|
},
|
|
@@ -14473,8 +14502,8 @@ function createQueryBuilder(state) {
|
|
|
14473
14502
|
return this;
|
|
14474
14503
|
},
|
|
14475
14504
|
groupByRaw(fragment) {
|
|
14476
|
-
|
|
14477
|
-
text = SQL_PATTERNS.GROUP_BY.test(text) ? `${text}, ${
|
|
14505
|
+
const frag = renderRawFragment(fragment, "groupByRaw(fragment)");
|
|
14506
|
+
text = SQL_PATTERNS.GROUP_BY.test(text) ? `${text}, ${frag}` : `${text} GROUP BY ${frag}`;
|
|
14478
14507
|
built = null;
|
|
14479
14508
|
return this;
|
|
14480
14509
|
},
|
|
@@ -14506,15 +14535,15 @@ function createQueryBuilder(state) {
|
|
|
14506
14535
|
return this;
|
|
14507
14536
|
},
|
|
14508
14537
|
havingRaw(fragment) {
|
|
14509
|
-
|
|
14538
|
+
const frag = renderRawFragment(fragment, "havingRaw(fragment)");
|
|
14510
14539
|
const kw = /\bHAVING\b/i.test(text) ? "AND" : "HAVING";
|
|
14511
|
-
text += ` ${kw} ${
|
|
14540
|
+
text += ` ${kw} ${frag}`;
|
|
14512
14541
|
built = null;
|
|
14513
14542
|
return this;
|
|
14514
14543
|
},
|
|
14515
14544
|
orderByRaw(fragment) {
|
|
14516
|
-
|
|
14517
|
-
text = SQL_PATTERNS.ORDER_BY.test(text) ? `${text}, ${
|
|
14545
|
+
const frag = renderRawFragment(fragment, "orderByRaw(fragment)");
|
|
14546
|
+
text = SQL_PATTERNS.ORDER_BY.test(text) ? `${text}, ${frag}` : `${text} ORDER BY ${frag}`;
|
|
14518
14547
|
built = null;
|
|
14519
14548
|
return this;
|
|
14520
14549
|
},
|
|
@@ -14697,20 +14726,20 @@ function createQueryBuilder(state) {
|
|
|
14697
14726
|
includeTrashed = true;
|
|
14698
14727
|
onlyTrashed = true;
|
|
14699
14728
|
const softDeleteColumn = config5.softDeletes?.column || "deleted_at";
|
|
14700
|
-
const splice = (
|
|
14701
|
-
const upper =
|
|
14729
|
+
const splice = (raw2, predicate2) => {
|
|
14730
|
+
const upper = raw2.toUpperCase();
|
|
14702
14731
|
let depth = 0;
|
|
14703
|
-
for (let i = 0;i <
|
|
14704
|
-
const c =
|
|
14732
|
+
for (let i = 0;i < raw2.length; i++) {
|
|
14733
|
+
const c = raw2[i];
|
|
14705
14734
|
if (c === "(")
|
|
14706
14735
|
depth++;
|
|
14707
14736
|
else if (c === ")")
|
|
14708
14737
|
depth--;
|
|
14709
|
-
else if (depth === 0 && upper.substring(i, i + 5) === "WHERE" && (i === 0 || /\s/.test(
|
|
14710
|
-
return `${
|
|
14738
|
+
else if (depth === 0 && upper.substring(i, i + 5) === "WHERE" && (i === 0 || /\s/.test(raw2[i - 1] ?? "")) && /\s/.test(raw2[i + 5] ?? "")) {
|
|
14739
|
+
return `${raw2.substring(0, i)}WHERE ${predicate2} AND ${raw2.substring(i + 6)}`;
|
|
14711
14740
|
}
|
|
14712
14741
|
}
|
|
14713
|
-
return `${
|
|
14742
|
+
return `${raw2} WHERE ${predicate2}`;
|
|
14714
14743
|
};
|
|
14715
14744
|
const predicate = `${table}.${softDeleteColumn} IS NOT NULL`;
|
|
14716
14745
|
text = splice(text, predicate);
|
|
@@ -15014,13 +15043,13 @@ function createQueryBuilder(state) {
|
|
|
15014
15043
|
const cacheKey = `${String(table)}|${prop}`;
|
|
15015
15044
|
let chosen = dynamicWhereColumnCache.get(cacheKey);
|
|
15016
15045
|
if (chosen === undefined) {
|
|
15017
|
-
const
|
|
15018
|
-
if (!
|
|
15046
|
+
const raw2 = prop.replace(/^(?:or|and)?where/i, "");
|
|
15047
|
+
if (!raw2) {
|
|
15019
15048
|
dynamicWhereColumnCache.set(cacheKey, "");
|
|
15020
15049
|
chosen = "";
|
|
15021
15050
|
} else {
|
|
15022
|
-
const lowerFirst =
|
|
15023
|
-
const snake =
|
|
15051
|
+
const lowerFirst = raw2.charAt(0).toLowerCase() + raw2.slice(1);
|
|
15052
|
+
const snake = raw2.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
15024
15053
|
const available = schema ? Object.keys(schema[String(table)]?.columns ?? {}) : [];
|
|
15025
15054
|
chosen = [snake, lowerFirst, lowerFirst.toLowerCase()].find((n) => available.includes(n)) ?? snake;
|
|
15026
15055
|
dynamicWhereColumnCache.set(cacheKey, chosen);
|
|
@@ -15410,6 +15439,10 @@ function createQueryBuilder(state) {
|
|
|
15410
15439
|
returning(...cols) {
|
|
15411
15440
|
const returningSql = `${sqlText} RETURNING ${cols.join(", ")}`;
|
|
15412
15441
|
const q = _sql.unsafe(returningSql, params);
|
|
15442
|
+
const runFirst = async () => {
|
|
15443
|
+
const rows = await runWithHooks(q, "insert");
|
|
15444
|
+
return Array.isArray(rows) ? rows[0] : rows;
|
|
15445
|
+
};
|
|
15413
15446
|
return {
|
|
15414
15447
|
where: () => this,
|
|
15415
15448
|
andWhere: () => this,
|
|
@@ -15418,7 +15451,22 @@ function createQueryBuilder(state) {
|
|
|
15418
15451
|
limit: () => this,
|
|
15419
15452
|
offset: () => this,
|
|
15420
15453
|
toSQL: () => makeExecutableQuery(q, returningSql),
|
|
15421
|
-
execute: () => runWithHooks(q, "insert")
|
|
15454
|
+
execute: () => runWithHooks(q, "insert"),
|
|
15455
|
+
get: () => runWithHooks(q, "insert"),
|
|
15456
|
+
first: runFirst,
|
|
15457
|
+
executeTakeFirst: runFirst,
|
|
15458
|
+
async firstOrFail() {
|
|
15459
|
+
const row = await runFirst();
|
|
15460
|
+
if (!row)
|
|
15461
|
+
throw new Error("Insert with RETURNING returned no rows");
|
|
15462
|
+
return row;
|
|
15463
|
+
},
|
|
15464
|
+
async executeTakeFirstOrThrow() {
|
|
15465
|
+
const row = await runFirst();
|
|
15466
|
+
if (!row)
|
|
15467
|
+
throw new Error("Insert with RETURNING returned no rows");
|
|
15468
|
+
return row;
|
|
15469
|
+
}
|
|
15422
15470
|
};
|
|
15423
15471
|
},
|
|
15424
15472
|
toSQL() {
|
|
@@ -15457,19 +15505,27 @@ function createQueryBuilder(state) {
|
|
|
15457
15505
|
returningAll() {
|
|
15458
15506
|
const returningSql = `${sqlText} RETURNING *`;
|
|
15459
15507
|
const q = _sql.unsafe(returningSql, params);
|
|
15508
|
+
const runFirst = async () => {
|
|
15509
|
+
const result = await runWithHooks(q, "insert");
|
|
15510
|
+
return Array.isArray(result) ? result[0] : result;
|
|
15511
|
+
};
|
|
15460
15512
|
return {
|
|
15461
15513
|
toSQL: () => makeExecutableQuery(q, returningSql),
|
|
15462
15514
|
execute: () => runWithHooks(q, "insert"),
|
|
15463
|
-
|
|
15464
|
-
|
|
15465
|
-
|
|
15515
|
+
get: () => runWithHooks(q, "insert"),
|
|
15516
|
+
first: runFirst,
|
|
15517
|
+
executeTakeFirst: runFirst,
|
|
15518
|
+
async firstOrFail() {
|
|
15519
|
+
const row = await runFirst();
|
|
15520
|
+
if (!row)
|
|
15521
|
+
throw new Error("Insert with RETURNING returned no rows");
|
|
15522
|
+
return row;
|
|
15466
15523
|
},
|
|
15467
15524
|
async executeTakeFirstOrThrow() {
|
|
15468
|
-
const
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
return first;
|
|
15525
|
+
const row = await runFirst();
|
|
15526
|
+
if (!row)
|
|
15527
|
+
throw new Error("Insert with RETURNING returned no rows");
|
|
15528
|
+
return row;
|
|
15473
15529
|
}
|
|
15474
15530
|
};
|
|
15475
15531
|
}
|
|
@@ -15533,6 +15589,10 @@ function createQueryBuilder(state) {
|
|
|
15533
15589
|
returning(...cols) {
|
|
15534
15590
|
const retText = `${sqlText} RETURNING ${cols.join(", ")}`;
|
|
15535
15591
|
const q = params.length > 0 ? _sql.unsafe(retText, params) : _sql.unsafe(retText);
|
|
15592
|
+
const runFirst = async () => {
|
|
15593
|
+
const rows = await runWithHooks(q, "update");
|
|
15594
|
+
return Array.isArray(rows) ? rows[0] : rows;
|
|
15595
|
+
};
|
|
15536
15596
|
const obj = {
|
|
15537
15597
|
where: () => obj,
|
|
15538
15598
|
andWhere: () => obj,
|
|
@@ -15541,7 +15601,22 @@ function createQueryBuilder(state) {
|
|
|
15541
15601
|
limit: () => obj,
|
|
15542
15602
|
offset: () => obj,
|
|
15543
15603
|
toSQL: () => makeExecutableQuery(q, retText),
|
|
15544
|
-
execute: () => runWithHooks(q, "update")
|
|
15604
|
+
execute: () => runWithHooks(q, "update"),
|
|
15605
|
+
get: () => runWithHooks(q, "update"),
|
|
15606
|
+
first: runFirst,
|
|
15607
|
+
executeTakeFirst: runFirst,
|
|
15608
|
+
async firstOrFail() {
|
|
15609
|
+
const row = await runFirst();
|
|
15610
|
+
if (!row)
|
|
15611
|
+
throw new Error("Update with RETURNING returned no rows");
|
|
15612
|
+
return row;
|
|
15613
|
+
},
|
|
15614
|
+
async executeTakeFirstOrThrow() {
|
|
15615
|
+
const row = await runFirst();
|
|
15616
|
+
if (!row)
|
|
15617
|
+
throw new Error("Update with RETURNING returned no rows");
|
|
15618
|
+
return row;
|
|
15619
|
+
}
|
|
15545
15620
|
};
|
|
15546
15621
|
return obj;
|
|
15547
15622
|
},
|
|
@@ -15640,6 +15715,10 @@ function createQueryBuilder(state) {
|
|
|
15640
15715
|
returning(...cols) {
|
|
15641
15716
|
const retText = `${sqlText} RETURNING ${cols.join(", ")}`;
|
|
15642
15717
|
const q = delParams.length > 0 ? _sql.unsafe(retText, delParams) : _sql.unsafe(retText);
|
|
15718
|
+
const runFirst = async () => {
|
|
15719
|
+
const rows = await runWithHooks(q, "delete");
|
|
15720
|
+
return Array.isArray(rows) ? rows[0] : rows;
|
|
15721
|
+
};
|
|
15643
15722
|
const obj = {
|
|
15644
15723
|
where: () => obj,
|
|
15645
15724
|
andWhere: () => obj,
|
|
@@ -15648,7 +15727,22 @@ function createQueryBuilder(state) {
|
|
|
15648
15727
|
limit: () => obj,
|
|
15649
15728
|
offset: () => obj,
|
|
15650
15729
|
toSQL: () => makeExecutableQuery(q, retText),
|
|
15651
|
-
execute: () => runWithHooks(q, "delete")
|
|
15730
|
+
execute: () => runWithHooks(q, "delete"),
|
|
15731
|
+
get: () => runWithHooks(q, "delete"),
|
|
15732
|
+
first: runFirst,
|
|
15733
|
+
executeTakeFirst: runFirst,
|
|
15734
|
+
async firstOrFail() {
|
|
15735
|
+
const row = await runFirst();
|
|
15736
|
+
if (!row)
|
|
15737
|
+
throw new Error("Delete with RETURNING returned no rows");
|
|
15738
|
+
return row;
|
|
15739
|
+
},
|
|
15740
|
+
async executeTakeFirstOrThrow() {
|
|
15741
|
+
const row = await runFirst();
|
|
15742
|
+
if (!row)
|
|
15743
|
+
throw new Error("Delete with RETURNING returned no rows");
|
|
15744
|
+
return row;
|
|
15745
|
+
}
|
|
15652
15746
|
};
|
|
15653
15747
|
return obj;
|
|
15654
15748
|
},
|
|
@@ -18000,8 +18094,8 @@ function loadPlanSnapshot(workspaceRoot, dialect) {
|
|
|
18000
18094
|
return;
|
|
18001
18095
|
}
|
|
18002
18096
|
try {
|
|
18003
|
-
const
|
|
18004
|
-
const parsed = JSON.parse(
|
|
18097
|
+
const raw2 = readFileSync3(snapshotPath, "utf8");
|
|
18098
|
+
const parsed = JSON.parse(raw2);
|
|
18005
18099
|
if (parsed?.plan && Array.isArray(parsed.plan.tables) && parsed.plan.dialect) {
|
|
18006
18100
|
return parsed.plan;
|
|
18007
18101
|
}
|
|
@@ -18060,8 +18154,8 @@ async function generateMigration(dir, opts = {}) {
|
|
|
18060
18154
|
const statePath = String(opts.state || defaultStatePath);
|
|
18061
18155
|
if (existsSync16(statePath)) {
|
|
18062
18156
|
try {
|
|
18063
|
-
const
|
|
18064
|
-
const parsed = JSON.parse(
|
|
18157
|
+
const raw2 = readFileSync3(statePath, "utf8");
|
|
18158
|
+
const parsed = JSON.parse(raw2);
|
|
18065
18159
|
previous = parsed?.plan && parsed.plan.tables ? parsed.plan : parsed?.tables ? parsed : undefined;
|
|
18066
18160
|
if (previous) {
|
|
18067
18161
|
info("-- Comparing with legacy state file (will migrate to new snapshot format)");
|
|
@@ -24651,10 +24745,10 @@ class BelongsToManyRelationBuilder {
|
|
|
24651
24745
|
hydrateRows(rows) {
|
|
24652
24746
|
const fkParent = this.fkParent;
|
|
24653
24747
|
const fkRelated = this.fkRelated;
|
|
24654
|
-
return rows.map((
|
|
24748
|
+
return rows.map((raw2) => {
|
|
24655
24749
|
const relatedRow = {};
|
|
24656
24750
|
const pivotExtras = {};
|
|
24657
|
-
for (const [k2, v2] of Object.entries(
|
|
24751
|
+
for (const [k2, v2] of Object.entries(raw2)) {
|
|
24658
24752
|
if (k2.startsWith(BTM_RELATED_ALIAS))
|
|
24659
24753
|
relatedRow[k2.slice(BTM_RELATED_ALIAS.length)] = v2;
|
|
24660
24754
|
else if (k2 !== fkParent && k2 !== fkRelated)
|
|
@@ -29120,11 +29214,11 @@ Received ${signal}, cleaning up...`);
|
|
|
29120
29214
|
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
|
|
29121
29215
|
argv = argv.slice(0, doubleDashesIndex);
|
|
29122
29216
|
}
|
|
29123
|
-
const
|
|
29124
|
-
const parsed = { _:
|
|
29125
|
-
for (const name of Object.keys(
|
|
29217
|
+
const raw2 = parseArgv(argv, mriOptions);
|
|
29218
|
+
const parsed = { _: raw2._ };
|
|
29219
|
+
for (const name of Object.keys(raw2)) {
|
|
29126
29220
|
if (name !== "_") {
|
|
29127
|
-
parsed[camelcaseOptionName(name)] =
|
|
29221
|
+
parsed[camelcaseOptionName(name)] = raw2[name];
|
|
29128
29222
|
}
|
|
29129
29223
|
}
|
|
29130
29224
|
const args = parsed._;
|
|
@@ -29169,11 +29263,11 @@ Received ${signal}, cleaning up...`);
|
|
|
29169
29263
|
if (!isUsage)
|
|
29170
29264
|
return;
|
|
29171
29265
|
const e2 = err;
|
|
29172
|
-
const
|
|
29266
|
+
const raw2 = e2.message ?? "command-line error";
|
|
29173
29267
|
const label = this.name ? `${this.name}: ` : "";
|
|
29174
|
-
const suffix = /--help/.test(
|
|
29268
|
+
const suffix = /--help/.test(raw2) ? "" : `
|
|
29175
29269
|
Run \`${this.name ?? "cli"} --help\` for usage.`;
|
|
29176
|
-
process52.stderr.write(`${label}${
|
|
29270
|
+
process52.stderr.write(`${label}${raw2}${suffix}
|
|
29177
29271
|
`);
|
|
29178
29272
|
process52.exit(e2.exitCode ?? 2);
|
|
29179
29273
|
}
|
|
@@ -30031,7 +30125,7 @@ function getPrefix() {
|
|
|
30031
30125
|
}
|
|
30032
30126
|
var prefix = getPrefix();
|
|
30033
30127
|
// package.json
|
|
30034
|
-
var version2 = "0.1.
|
|
30128
|
+
var version2 = "0.1.32";
|
|
30035
30129
|
|
|
30036
30130
|
// bin/cli.ts
|
|
30037
30131
|
init_actions();
|
package/dist/client.d.ts
CHANGED
|
@@ -2,6 +2,33 @@ import { config } from './config';
|
|
|
2
2
|
import { resetConnection } from './db';
|
|
3
3
|
import type { DatabaseSchema } from './schema';
|
|
4
4
|
import type { SchemaMeta } from './meta';
|
|
5
|
+
/**
|
|
6
|
+
* # `raw`
|
|
7
|
+
*
|
|
8
|
+
* Build a raw SQL fragment for the `*Raw` builder methods (`whereRaw`,
|
|
9
|
+
* `selectRaw`, `orderByRaw`, `groupByRaw`, `havingRaw`) and `select()`.
|
|
10
|
+
*
|
|
11
|
+
* Use this INSTEAD of a Bun `sql\`...\`` tag: a Bun query object cannot be
|
|
12
|
+
* converted back to SQL text (it stringifies to "[object Promise]"), so it
|
|
13
|
+
* silently corrupts the generated SQL. `raw` returns a `{ raw: string }`
|
|
14
|
+
* fragment that the builder renders correctly and that satisfies the
|
|
15
|
+
* `SqlFragment` type (so it passes the bare-string injection guard).
|
|
16
|
+
*
|
|
17
|
+
* Interpolated values in the tagged-template form are SQL-escaped (strings
|
|
18
|
+
* single-quote-doubled, dates → ISO, numbers/booleans/null inlined) — the
|
|
19
|
+
* same escaping the relation-subquery builders use. For user input that must
|
|
20
|
+
* be parameterised, prefer the typed `where(...)` methods over `raw`.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { raw } from 'bun-query-builder'
|
|
25
|
+
* db.selectFrom('users').selectRaw(raw`count(*) as c`)
|
|
26
|
+
* db.selectFrom('users').whereRaw(raw('age > 18'))
|
|
27
|
+
* db.selectFrom('users').orderByRaw(raw`created_at desc`)
|
|
28
|
+
* db.selectFrom('orders').whereRaw(raw`status = ${userStatus}`) // value escaped
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function raw(strings: TemplateStringsArray | string, ...values: unknown[]): RawExpression;
|
|
5
32
|
// eslint-disable-next-line pickier/no-unused-vars
|
|
6
33
|
export declare function createQueryBuilder<DB extends DatabaseSchema<any>>(state?: Partial<InternalState>): QueryBuilder<DB>;
|
|
7
34
|
/**
|
|
@@ -26,6 +53,10 @@ export declare function clearQueryCache(): void;
|
|
|
26
53
|
* ```
|
|
27
54
|
*/
|
|
28
55
|
export declare function setQueryCacheMaxSize(size: number): void;
|
|
56
|
+
// Type guard for raw SQL expressions
|
|
57
|
+
declare interface RawExpression {
|
|
58
|
+
raw: string
|
|
59
|
+
}
|
|
29
60
|
export declare interface WhereRaw {
|
|
30
61
|
raw: any
|
|
31
62
|
}
|
package/dist/src/index.js
CHANGED
|
@@ -12344,6 +12344,14 @@ function* iterateAllPivots(meta, options = {}) {
|
|
|
12344
12344
|
function isRawExpression(expr) {
|
|
12345
12345
|
return typeof expr === "object" && expr !== null && "raw" in expr && typeof expr.raw === "string";
|
|
12346
12346
|
}
|
|
12347
|
+
function raw(strings, ...values) {
|
|
12348
|
+
if (typeof strings === "string")
|
|
12349
|
+
return { raw: strings };
|
|
12350
|
+
let out = strings[0];
|
|
12351
|
+
for (let i = 0;i < values.length; i++)
|
|
12352
|
+
out += formatSubqueryValue(values[i]) + strings[i + 1];
|
|
12353
|
+
return { raw: out };
|
|
12354
|
+
}
|
|
12347
12355
|
function quoteInsertIdent(id) {
|
|
12348
12356
|
return config5.dialect === "mysql" ? `\`${id.replace(/`/g, "``")}\`` : `"${id.replace(/"/g, '""')}"`;
|
|
12349
12357
|
}
|
|
@@ -12412,13 +12420,31 @@ function validateQualifiedIdentifier(value, context) {
|
|
|
12412
12420
|
throw new TypeError(`[query-builder] ${context}: identifier segment '${part}' contains characters outside [A-Za-z0-9_]`);
|
|
12413
12421
|
}
|
|
12414
12422
|
}
|
|
12415
|
-
function
|
|
12416
|
-
if (fragment === null || fragment === undefined) {
|
|
12417
|
-
throw new TypeError(`[query-builder] ${context}: fragment must be a SqlFragment, got ${fragment}`);
|
|
12418
|
-
}
|
|
12423
|
+
function renderRawFragment(fragment, context) {
|
|
12419
12424
|
if (typeof fragment === "string") {
|
|
12420
12425
|
warnOnceBareSqlFragment(context);
|
|
12426
|
+
return fragment;
|
|
12421
12427
|
}
|
|
12428
|
+
if (fragment === null || fragment === undefined)
|
|
12429
|
+
throw new TypeError(`[query-builder] ${context}: fragment must be a SqlFragment, got ${fragment}`);
|
|
12430
|
+
if (isRawExpression(fragment))
|
|
12431
|
+
return fragment.raw;
|
|
12432
|
+
if (typeof fragment === "object") {
|
|
12433
|
+
const f = fragment;
|
|
12434
|
+
if (typeof f.raw === "string")
|
|
12435
|
+
return f.raw;
|
|
12436
|
+
if (typeof f.raw === "function") {
|
|
12437
|
+
const r = f.raw();
|
|
12438
|
+
if (typeof r === "string")
|
|
12439
|
+
return r;
|
|
12440
|
+
}
|
|
12441
|
+
if (typeof f.sql === "string")
|
|
12442
|
+
return f.sql;
|
|
12443
|
+
const s = String(fragment);
|
|
12444
|
+
if (s !== "[object Object]" && s !== "[object Promise]")
|
|
12445
|
+
return s;
|
|
12446
|
+
}
|
|
12447
|
+
throw new TypeError(`[query-builder] ${context}: cannot render this value as a SQL fragment. ` + `A Bun \`sql\`...\`\` query object cannot be converted to SQL text \u2014 pass a ` + `string, or use the exported \`raw\` helper: raw\`count(*) as c\` / raw('age > 18').`);
|
|
12422
12448
|
}
|
|
12423
12449
|
function warnOnceBareSqlFragment(context) {
|
|
12424
12450
|
if (warnedSqlFragmentContexts.has(context))
|
|
@@ -13093,12 +13119,12 @@ function createQueryBuilder(state) {
|
|
|
13093
13119
|
return this;
|
|
13094
13120
|
},
|
|
13095
13121
|
selectRaw(fragment) {
|
|
13096
|
-
|
|
13122
|
+
const frag = renderRawFragment(fragment, "selectRaw(fragment)");
|
|
13097
13123
|
const fromIdx = text.indexOf(" FROM ");
|
|
13098
13124
|
if (fromIdx !== -1) {
|
|
13099
|
-
text = `${text.substring(0, fromIdx)}, ${
|
|
13125
|
+
text = `${text.substring(0, fromIdx)}, ${frag}${text.substring(fromIdx)}`;
|
|
13100
13126
|
} else {
|
|
13101
|
-
text += `, ${
|
|
13127
|
+
text += `, ${frag}`;
|
|
13102
13128
|
}
|
|
13103
13129
|
built = null;
|
|
13104
13130
|
return this;
|
|
@@ -13211,12 +13237,15 @@ function createQueryBuilder(state) {
|
|
|
13211
13237
|
if (cols.length === 0)
|
|
13212
13238
|
return this;
|
|
13213
13239
|
const rendered = cols.map(renderSelectColumn);
|
|
13240
|
+
const distinctMatch = /^SELECT\s+(DISTINCT(?:\s+ON\s+\([^)]*\))?\s+)/i.exec(text);
|
|
13241
|
+
const distinctPrefix = distinctMatch ? distinctMatch[1] : "";
|
|
13214
13242
|
const fromIndex = text.indexOf(" FROM ");
|
|
13215
13243
|
if (fromIndex !== -1) {
|
|
13216
|
-
text = `SELECT ${rendered.join(", ")}${text.substring(fromIndex)}`;
|
|
13244
|
+
text = `SELECT ${distinctPrefix}${rendered.join(", ")}${text.substring(fromIndex)}`;
|
|
13217
13245
|
} else {
|
|
13218
|
-
text = `SELECT ${rendered.join(", ")} FROM ${table}`;
|
|
13246
|
+
text = `SELECT ${distinctPrefix}${rendered.join(", ")} FROM ${table}`;
|
|
13219
13247
|
}
|
|
13248
|
+
built = null;
|
|
13220
13249
|
return this;
|
|
13221
13250
|
},
|
|
13222
13251
|
addSelect(...columns2) {
|
|
@@ -14105,9 +14134,9 @@ function createQueryBuilder(state) {
|
|
|
14105
14134
|
return this;
|
|
14106
14135
|
},
|
|
14107
14136
|
whereRaw(fragment) {
|
|
14108
|
-
|
|
14137
|
+
const frag = renderRawFragment(fragment, "whereRaw(fragment)");
|
|
14109
14138
|
const keyword = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
|
|
14110
|
-
text += ` ${keyword} ${
|
|
14139
|
+
text += ` ${keyword} ${frag}`;
|
|
14111
14140
|
built = null;
|
|
14112
14141
|
return this;
|
|
14113
14142
|
},
|
|
@@ -14473,8 +14502,8 @@ function createQueryBuilder(state) {
|
|
|
14473
14502
|
return this;
|
|
14474
14503
|
},
|
|
14475
14504
|
groupByRaw(fragment) {
|
|
14476
|
-
|
|
14477
|
-
text = SQL_PATTERNS.GROUP_BY.test(text) ? `${text}, ${
|
|
14505
|
+
const frag = renderRawFragment(fragment, "groupByRaw(fragment)");
|
|
14506
|
+
text = SQL_PATTERNS.GROUP_BY.test(text) ? `${text}, ${frag}` : `${text} GROUP BY ${frag}`;
|
|
14478
14507
|
built = null;
|
|
14479
14508
|
return this;
|
|
14480
14509
|
},
|
|
@@ -14506,15 +14535,15 @@ function createQueryBuilder(state) {
|
|
|
14506
14535
|
return this;
|
|
14507
14536
|
},
|
|
14508
14537
|
havingRaw(fragment) {
|
|
14509
|
-
|
|
14538
|
+
const frag = renderRawFragment(fragment, "havingRaw(fragment)");
|
|
14510
14539
|
const kw = /\bHAVING\b/i.test(text) ? "AND" : "HAVING";
|
|
14511
|
-
text += ` ${kw} ${
|
|
14540
|
+
text += ` ${kw} ${frag}`;
|
|
14512
14541
|
built = null;
|
|
14513
14542
|
return this;
|
|
14514
14543
|
},
|
|
14515
14544
|
orderByRaw(fragment) {
|
|
14516
|
-
|
|
14517
|
-
text = SQL_PATTERNS.ORDER_BY.test(text) ? `${text}, ${
|
|
14545
|
+
const frag = renderRawFragment(fragment, "orderByRaw(fragment)");
|
|
14546
|
+
text = SQL_PATTERNS.ORDER_BY.test(text) ? `${text}, ${frag}` : `${text} ORDER BY ${frag}`;
|
|
14518
14547
|
built = null;
|
|
14519
14548
|
return this;
|
|
14520
14549
|
},
|
|
@@ -14697,20 +14726,20 @@ function createQueryBuilder(state) {
|
|
|
14697
14726
|
includeTrashed = true;
|
|
14698
14727
|
onlyTrashed = true;
|
|
14699
14728
|
const softDeleteColumn = config5.softDeletes?.column || "deleted_at";
|
|
14700
|
-
const splice = (
|
|
14701
|
-
const upper =
|
|
14729
|
+
const splice = (raw2, predicate2) => {
|
|
14730
|
+
const upper = raw2.toUpperCase();
|
|
14702
14731
|
let depth = 0;
|
|
14703
|
-
for (let i = 0;i <
|
|
14704
|
-
const c =
|
|
14732
|
+
for (let i = 0;i < raw2.length; i++) {
|
|
14733
|
+
const c = raw2[i];
|
|
14705
14734
|
if (c === "(")
|
|
14706
14735
|
depth++;
|
|
14707
14736
|
else if (c === ")")
|
|
14708
14737
|
depth--;
|
|
14709
|
-
else if (depth === 0 && upper.substring(i, i + 5) === "WHERE" && (i === 0 || /\s/.test(
|
|
14710
|
-
return `${
|
|
14738
|
+
else if (depth === 0 && upper.substring(i, i + 5) === "WHERE" && (i === 0 || /\s/.test(raw2[i - 1] ?? "")) && /\s/.test(raw2[i + 5] ?? "")) {
|
|
14739
|
+
return `${raw2.substring(0, i)}WHERE ${predicate2} AND ${raw2.substring(i + 6)}`;
|
|
14711
14740
|
}
|
|
14712
14741
|
}
|
|
14713
|
-
return `${
|
|
14742
|
+
return `${raw2} WHERE ${predicate2}`;
|
|
14714
14743
|
};
|
|
14715
14744
|
const predicate = `${table}.${softDeleteColumn} IS NOT NULL`;
|
|
14716
14745
|
text = splice(text, predicate);
|
|
@@ -15014,13 +15043,13 @@ function createQueryBuilder(state) {
|
|
|
15014
15043
|
const cacheKey = `${String(table)}|${prop}`;
|
|
15015
15044
|
let chosen = dynamicWhereColumnCache.get(cacheKey);
|
|
15016
15045
|
if (chosen === undefined) {
|
|
15017
|
-
const
|
|
15018
|
-
if (!
|
|
15046
|
+
const raw2 = prop.replace(/^(?:or|and)?where/i, "");
|
|
15047
|
+
if (!raw2) {
|
|
15019
15048
|
dynamicWhereColumnCache.set(cacheKey, "");
|
|
15020
15049
|
chosen = "";
|
|
15021
15050
|
} else {
|
|
15022
|
-
const lowerFirst =
|
|
15023
|
-
const snake =
|
|
15051
|
+
const lowerFirst = raw2.charAt(0).toLowerCase() + raw2.slice(1);
|
|
15052
|
+
const snake = raw2.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
15024
15053
|
const available = schema ? Object.keys(schema[String(table)]?.columns ?? {}) : [];
|
|
15025
15054
|
chosen = [snake, lowerFirst, lowerFirst.toLowerCase()].find((n) => available.includes(n)) ?? snake;
|
|
15026
15055
|
dynamicWhereColumnCache.set(cacheKey, chosen);
|
|
@@ -15410,6 +15439,10 @@ function createQueryBuilder(state) {
|
|
|
15410
15439
|
returning(...cols) {
|
|
15411
15440
|
const returningSql = `${sqlText} RETURNING ${cols.join(", ")}`;
|
|
15412
15441
|
const q = _sql.unsafe(returningSql, params);
|
|
15442
|
+
const runFirst = async () => {
|
|
15443
|
+
const rows = await runWithHooks(q, "insert");
|
|
15444
|
+
return Array.isArray(rows) ? rows[0] : rows;
|
|
15445
|
+
};
|
|
15413
15446
|
return {
|
|
15414
15447
|
where: () => this,
|
|
15415
15448
|
andWhere: () => this,
|
|
@@ -15418,7 +15451,22 @@ function createQueryBuilder(state) {
|
|
|
15418
15451
|
limit: () => this,
|
|
15419
15452
|
offset: () => this,
|
|
15420
15453
|
toSQL: () => makeExecutableQuery(q, returningSql),
|
|
15421
|
-
execute: () => runWithHooks(q, "insert")
|
|
15454
|
+
execute: () => runWithHooks(q, "insert"),
|
|
15455
|
+
get: () => runWithHooks(q, "insert"),
|
|
15456
|
+
first: runFirst,
|
|
15457
|
+
executeTakeFirst: runFirst,
|
|
15458
|
+
async firstOrFail() {
|
|
15459
|
+
const row = await runFirst();
|
|
15460
|
+
if (!row)
|
|
15461
|
+
throw new Error("Insert with RETURNING returned no rows");
|
|
15462
|
+
return row;
|
|
15463
|
+
},
|
|
15464
|
+
async executeTakeFirstOrThrow() {
|
|
15465
|
+
const row = await runFirst();
|
|
15466
|
+
if (!row)
|
|
15467
|
+
throw new Error("Insert with RETURNING returned no rows");
|
|
15468
|
+
return row;
|
|
15469
|
+
}
|
|
15422
15470
|
};
|
|
15423
15471
|
},
|
|
15424
15472
|
toSQL() {
|
|
@@ -15457,19 +15505,27 @@ function createQueryBuilder(state) {
|
|
|
15457
15505
|
returningAll() {
|
|
15458
15506
|
const returningSql = `${sqlText} RETURNING *`;
|
|
15459
15507
|
const q = _sql.unsafe(returningSql, params);
|
|
15508
|
+
const runFirst = async () => {
|
|
15509
|
+
const result = await runWithHooks(q, "insert");
|
|
15510
|
+
return Array.isArray(result) ? result[0] : result;
|
|
15511
|
+
};
|
|
15460
15512
|
return {
|
|
15461
15513
|
toSQL: () => makeExecutableQuery(q, returningSql),
|
|
15462
15514
|
execute: () => runWithHooks(q, "insert"),
|
|
15463
|
-
|
|
15464
|
-
|
|
15465
|
-
|
|
15515
|
+
get: () => runWithHooks(q, "insert"),
|
|
15516
|
+
first: runFirst,
|
|
15517
|
+
executeTakeFirst: runFirst,
|
|
15518
|
+
async firstOrFail() {
|
|
15519
|
+
const row = await runFirst();
|
|
15520
|
+
if (!row)
|
|
15521
|
+
throw new Error("Insert with RETURNING returned no rows");
|
|
15522
|
+
return row;
|
|
15466
15523
|
},
|
|
15467
15524
|
async executeTakeFirstOrThrow() {
|
|
15468
|
-
const
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
return first;
|
|
15525
|
+
const row = await runFirst();
|
|
15526
|
+
if (!row)
|
|
15527
|
+
throw new Error("Insert with RETURNING returned no rows");
|
|
15528
|
+
return row;
|
|
15473
15529
|
}
|
|
15474
15530
|
};
|
|
15475
15531
|
}
|
|
@@ -15533,6 +15589,10 @@ function createQueryBuilder(state) {
|
|
|
15533
15589
|
returning(...cols) {
|
|
15534
15590
|
const retText = `${sqlText} RETURNING ${cols.join(", ")}`;
|
|
15535
15591
|
const q = params.length > 0 ? _sql.unsafe(retText, params) : _sql.unsafe(retText);
|
|
15592
|
+
const runFirst = async () => {
|
|
15593
|
+
const rows = await runWithHooks(q, "update");
|
|
15594
|
+
return Array.isArray(rows) ? rows[0] : rows;
|
|
15595
|
+
};
|
|
15536
15596
|
const obj = {
|
|
15537
15597
|
where: () => obj,
|
|
15538
15598
|
andWhere: () => obj,
|
|
@@ -15541,7 +15601,22 @@ function createQueryBuilder(state) {
|
|
|
15541
15601
|
limit: () => obj,
|
|
15542
15602
|
offset: () => obj,
|
|
15543
15603
|
toSQL: () => makeExecutableQuery(q, retText),
|
|
15544
|
-
execute: () => runWithHooks(q, "update")
|
|
15604
|
+
execute: () => runWithHooks(q, "update"),
|
|
15605
|
+
get: () => runWithHooks(q, "update"),
|
|
15606
|
+
first: runFirst,
|
|
15607
|
+
executeTakeFirst: runFirst,
|
|
15608
|
+
async firstOrFail() {
|
|
15609
|
+
const row = await runFirst();
|
|
15610
|
+
if (!row)
|
|
15611
|
+
throw new Error("Update with RETURNING returned no rows");
|
|
15612
|
+
return row;
|
|
15613
|
+
},
|
|
15614
|
+
async executeTakeFirstOrThrow() {
|
|
15615
|
+
const row = await runFirst();
|
|
15616
|
+
if (!row)
|
|
15617
|
+
throw new Error("Update with RETURNING returned no rows");
|
|
15618
|
+
return row;
|
|
15619
|
+
}
|
|
15545
15620
|
};
|
|
15546
15621
|
return obj;
|
|
15547
15622
|
},
|
|
@@ -15640,6 +15715,10 @@ function createQueryBuilder(state) {
|
|
|
15640
15715
|
returning(...cols) {
|
|
15641
15716
|
const retText = `${sqlText} RETURNING ${cols.join(", ")}`;
|
|
15642
15717
|
const q = delParams.length > 0 ? _sql.unsafe(retText, delParams) : _sql.unsafe(retText);
|
|
15718
|
+
const runFirst = async () => {
|
|
15719
|
+
const rows = await runWithHooks(q, "delete");
|
|
15720
|
+
return Array.isArray(rows) ? rows[0] : rows;
|
|
15721
|
+
};
|
|
15643
15722
|
const obj = {
|
|
15644
15723
|
where: () => obj,
|
|
15645
15724
|
andWhere: () => obj,
|
|
@@ -15648,7 +15727,22 @@ function createQueryBuilder(state) {
|
|
|
15648
15727
|
limit: () => obj,
|
|
15649
15728
|
offset: () => obj,
|
|
15650
15729
|
toSQL: () => makeExecutableQuery(q, retText),
|
|
15651
|
-
execute: () => runWithHooks(q, "delete")
|
|
15730
|
+
execute: () => runWithHooks(q, "delete"),
|
|
15731
|
+
get: () => runWithHooks(q, "delete"),
|
|
15732
|
+
first: runFirst,
|
|
15733
|
+
executeTakeFirst: runFirst,
|
|
15734
|
+
async firstOrFail() {
|
|
15735
|
+
const row = await runFirst();
|
|
15736
|
+
if (!row)
|
|
15737
|
+
throw new Error("Delete with RETURNING returned no rows");
|
|
15738
|
+
return row;
|
|
15739
|
+
},
|
|
15740
|
+
async executeTakeFirstOrThrow() {
|
|
15741
|
+
const row = await runFirst();
|
|
15742
|
+
if (!row)
|
|
15743
|
+
throw new Error("Delete with RETURNING returned no rows");
|
|
15744
|
+
return row;
|
|
15745
|
+
}
|
|
15652
15746
|
};
|
|
15653
15747
|
return obj;
|
|
15654
15748
|
},
|
|
@@ -18000,8 +18094,8 @@ function loadPlanSnapshot(workspaceRoot, dialect) {
|
|
|
18000
18094
|
return;
|
|
18001
18095
|
}
|
|
18002
18096
|
try {
|
|
18003
|
-
const
|
|
18004
|
-
const parsed = JSON.parse(
|
|
18097
|
+
const raw2 = readFileSync3(snapshotPath, "utf8");
|
|
18098
|
+
const parsed = JSON.parse(raw2);
|
|
18005
18099
|
if (parsed?.plan && Array.isArray(parsed.plan.tables) && parsed.plan.dialect) {
|
|
18006
18100
|
return parsed.plan;
|
|
18007
18101
|
}
|
|
@@ -18060,8 +18154,8 @@ async function generateMigration(dir, opts = {}) {
|
|
|
18060
18154
|
const statePath = String(opts.state || defaultStatePath);
|
|
18061
18155
|
if (existsSync16(statePath)) {
|
|
18062
18156
|
try {
|
|
18063
|
-
const
|
|
18064
|
-
const parsed = JSON.parse(
|
|
18157
|
+
const raw2 = readFileSync3(statePath, "utf8");
|
|
18158
|
+
const parsed = JSON.parse(raw2);
|
|
18065
18159
|
previous = parsed?.plan && parsed.plan.tables ? parsed.plan : parsed?.tables ? parsed : undefined;
|
|
18066
18160
|
if (previous) {
|
|
18067
18161
|
info("-- Comparing with legacy state file (will migrate to new snapshot format)");
|
|
@@ -24651,10 +24745,10 @@ class BelongsToManyRelationBuilder {
|
|
|
24651
24745
|
hydrateRows(rows) {
|
|
24652
24746
|
const fkParent = this.fkParent;
|
|
24653
24747
|
const fkRelated = this.fkRelated;
|
|
24654
|
-
return rows.map((
|
|
24748
|
+
return rows.map((raw2) => {
|
|
24655
24749
|
const relatedRow = {};
|
|
24656
24750
|
const pivotExtras = {};
|
|
24657
|
-
for (const [k2, v2] of Object.entries(
|
|
24751
|
+
for (const [k2, v2] of Object.entries(raw2)) {
|
|
24658
24752
|
if (k2.startsWith(BTM_RELATED_ALIAS))
|
|
24659
24753
|
relatedRow[k2.slice(BTM_RELATED_ALIAS.length)] = v2;
|
|
24660
24754
|
else if (k2 !== fkParent && k2 !== fkRelated)
|
|
@@ -28021,6 +28115,7 @@ export {
|
|
|
28021
28115
|
relationDiagram,
|
|
28022
28116
|
registerModel,
|
|
28023
28117
|
registerBrowserModels,
|
|
28118
|
+
raw,
|
|
28024
28119
|
queryExplainAll,
|
|
28025
28120
|
ping,
|
|
28026
28121
|
parseStacksModels,
|
package/package.json
CHANGED