@atscript/db 0.1.146 → 0.1.147

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.
Files changed (45) hide show
  1. package/dist/agg.cjs +1 -1
  2. package/dist/agg.d.cts +1 -1
  3. package/dist/agg.d.mts +1 -1
  4. package/dist/agg.mjs +1 -1
  5. package/dist/{aggregate-fns-CfsveE1w.mjs → aggregate-fns-C0BymEqa.mjs} +3 -1
  6. package/dist/{aggregate-fns-CGBv3E8S.cjs → aggregate-fns-CtsRbZn9.cjs} +8 -0
  7. package/dist/{buckets-DYFu0eZ8.d.cts → buckets-CjdPipCC.d.cts} +522 -17
  8. package/dist/{buckets-DRycmhOW.d.mts → buckets-DYopfd2Y.d.mts} +522 -17
  9. package/dist/{column-diff-e2oHc71_.mjs → column-diff-CO06iQvI.mjs} +862 -115
  10. package/dist/{column-diff-D_Kyuh0S.cjs → column-diff-Dt7EDJsA.cjs} +872 -113
  11. package/dist/{column-diff-Q9UmWn5x.d.mts → fk-diff-BtOmL4OW.d.mts} +48 -2
  12. package/dist/{column-diff-w-Mym_3w.d.cts → fk-diff-DLqwVkKG.d.cts} +48 -2
  13. package/dist/index.cjs +28 -33
  14. package/dist/index.d.cts +40 -15
  15. package/dist/index.d.mts +40 -15
  16. package/dist/index.mjs +5 -33
  17. package/dist/{nested-writer-CnOOAehr.mjs → nested-writer-D35UsDBT.mjs} +542 -2
  18. package/dist/{nested-writer-xfQwxplL.cjs → nested-writer-SqtYJHF0.cjs} +666 -0
  19. package/dist/plugin.cjs +266 -5
  20. package/dist/plugin.mjs +267 -6
  21. package/dist/rel.cjs +2 -2
  22. package/dist/rel.d.cts +2 -2
  23. package/dist/rel.d.mts +2 -2
  24. package/dist/rel.mjs +2 -2
  25. package/dist/{relation-helpers-B-0NRKat.d.mts → relation-helpers-C2bLtE-t.d.mts} +1 -1
  26. package/dist/{relation-helpers-BOMm_HUI.d.cts → relation-helpers-DH3LvwLV.d.cts} +1 -1
  27. package/dist/relation-loader-BFhVuJ-B.cjs +369 -0
  28. package/dist/relation-loader-C0qE8xgR.mjs +370 -0
  29. package/dist/shared.cjs +1 -1
  30. package/dist/shared.d.cts +4 -3
  31. package/dist/shared.d.mts +4 -3
  32. package/dist/shared.mjs +1 -1
  33. package/dist/sync.cjs +10 -6
  34. package/dist/sync.d.cts +2 -25
  35. package/dist/sync.d.mts +2 -25
  36. package/dist/sync.mjs +10 -6
  37. package/dist/{validation-utils-DOsB4e6G.cjs → validation-utils-Da2GjobR.cjs} +35 -24
  38. package/dist/{validation-utils-CMR4fe2M.mjs → validation-utils-Dq0uZ7ef.mjs} +35 -24
  39. package/dist/{validator-Bw6ks9Hy.d.mts → validator-CMnTI6r7.d.cts} +9 -6
  40. package/dist/{validator-Bw6ks9Hy.d.cts → validator-CMnTI6r7.d.mts} +9 -6
  41. package/dist/validator.d.cts +1 -1
  42. package/dist/validator.d.mts +1 -1
  43. package/package.json +8 -8
  44. package/dist/relation-loader-CBPY6kM7.cjs +0 -461
  45. package/dist/relation-loader-D9XuXaMv.mjs +0 -462
@@ -1,462 +0,0 @@
1
- import { C as findRemoteFK, S as findFKForRelation, w as resolveRelationTargetTable } from "./nested-writer-CnOOAehr.mjs";
2
- //#region \0rolldown/runtime.js
3
- var __defProp = Object.defineProperty;
4
- var __exportAll = (all, no_symbols) => {
5
- let target = {};
6
- for (var name in all) __defProp(target, name, {
7
- get: all[name],
8
- enumerable: true
9
- });
10
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
11
- return target;
12
- };
13
- //#endregion
14
- //#region src/rel/relation-loader.ts
15
- var relation_loader_exports = /* @__PURE__ */ __exportAll({
16
- ensureSelectIncludesFields: () => ensureSelectIncludesFields,
17
- loadRelationsImpl: () => loadRelationsImpl
18
- });
19
- /**
20
- * Loads related data for `$with` relations and attaches them to result rows.
21
- */
22
- async function loadRelationsImpl(rows, withRelations, host) {
23
- if (rows.length === 0 || withRelations.length === 0) return;
24
- if (host.adapter.supportsNativeRelations()) return host.adapter.loadRelations(rows, withRelations, host._meta.relations, host._meta.foreignKeys, host._tableResolver);
25
- if (!host._tableResolver) return;
26
- const tasks = [];
27
- for (const withRel of withRelations) {
28
- const relName = withRel.name;
29
- if (relName.includes(".")) continue;
30
- const relation = host._meta.relations.get(relName);
31
- if (!relation) throw new Error(`Unknown relation "${relName}" in $with. Available relations: ${[...host._meta.relations.keys()].join(", ") || "(none)"}`);
32
- const targetType = relation.targetType();
33
- if (!targetType) continue;
34
- const targetTable = host._tableResolver(targetType);
35
- if (!targetTable) {
36
- host.logger.warn(`Could not resolve table for relation "${relName}" — skipping`);
37
- continue;
38
- }
39
- const filter = withRel.filter && Object.keys(withRel.filter).length > 0 ? withRel.filter : void 0;
40
- const flatRel = withRel;
41
- const controls = { ...withRel.controls || {} };
42
- if (flatRel.$sort && !controls.$sort) controls.$sort = flatRel.$sort;
43
- if (flatRel.$limit !== null && flatRel.$limit !== void 0 && (controls.$limit === null || controls.$limit === void 0)) controls.$limit = flatRel.$limit;
44
- if (flatRel.$skip !== null && flatRel.$skip !== void 0 && (controls.$skip === null || controls.$skip === void 0)) controls.$skip = flatRel.$skip;
45
- if (flatRel.$select && !controls.$select) controls.$select = flatRel.$select;
46
- if (flatRel.$with && !controls.$with) controls.$with = flatRel.$with;
47
- const relQuery = {
48
- filter,
49
- controls
50
- };
51
- if (relation.direction === "to") tasks.push(loadToRelation(rows, {
52
- relName,
53
- relation,
54
- targetTable,
55
- relQuery
56
- }, host));
57
- else if (relation.direction === "via") tasks.push(loadViaRelation(rows, {
58
- relName,
59
- relation,
60
- targetTable,
61
- relQuery
62
- }, host));
63
- else tasks.push(loadFromRelation(rows, {
64
- relName,
65
- relation,
66
- targetTable,
67
- relQuery
68
- }, host));
69
- }
70
- await Promise.all(tasks);
71
- }
72
- /**
73
- * Loads a `@db.rel.to` relation (FK is on this table).
74
- */
75
- async function loadToRelation(rows, opts, host) {
76
- const { relName, relation, targetTable, relQuery } = opts;
77
- const fkEntry = findFKForRelation(relation, host._meta.foreignKeys);
78
- if (!fkEntry) return;
79
- const { localFields, targetFields } = fkEntry;
80
- if (localFields.length === 1) {
81
- const localField = localFields[0];
82
- const targetField = targetFields[0];
83
- const fkValues = collectUniqueValues(rows, localField);
84
- if (fkValues.length === 0) {
85
- for (const row of rows) row[relName] = null;
86
- return;
87
- }
88
- const inFilter = { [targetField]: { $in: fkValues } };
89
- const targetFilter = relQuery.filter ? { $and: [inFilter, relQuery.filter] } : inFilter;
90
- const controls = ensureSelectIncludesFields(relQuery.controls, targetFields);
91
- assignSingle({
92
- rows,
93
- related: await targetTable.findMany({
94
- filter: targetFilter,
95
- controls
96
- }),
97
- localField,
98
- remoteField: targetField,
99
- relName
100
- });
101
- } else {
102
- const related = await queryCompositeFK(rows, {
103
- localFields,
104
- targetFields,
105
- targetTable,
106
- relQuery
107
- });
108
- const index = /* @__PURE__ */ new Map();
109
- for (const item of related) index.set(compositeKey(targetFields, item), item);
110
- for (const row of rows) row[relName] = index.get(compositeKey(localFields, row)) ?? null;
111
- }
112
- }
113
- /**
114
- * Loads a `@db.rel.from` relation (FK is on the target table).
115
- */
116
- async function loadFromRelation(rows, opts, host) {
117
- const { relName, relation, targetTable, relQuery } = opts;
118
- const remoteFK = findRemoteFK(targetTable, host.tableName, relation.alias);
119
- if (!remoteFK) {
120
- host.logger.warn(`Could not find FK on target table for relation "${relName}"`);
121
- return;
122
- }
123
- const localFields = remoteFK.targetFields;
124
- const remoteFields = remoteFK.fields;
125
- if (localFields.length === 1) {
126
- const localField = localFields[0];
127
- const remoteField = remoteFields[0];
128
- const pkValues = collectUniqueValues(rows, localField);
129
- if (pkValues.length === 0) return;
130
- const inFilter = { [remoteField]: { $in: pkValues } };
131
- const targetFilter = relQuery.filter ? { $and: [inFilter, relQuery.filter] } : inFilter;
132
- const controls = ensureSelectIncludesFields(relQuery.controls, remoteFields);
133
- const related = await targetTable.findMany({
134
- filter: targetFilter,
135
- controls
136
- });
137
- if (relation.isArray) assignGrouped({
138
- rows,
139
- related,
140
- localField,
141
- remoteField,
142
- relName
143
- });
144
- else assignSingle({
145
- rows,
146
- related,
147
- localField,
148
- remoteField,
149
- relName
150
- });
151
- } else {
152
- const related = await queryCompositeFK(rows, {
153
- localFields,
154
- targetFields: remoteFields,
155
- targetTable,
156
- relQuery
157
- });
158
- if (relation.isArray) {
159
- const groups = /* @__PURE__ */ new Map();
160
- for (const item of related) {
161
- const key = compositeKey(remoteFields, item);
162
- let group = groups.get(key);
163
- if (!group) {
164
- group = [];
165
- groups.set(key, group);
166
- }
167
- group.push(item);
168
- }
169
- for (const row of rows) row[relName] = groups.get(compositeKey(localFields, row)) ?? [];
170
- } else {
171
- const index = /* @__PURE__ */ new Map();
172
- for (const item of related) {
173
- const key = compositeKey(remoteFields, item);
174
- if (!index.has(key)) index.set(key, item);
175
- }
176
- for (const row of rows) row[relName] = index.get(compositeKey(localFields, row)) ?? null;
177
- }
178
- }
179
- }
180
- /**
181
- * Loads a `@db.rel.via` relation (M:N through a junction table).
182
- */
183
- async function loadViaRelation(rows, opts, host) {
184
- const { relName, relation, targetTable, relQuery } = opts;
185
- if (!relation.viaType || !host._tableResolver) return;
186
- const junctionType = relation.viaType();
187
- if (!junctionType) return;
188
- const junctionTable = host._tableResolver(junctionType);
189
- if (!junctionTable) {
190
- host.logger.warn(`Could not resolve junction table for via relation "${relName}"`);
191
- return;
192
- }
193
- const fkToThis = findRemoteFK(junctionTable, host.tableName);
194
- if (!fkToThis) {
195
- host.logger.warn(`Could not find FK on junction table pointing to "${host.tableName}" for via relation "${relName}"`);
196
- return;
197
- }
198
- const targetTableName = resolveRelationTargetTable(relation);
199
- const fkToTarget = findRemoteFK(junctionTable, targetTableName);
200
- if (!fkToTarget) {
201
- host.logger.warn(`Could not find FK on junction table pointing to target "${targetTableName}" for via relation "${relName}"`);
202
- return;
203
- }
204
- const localPKFields = fkToThis.targetFields;
205
- const junctionLocalFields = fkToThis.fields;
206
- const targetPKFields = fkToTarget.targetFields;
207
- const junctionTargetFields = fkToTarget.fields;
208
- if (localPKFields.length === 1) await loadViaSingleKey(rows, {
209
- relName,
210
- relation,
211
- targetTable,
212
- relQuery,
213
- localPKFields,
214
- junctionLocalFields,
215
- targetPKFields,
216
- junctionTargetFields,
217
- junctionTable
218
- });
219
- else await loadViaCompositeKey(rows, {
220
- relName,
221
- relation,
222
- targetTable,
223
- relQuery,
224
- localPKFields,
225
- junctionLocalFields,
226
- targetPKFields,
227
- junctionTargetFields,
228
- junctionTable
229
- });
230
- }
231
- async function loadViaSingleKey(rows, opts) {
232
- const { relName, relation, targetTable, relQuery, localPKFields, junctionLocalFields, targetPKFields, junctionTargetFields, junctionTable } = opts;
233
- const localField = localPKFields[0];
234
- const junctionLocalField = junctionLocalFields[0];
235
- const junctionTargetField = junctionTargetFields[0];
236
- const targetPKField = targetPKFields[0];
237
- const pkValues = collectUniqueValues(rows, localField);
238
- if (pkValues.length === 0) {
239
- for (const row of rows) row[relName] = [];
240
- return;
241
- }
242
- const junctionFilter = { [junctionLocalField]: { $in: pkValues } };
243
- const junctionRows = await junctionTable.findMany({
244
- filter: junctionFilter,
245
- controls: { $select: [junctionLocalField, junctionTargetField] }
246
- });
247
- if (junctionRows.length === 0) {
248
- for (const row of rows) row[relName] = relation.isArray ? [] : null;
249
- return;
250
- }
251
- const targetFKValues = collectUniqueValues(junctionRows, junctionTargetField);
252
- const inFilter = { [targetPKField]: { $in: targetFKValues } };
253
- const targetFilter = relQuery.filter ? { $and: [inFilter, relQuery.filter] } : inFilter;
254
- const controls = ensureSelectIncludesFields(relQuery.controls, targetPKFields);
255
- const targetRows = await targetTable.findMany({
256
- filter: targetFilter,
257
- controls
258
- });
259
- const targetIndex = /* @__PURE__ */ new Map();
260
- for (const item of targetRows) targetIndex.set(String(item[targetPKField]), item);
261
- const groups = /* @__PURE__ */ new Map();
262
- for (const jRow of junctionRows) {
263
- const localKey = String(jRow[junctionLocalField]);
264
- const targetKey = String(jRow[junctionTargetField]);
265
- const target = targetIndex.get(targetKey);
266
- if (!target) continue;
267
- let group = groups.get(localKey);
268
- if (!group) {
269
- group = [];
270
- groups.set(localKey, group);
271
- }
272
- group.push(target);
273
- }
274
- for (const row of rows) {
275
- const key = String(row[localField]);
276
- row[relName] = relation.isArray ? groups.get(key) ?? [] : groups.get(key)?.[0] ?? null;
277
- }
278
- }
279
- async function loadViaCompositeKey(rows, opts) {
280
- const { relName, relation, targetTable, relQuery, localPKFields, junctionLocalFields, targetPKFields, junctionTargetFields, junctionTable } = opts;
281
- const orFilters = [];
282
- for (const row of rows) {
283
- const condition = {};
284
- let valid = true;
285
- for (let i = 0; i < localPKFields.length; i++) {
286
- const val = row[localPKFields[i]];
287
- if (val === null || val === void 0) {
288
- valid = false;
289
- break;
290
- }
291
- condition[junctionLocalFields[i]] = val;
292
- }
293
- if (valid) orFilters.push(condition);
294
- }
295
- if (orFilters.length === 0) {
296
- for (const row of rows) row[relName] = relation.isArray ? [] : null;
297
- return;
298
- }
299
- const junctionFilter = orFilters.length === 1 ? orFilters[0] : { $or: orFilters };
300
- const junctionRows = await junctionTable.findMany({
301
- filter: junctionFilter,
302
- controls: { $select: [...junctionLocalFields, ...junctionTargetFields] }
303
- });
304
- if (junctionRows.length === 0) {
305
- for (const row of rows) row[relName] = relation.isArray ? [] : null;
306
- return;
307
- }
308
- const targetOrFilters = [];
309
- const seenTargets = /* @__PURE__ */ new Set();
310
- for (const jRow of junctionRows) {
311
- const key = compositeKey(junctionTargetFields, jRow);
312
- if (seenTargets.has(key)) continue;
313
- seenTargets.add(key);
314
- const condition = {};
315
- for (let i = 0; i < junctionTargetFields.length; i++) condition[targetPKFields[i]] = jRow[junctionTargetFields[i]];
316
- targetOrFilters.push(condition);
317
- }
318
- const targetBaseFilter = targetOrFilters.length === 1 ? targetOrFilters[0] : { $or: targetOrFilters };
319
- const finalFilter = relQuery.filter ? { $and: [targetBaseFilter, relQuery.filter] } : targetBaseFilter;
320
- const controls = ensureSelectIncludesFields(relQuery.controls, targetPKFields);
321
- const targetRows = await targetTable.findMany({
322
- filter: finalFilter,
323
- controls
324
- });
325
- const targetIndex = /* @__PURE__ */ new Map();
326
- for (const item of targetRows) targetIndex.set(compositeKey(targetPKFields, item), item);
327
- const groups = /* @__PURE__ */ new Map();
328
- for (const jRow of junctionRows) {
329
- const localKey = compositeKey(junctionLocalFields, jRow);
330
- const targetKey = compositeKey(junctionTargetFields, jRow);
331
- const target = targetIndex.get(targetKey);
332
- if (!target) continue;
333
- let group = groups.get(localKey);
334
- if (!group) {
335
- group = [];
336
- groups.set(localKey, group);
337
- }
338
- group.push(target);
339
- }
340
- for (const row of rows) {
341
- const key = compositeKey(localPKFields, row);
342
- row[relName] = relation.isArray ? groups.get(key) ?? [] : groups.get(key)?.[0] ?? null;
343
- }
344
- }
345
- /**
346
- * Ensure the given join fields survive the user's $select on a $with relation
347
- * read. Without this, the JS-side join would key off undefined and silently
348
- * return empty relations.
349
- *
350
- * - Array $select: append missing FK fields.
351
- * - Include-mode object $select (any value is 1/true, or empty object): set
352
- * missing FK fields to 1.
353
- * - Exclude-mode object $select: leave alone — FK survives by default. If the
354
- * FK is explicitly excluded, throw rather than silently override user intent.
355
- */
356
- function ensureSelectIncludesFields(controls, fields) {
357
- if (!controls) return controls;
358
- const sel = controls.$select;
359
- if (sel === void 0 || sel === null) return controls;
360
- if (Array.isArray(sel)) {
361
- const augmented = [...sel];
362
- for (const f of fields) if (!augmented.includes(f)) augmented.push(f);
363
- return {
364
- ...controls,
365
- $select: augmented
366
- };
367
- }
368
- if (typeof sel === "object") {
369
- const selObj = sel;
370
- const isInclude = Object.keys(selObj).length === 0 || Object.values(selObj).some((v) => v === 1 || v === true);
371
- const augmented = { ...selObj };
372
- let mutated = false;
373
- for (const f of fields) {
374
- const v = augmented[f];
375
- if (v === 0 || v === false) throw new Error(`Cannot exclude join column "${f}" from $select on $with relation`);
376
- if (v === void 0 && isInclude) {
377
- augmented[f] = 1;
378
- mutated = true;
379
- }
380
- }
381
- return mutated ? {
382
- ...controls,
383
- $select: augmented
384
- } : controls;
385
- }
386
- return controls;
387
- }
388
- function compositeKey(fields, obj) {
389
- let key = "";
390
- for (let i = 0; i < fields.length; i++) {
391
- if (i > 0) key += "\0\0";
392
- const v = obj[fields[i]];
393
- key += v === null || v === void 0 ? "\0" : String(v);
394
- }
395
- return key;
396
- }
397
- /** Collects unique non-null values for a field across rows. */
398
- function collectUniqueValues(rows, field) {
399
- const set = /* @__PURE__ */ new Set();
400
- for (const row of rows) {
401
- const v = row[field];
402
- if (v !== null && v !== void 0) set.add(v);
403
- }
404
- return [...set];
405
- }
406
- /** Assigns related items grouped by FK value (one-to-many). */
407
- function assignGrouped(opts) {
408
- const { rows, related, localField, remoteField, relName } = opts;
409
- const groups = /* @__PURE__ */ new Map();
410
- for (const item of related) {
411
- const key = item[remoteField];
412
- let group = groups.get(key);
413
- if (!group) {
414
- group = [];
415
- groups.set(key, group);
416
- }
417
- group.push(item);
418
- }
419
- for (const row of rows) row[relName] = groups.get(row[localField]) ?? [];
420
- }
421
- /** Assigns related items by FK value (many-to-one / one-to-one). */
422
- function assignSingle(opts) {
423
- const { rows, related, localField, remoteField, relName } = opts;
424
- const index = /* @__PURE__ */ new Map();
425
- for (const item of related) {
426
- const key = item[remoteField];
427
- if (!index.has(key)) index.set(key, item);
428
- }
429
- for (const row of rows) row[relName] = index.get(row[localField]) ?? null;
430
- }
431
- /** Batch query for composite FK. */
432
- function queryCompositeFK(rows, opts) {
433
- const { localFields, targetFields, targetTable, relQuery } = opts;
434
- const seen = /* @__PURE__ */ new Set();
435
- const orFilters = [];
436
- for (const row of rows) {
437
- const key = compositeKey(localFields, row);
438
- if (seen.has(key)) continue;
439
- seen.add(key);
440
- const condition = {};
441
- let valid = true;
442
- for (let i = 0; i < localFields.length; i++) {
443
- const val = row[localFields[i]];
444
- if (val === null || val === void 0) {
445
- valid = false;
446
- break;
447
- }
448
- condition[targetFields[i]] = val;
449
- }
450
- if (valid) orFilters.push(condition);
451
- }
452
- if (orFilters.length === 0) return Promise.resolve([]);
453
- const baseFilter = orFilters.length === 1 ? orFilters[0] : { $or: orFilters };
454
- const targetFilter = relQuery.filter ? { $and: [baseFilter, relQuery.filter] } : baseFilter;
455
- const controls = ensureSelectIncludesFields(relQuery.controls, targetFields);
456
- return targetTable.findMany({
457
- filter: targetFilter,
458
- controls
459
- });
460
- }
461
- //#endregion
462
- export { relation_loader_exports as n, loadRelationsImpl as t };