@rudderjs/orm 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -0
- package/dist/aggregate.d.ts +95 -0
- package/dist/aggregate.d.ts.map +1 -0
- package/dist/aggregate.js +390 -0
- package/dist/aggregate.js.map +1 -0
- package/dist/commands/prune.d.ts +18 -0
- package/dist/commands/prune.d.ts.map +1 -0
- package/dist/commands/prune.js +43 -0
- package/dist/commands/prune.js.map +1 -0
- package/dist/index.d.ts +220 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +620 -5
- package/dist/index.js.map +1 -1
- package/dist/prune.d.ts +27 -0
- package/dist/prune.d.ts.map +1 -0
- package/dist/prune.js +65 -0
- package/dist/prune.js.map +1 -0
- package/package.json +7 -3
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `where`/`orWhere`/`as` recorder passed to {@link AggregateConstraint}
|
|
3
|
+
* callbacks. Captures clauses for the adapter to AND into the aggregate
|
|
4
|
+
* subquery, plus an optional alias prefix override (`.as('publishedPosts')`).
|
|
5
|
+
*/
|
|
6
|
+
export class AggregateConstraintBuilder {
|
|
7
|
+
/** @internal */
|
|
8
|
+
_wheres = [];
|
|
9
|
+
/** @internal — alias prefix override; falls back to the relation name. */
|
|
10
|
+
_aliasPrefix;
|
|
11
|
+
where(column, valueOrOperator, maybeValue) {
|
|
12
|
+
if (maybeValue === undefined) {
|
|
13
|
+
this._wheres.push({ column, operator: '=', value: valueOrOperator });
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
this._wheres.push({ column, operator: valueOrOperator, value: maybeValue });
|
|
17
|
+
}
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
orWhere(column, valueOrOperator, maybeValue) {
|
|
21
|
+
if (maybeValue === undefined) {
|
|
22
|
+
this._wheres.push({ column, operator: '=', value: valueOrOperator });
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
this._wheres.push({ column, operator: valueOrOperator, value: maybeValue });
|
|
26
|
+
}
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Override the alias prefix used to stamp the aggregate column onto the
|
|
31
|
+
* result row. Default = relation name. The verb suffix (`Count`/`SumX`/etc.)
|
|
32
|
+
* is preserved, so `.as('publishedPosts')` on a `withCount` call yields
|
|
33
|
+
* `publishedPostsCount`.
|
|
34
|
+
*
|
|
35
|
+
* Required when calling the same `withCount` / `withSum` twice on different
|
|
36
|
+
* constraints — distinct aliases prevent the second from clobbering the first.
|
|
37
|
+
*/
|
|
38
|
+
as(alias) {
|
|
39
|
+
this._aliasPrefix = alias;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// ─── Symbol tag for hydration ──────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* Per-instance set of attribute keys that came from an aggregate eager-load,
|
|
46
|
+
* not from the underlying schema. Read by `Model._toData()` to skip these
|
|
47
|
+
* keys on writes and by callers that need to distinguish injected columns.
|
|
48
|
+
*
|
|
49
|
+
* Cross-realm-safe via `Symbol.for(...)` — distinct copies of `@rudderjs/orm`
|
|
50
|
+
* loaded by different module graphs share the same tag.
|
|
51
|
+
*/
|
|
52
|
+
export const AGGREGATES_SYMBOL = Symbol.for('rudderjs.orm.aggregates');
|
|
53
|
+
/** @internal — read or initialise the aggregate-key set on a Model instance. */
|
|
54
|
+
export function aggregateKeysOf(instance) {
|
|
55
|
+
const obj = instance;
|
|
56
|
+
let set = obj[AGGREGATES_SYMBOL];
|
|
57
|
+
if (!set) {
|
|
58
|
+
set = new Set();
|
|
59
|
+
Object.defineProperty(instance, AGGREGATES_SYMBOL, {
|
|
60
|
+
value: set,
|
|
61
|
+
writable: true,
|
|
62
|
+
configurable: true,
|
|
63
|
+
enumerable: false,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return set;
|
|
67
|
+
}
|
|
68
|
+
// ─── Alias suffix ──────────────────────────────────────────
|
|
69
|
+
function _capitalize(s) {
|
|
70
|
+
if (s.length === 0)
|
|
71
|
+
return s;
|
|
72
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The verb suffix that distinguishes which aggregate is stamped on the parent.
|
|
76
|
+
* Combined with the relation name (or `.as(...)` override) to produce the
|
|
77
|
+
* final alias key — e.g. `posts` + `count` → `postsCount`,
|
|
78
|
+
* `posts` + sum of `views` → `postsSumViews`.
|
|
79
|
+
*/
|
|
80
|
+
export function aggregateSuffix(fn, column) {
|
|
81
|
+
switch (fn) {
|
|
82
|
+
case 'count': return 'Count';
|
|
83
|
+
case 'exists': return 'Exists';
|
|
84
|
+
case 'sum': return 'Sum' + _capitalize(column ?? '');
|
|
85
|
+
case 'min': return 'Min' + _capitalize(column ?? '');
|
|
86
|
+
case 'max': return 'Max' + _capitalize(column ?? '');
|
|
87
|
+
case 'avg': return 'Avg' + _capitalize(column ?? '');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export function aggregateAlias(fn, baseAlias, column) {
|
|
91
|
+
return baseAlias + aggregateSuffix(fn, column);
|
|
92
|
+
}
|
|
93
|
+
// ─── Join-shape resolution ─────────────────────────────────
|
|
94
|
+
function _camelHead(s) {
|
|
95
|
+
return s.charAt(0).toLowerCase() + s.slice(1);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Build the {@link AggregateJoinShape} for a relation declared on `Parent`.
|
|
99
|
+
* Mirrors `_buildRelationPredicate` but emits the join-shape subset rather
|
|
100
|
+
* than the full {@link RelationExistencePredicate}. `morphTo` and `belongsTo`
|
|
101
|
+
* are rejected by the caller before reaching this function; everything else
|
|
102
|
+
* routes through.
|
|
103
|
+
*/
|
|
104
|
+
export function buildAggregateJoinShape(Parent, relation, def) {
|
|
105
|
+
const Related = def.model();
|
|
106
|
+
const softDeletes = Related.softDeletes;
|
|
107
|
+
if (def.type === 'belongsToMany') {
|
|
108
|
+
const parentKey = def.parentKey ?? Parent.primaryKey;
|
|
109
|
+
const relatedKey = def.relatedKey ?? Related.primaryKey;
|
|
110
|
+
const foreignPivotKey = def.foreignPivotKey ?? `${_camelHead(Parent.name)}Id`;
|
|
111
|
+
const relatedPivotKey = def.relatedPivotKey ?? `${_camelHead(Related.name)}Id`;
|
|
112
|
+
return {
|
|
113
|
+
relatedTable: Related.getTable(),
|
|
114
|
+
parentColumn: parentKey,
|
|
115
|
+
relatedColumn: relatedKey,
|
|
116
|
+
through: {
|
|
117
|
+
pivotTable: def.pivotTable,
|
|
118
|
+
foreignPivotKey,
|
|
119
|
+
relatedPivotKey,
|
|
120
|
+
},
|
|
121
|
+
...(softDeletes && { softDeletes: true }),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
if (def.type === 'morphToMany') {
|
|
125
|
+
const parentKey = def.parentKey ?? Parent.primaryKey;
|
|
126
|
+
const relatedKey = def.relatedKey ?? Related.primaryKey;
|
|
127
|
+
const foreignPivotKey = `${def.morphName}Id`;
|
|
128
|
+
const morphTypeKey = `${def.morphName}Type`;
|
|
129
|
+
const morphTypeValue = def.morphType ?? Parent.morphAlias ?? Parent.name;
|
|
130
|
+
const relatedPivotKey = def.relatedPivotKey ?? `${_camelHead(Related.name)}Id`;
|
|
131
|
+
return {
|
|
132
|
+
relatedTable: Related.getTable(),
|
|
133
|
+
parentColumn: parentKey,
|
|
134
|
+
relatedColumn: relatedKey,
|
|
135
|
+
extraEquals: { [morphTypeKey]: morphTypeValue },
|
|
136
|
+
through: {
|
|
137
|
+
pivotTable: def.pivotTable,
|
|
138
|
+
foreignPivotKey,
|
|
139
|
+
relatedPivotKey,
|
|
140
|
+
},
|
|
141
|
+
...(softDeletes && { softDeletes: true }),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (def.type === 'morphedByMany') {
|
|
145
|
+
const parentKey = def.parentKey ?? Parent.primaryKey;
|
|
146
|
+
const relatedKey = def.relatedKey ?? Related.primaryKey;
|
|
147
|
+
const foreignPivotKey = def.foreignPivotKey ?? `${_camelHead(Parent.name)}Id`;
|
|
148
|
+
const morphTypeKey = `${def.morphName}Type`;
|
|
149
|
+
const morphTypeValue = def.morphType ?? Related.morphAlias ?? Related.name;
|
|
150
|
+
const relatedPivotKey = `${def.morphName}Id`;
|
|
151
|
+
return {
|
|
152
|
+
relatedTable: Related.getTable(),
|
|
153
|
+
parentColumn: parentKey,
|
|
154
|
+
relatedColumn: relatedKey,
|
|
155
|
+
extraEquals: { [morphTypeKey]: morphTypeValue },
|
|
156
|
+
through: {
|
|
157
|
+
pivotTable: def.pivotTable,
|
|
158
|
+
foreignPivotKey,
|
|
159
|
+
relatedPivotKey,
|
|
160
|
+
},
|
|
161
|
+
...(softDeletes && { softDeletes: true }),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (def.type === 'morphMany' || def.type === 'morphOne') {
|
|
165
|
+
const idCol = `${def.morphName}Id`;
|
|
166
|
+
const typeCol = `${def.morphName}Type`;
|
|
167
|
+
const localCol = def.localKey ?? Parent.primaryKey;
|
|
168
|
+
const typeVal = def.morphType ?? Parent.morphAlias ?? Parent.name;
|
|
169
|
+
return {
|
|
170
|
+
relatedTable: Related.getTable(),
|
|
171
|
+
parentColumn: localCol,
|
|
172
|
+
relatedColumn: idCol,
|
|
173
|
+
extraEquals: { [typeCol]: typeVal },
|
|
174
|
+
...(softDeletes && { softDeletes: true }),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// hasOne / hasMany — related table holds the FK pointing back to Parent.
|
|
178
|
+
const fk = def.foreignKey ?? `${_camelHead(Parent.name)}Id`;
|
|
179
|
+
const localCol = def.localKey ?? Parent.primaryKey;
|
|
180
|
+
return {
|
|
181
|
+
relatedTable: Related.getTable(),
|
|
182
|
+
parentColumn: localCol,
|
|
183
|
+
relatedColumn: fk,
|
|
184
|
+
...(softDeletes && { softDeletes: true }),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Run a constraint callback against a fresh {@link AggregateConstraintBuilder}
|
|
189
|
+
* and return the recorded clauses + alias override. Keeps the construction
|
|
190
|
+
* side-effect-free on the parent QB.
|
|
191
|
+
*/
|
|
192
|
+
function _runConstraint(constraint) {
|
|
193
|
+
const builder = new AggregateConstraintBuilder();
|
|
194
|
+
constraint(builder);
|
|
195
|
+
const out = { wheres: builder._wheres };
|
|
196
|
+
if (builder._aliasPrefix !== undefined)
|
|
197
|
+
out.aliasPrefix = builder._aliasPrefix;
|
|
198
|
+
return out;
|
|
199
|
+
}
|
|
200
|
+
function _resolveDef(Parent, relation) {
|
|
201
|
+
const def = Parent.relations[relation];
|
|
202
|
+
if (!def) {
|
|
203
|
+
throw new Error(`[RudderJS ORM] Relation "${relation}" is not defined on ${Parent.name}.`);
|
|
204
|
+
}
|
|
205
|
+
if (def.type === 'morphTo') {
|
|
206
|
+
throw new Error(`[RudderJS ORM] withCount() on morphTo "${relation}" is not supported — the related table is dynamic. ` +
|
|
207
|
+
`Aggregate per-target by querying each target class separately.`);
|
|
208
|
+
}
|
|
209
|
+
if (def.type === 'belongsTo') {
|
|
210
|
+
throw new Error(`[RudderJS ORM] withCount on belongsTo "${relation}" is ambiguous — every parent matches exactly one. ` +
|
|
211
|
+
`Use withExists("${relation}") to test presence or query the inverse hasMany side.`);
|
|
212
|
+
}
|
|
213
|
+
return def;
|
|
214
|
+
}
|
|
215
|
+
function _buildRequest(Parent, relation, fn, column, constraint) {
|
|
216
|
+
const def = _resolveDef(Parent, relation);
|
|
217
|
+
const joinShape = buildAggregateJoinShape(Parent, relation, def);
|
|
218
|
+
const captured = constraint ? _runConstraint(constraint) : undefined;
|
|
219
|
+
const baseAlias = captured?.aliasPrefix ?? relation;
|
|
220
|
+
const req = {
|
|
221
|
+
relation,
|
|
222
|
+
fn,
|
|
223
|
+
alias: aggregateAlias(fn, baseAlias, column),
|
|
224
|
+
joinShape,
|
|
225
|
+
constraintWheres: captured?.wheres ?? [],
|
|
226
|
+
};
|
|
227
|
+
if (column !== undefined)
|
|
228
|
+
req.column = column;
|
|
229
|
+
return req;
|
|
230
|
+
}
|
|
231
|
+
function _normalizeRelationsMap(Parent, relations, fn) {
|
|
232
|
+
return Object.entries(relations).map(([relation, constraint]) => _buildRequest(Parent, relation, fn, undefined, constraint));
|
|
233
|
+
}
|
|
234
|
+
function _normalizeStringList(Parent, relations, fn) {
|
|
235
|
+
return relations.map(r => _buildRequest(Parent, r, fn, undefined, undefined));
|
|
236
|
+
}
|
|
237
|
+
/** Public entrypoint: normalize all `withCount(...)` overloads. */
|
|
238
|
+
export function normalizeWithCount(Parent, arg) {
|
|
239
|
+
if (typeof arg === 'string')
|
|
240
|
+
return [_buildRequest(Parent, arg, 'count', undefined, undefined)];
|
|
241
|
+
if (Array.isArray(arg))
|
|
242
|
+
return _normalizeStringList(Parent, arg, 'count');
|
|
243
|
+
return _normalizeRelationsMap(Parent, arg, 'count');
|
|
244
|
+
}
|
|
245
|
+
/** Public entrypoint: normalize all `withExists(...)` overloads. */
|
|
246
|
+
export function normalizeWithExists(Parent, arg) {
|
|
247
|
+
if (typeof arg === 'string')
|
|
248
|
+
return [_buildRequest(Parent, arg, 'exists', undefined, undefined)];
|
|
249
|
+
return _normalizeStringList(Parent, arg, 'exists');
|
|
250
|
+
}
|
|
251
|
+
/** Public entrypoint: normalize all `withSum/withMin/withMax/withAvg(...)` overloads. */
|
|
252
|
+
export function normalizeWithNumericAggregate(Parent, fn, arg1, arg2) {
|
|
253
|
+
if (typeof arg1 === 'string') {
|
|
254
|
+
if (arg2 === undefined) {
|
|
255
|
+
throw new Error(`[RudderJS ORM] with${_capitalize(fn)}("${arg1}") requires a column argument.`);
|
|
256
|
+
}
|
|
257
|
+
return [_buildRequest(Parent, arg1, fn, arg2, undefined)];
|
|
258
|
+
}
|
|
259
|
+
return Object.entries(arg1).map(([relation, spec]) => _buildRequest(Parent, relation, fn, spec.column, spec.constraint));
|
|
260
|
+
}
|
|
261
|
+
// ─── Instance load path ────────────────────────────────────
|
|
262
|
+
/**
|
|
263
|
+
* Resolve the related Model class for `relation` on `Parent`. Throws on
|
|
264
|
+
* unknown relations and (for the aggregate path) on `morphTo` — the related
|
|
265
|
+
* class is dynamic, no scalar aggregate possible.
|
|
266
|
+
*/
|
|
267
|
+
function _relatedClassFor(Parent, relation) {
|
|
268
|
+
const def = Parent.relations[relation];
|
|
269
|
+
if (!def) {
|
|
270
|
+
throw new Error(`[RudderJS ORM] Relation "${relation}" is not defined on ${Parent.name}.`);
|
|
271
|
+
}
|
|
272
|
+
if (def.type === 'morphTo') {
|
|
273
|
+
throw new Error(`[RudderJS ORM] loadCount() on morphTo "${relation}" is not supported — the related table is dynamic.`);
|
|
274
|
+
}
|
|
275
|
+
return def.model();
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Build a chainable QB on `Related` filtered to `instance` for the given
|
|
279
|
+
* relation, with `constraintWheres` already AND-merged. Returns the QB ready
|
|
280
|
+
* for a terminal call (`count()`, `_aggregate(fn, column)`, etc.).
|
|
281
|
+
*
|
|
282
|
+
* Reuses `instance.related(name)` so the whole pivot/morph plumbing stays in
|
|
283
|
+
* one place — for `belongsTo`/`hasOne`/`hasMany`/`morph*` it's a direct
|
|
284
|
+
* single-step query; for `belongsToMany`/`morphToMany`/`morphedByMany` it's a
|
|
285
|
+
* deferred Proxy that resolves the pivot lookup on terminal call.
|
|
286
|
+
*/
|
|
287
|
+
function _instanceRelatedQb(instance, relation, constraintWheres) {
|
|
288
|
+
// The deferred pivot Proxy doesn't expose `_aggregate` directly; for
|
|
289
|
+
// pivot-mediated relations we need to wait for the inner Related QB to be
|
|
290
|
+
// resolved. The simplest portable path: lazily call `.where(...).count()`
|
|
291
|
+
// (or `_aggregate(...)`) and trust the Proxy to forward terminal calls.
|
|
292
|
+
// The deferred Proxy in index.ts whitelists known terminals via
|
|
293
|
+
// `_TERMINAL_METHODS`, which doesn't include `_aggregate`. To keep the
|
|
294
|
+
// public deferred shape stable, the load path here only uses public
|
|
295
|
+
// terminal forms (`count`/`get`) — see _scalarAggregateOnQb below.
|
|
296
|
+
let qb = instance.related(relation);
|
|
297
|
+
for (const w of constraintWheres) {
|
|
298
|
+
qb = qb.where(w.column, w.operator, w.value);
|
|
299
|
+
}
|
|
300
|
+
return qb;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Run a single-scalar aggregate on `qb`. Prefers the contract's `_aggregate`
|
|
304
|
+
* terminal (Prisma + Drizzle adapters) when available; falls back to
|
|
305
|
+
* portable `count()` / `get()` for the deferred pivot Proxy and any
|
|
306
|
+
* future adapter that hasn't implemented `_aggregate`.
|
|
307
|
+
*/
|
|
308
|
+
async function _scalarAggregateOnQb(qb, fn, column) {
|
|
309
|
+
const direct = qb._aggregate;
|
|
310
|
+
if (typeof direct === 'function') {
|
|
311
|
+
return direct.call(qb, fn, column);
|
|
312
|
+
}
|
|
313
|
+
// Fallback for the deferred pivot Proxy: use whatever public terminal we have.
|
|
314
|
+
if (fn === 'count' || fn === 'exists') {
|
|
315
|
+
const n = await qb.count();
|
|
316
|
+
return fn === 'exists' ? n > 0 : n;
|
|
317
|
+
}
|
|
318
|
+
// sum/min/max/avg can't be expressed without `_aggregate` — load the rows
|
|
319
|
+
// and compute in JS. Acceptable for instance-level loads; the parent QB
|
|
320
|
+
// path uses the adapter's native aggregate selector.
|
|
321
|
+
const rows = await qb.get();
|
|
322
|
+
return _jsAggregate(fn, column, rows);
|
|
323
|
+
}
|
|
324
|
+
function _jsAggregate(fn, column, rows) {
|
|
325
|
+
if (rows.length === 0) {
|
|
326
|
+
if (fn === 'sum')
|
|
327
|
+
return 0;
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
const nums = rows.map(r => Number(r[column])).filter(n => !Number.isNaN(n));
|
|
331
|
+
if (nums.length === 0) {
|
|
332
|
+
if (fn === 'sum')
|
|
333
|
+
return 0;
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
switch (fn) {
|
|
337
|
+
case 'sum': return nums.reduce((a, b) => a + b, 0);
|
|
338
|
+
case 'min': return Math.min(...nums);
|
|
339
|
+
case 'max': return Math.max(...nums);
|
|
340
|
+
case 'avg': return nums.reduce((a, b) => a + b, 0) / nums.length;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Apply a single aggregate request against `instance`, stamping the result
|
|
345
|
+
* onto `instance[req.alias]` and tagging the alias on the aggregates Symbol.
|
|
346
|
+
*/
|
|
347
|
+
async function _applyInstanceAggregate(instance, req) {
|
|
348
|
+
const qb = _instanceRelatedQb(instance, req.relation, req.constraintWheres);
|
|
349
|
+
const value = await _scalarAggregateOnQb(qb, req.fn, req.column);
|
|
350
|
+
instance[req.alias] = value;
|
|
351
|
+
aggregateKeysOf(instance).add(req.alias);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Implementation of `Model#loadCount` / `loadExists`. Mutates the instance
|
|
355
|
+
* in place; returns it for chaining at the call site.
|
|
356
|
+
*/
|
|
357
|
+
export async function loadCountOrExists(instance, fn, arg) {
|
|
358
|
+
const ctor = instance.constructor;
|
|
359
|
+
const reqs = fn === 'count' ? normalizeWithCount(ctor, arg) : normalizeWithExists(ctor, arg);
|
|
360
|
+
for (const r of reqs)
|
|
361
|
+
await _applyInstanceAggregate(instance, r);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Implementation of `Model#loadSum` / `loadMin` / `loadMax` / `loadAvg`.
|
|
365
|
+
*/
|
|
366
|
+
export async function loadNumericAggregate(instance, fn, relation, column) {
|
|
367
|
+
const ctor = instance.constructor;
|
|
368
|
+
const reqs = normalizeWithNumericAggregate(ctor, fn, relation, column);
|
|
369
|
+
for (const r of reqs)
|
|
370
|
+
await _applyInstanceAggregate(instance, r);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Implementation of `Model#loadMissing`. Loads each named relation onto the
|
|
374
|
+
* instance only when the property is currently `null` / `undefined`.
|
|
375
|
+
*
|
|
376
|
+
* Always uses `instance.related(name).get()` (the chainable QB form) — for
|
|
377
|
+
* `hasOne` / `belongsTo` / `morphOne` semantics the caller can `[0]` the
|
|
378
|
+
* resulting array if they know the relation is single-valued, or call
|
|
379
|
+
* `loadMissing` only on the *array* relations they care about.
|
|
380
|
+
*/
|
|
381
|
+
export async function loadMissingRelations(instance, names) {
|
|
382
|
+
for (const name of names) {
|
|
383
|
+
const cur = instance[name];
|
|
384
|
+
if (cur !== undefined && cur !== null)
|
|
385
|
+
continue;
|
|
386
|
+
const rows = await instance.related(name).get();
|
|
387
|
+
instance[name] = rows;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
//# sourceMappingURL=aggregate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../src/aggregate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type Rudder = {
|
|
2
|
+
command(name: string, handler: (args: string[]) => void | Promise<void>): {
|
|
3
|
+
description(text: string): unknown;
|
|
4
|
+
};
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Register `pnpm rudder model:prune`.
|
|
8
|
+
*
|
|
9
|
+
* Walks the {@link import('../index.js').ModelRegistry} and prunes every
|
|
10
|
+
* registered model that defines `static prunable()`. Filter with
|
|
11
|
+
* `--model=A,B`, exclude with `--except=A`, change batch size with
|
|
12
|
+
* `--chunk=N`, dry-run with `--pretend`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerPruneCommand(rudder: Rudder): void;
|
|
15
|
+
/** Tiny `--name=value` / `--name value` parser, mirrors migrate.ts style. */
|
|
16
|
+
export declare function arg(args: string[], name: string): string | undefined;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=prune.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../../src/commands/prune.ts"],"names":[],"mappings":"AAEA,KAAK,MAAM,GAAG;IACZ,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAChD;QAAE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CAC1C,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAwBzD;AAED,6EAA6E;AAC7E,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKpE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { pruneModels } from '../prune.js';
|
|
2
|
+
/**
|
|
3
|
+
* Register `pnpm rudder model:prune`.
|
|
4
|
+
*
|
|
5
|
+
* Walks the {@link import('../index.js').ModelRegistry} and prunes every
|
|
6
|
+
* registered model that defines `static prunable()`. Filter with
|
|
7
|
+
* `--model=A,B`, exclude with `--except=A`, change batch size with
|
|
8
|
+
* `--chunk=N`, dry-run with `--pretend`.
|
|
9
|
+
*/
|
|
10
|
+
export function registerPruneCommand(rudder) {
|
|
11
|
+
rudder.command('model:prune', async (args) => {
|
|
12
|
+
const opts = { pretend: args.includes('--pretend') };
|
|
13
|
+
const models = arg(args, '--model')?.split(',').map(s => s.trim()).filter(Boolean);
|
|
14
|
+
const except = arg(args, '--except')?.split(',').map(s => s.trim()).filter(Boolean);
|
|
15
|
+
const chunk = arg(args, '--chunk');
|
|
16
|
+
if (models?.length)
|
|
17
|
+
opts.models = models;
|
|
18
|
+
if (except?.length)
|
|
19
|
+
opts.except = except;
|
|
20
|
+
if (chunk !== undefined)
|
|
21
|
+
opts.chunk = Number(chunk);
|
|
22
|
+
const reports = await pruneModels(opts);
|
|
23
|
+
if (reports.length === 0) {
|
|
24
|
+
console.log(' No prunable models registered.');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const verb = opts.pretend ? 'Would prune' : 'Pruned';
|
|
28
|
+
for (const r of reports) {
|
|
29
|
+
console.log(` ${verb} ${r.count.toLocaleString()} ${r.model} (${r.mode})`);
|
|
30
|
+
}
|
|
31
|
+
const total = reports.reduce((n, r) => n + r.count, 0);
|
|
32
|
+
console.log(` ${verb.toLowerCase()} ${total.toLocaleString()} record(s) across ${reports.length} model(s).`);
|
|
33
|
+
}).description('Prune records from models implementing Prunable / MassPrunable — pnpm rudder model:prune [--model=A,B] [--except=X] [--chunk=N] [--pretend]');
|
|
34
|
+
}
|
|
35
|
+
/** Tiny `--name=value` / `--name value` parser, mirrors migrate.ts style. */
|
|
36
|
+
export function arg(args, name) {
|
|
37
|
+
const eq = args.find(a => a.startsWith(`${name}=`));
|
|
38
|
+
if (eq)
|
|
39
|
+
return eq.slice(name.length + 1);
|
|
40
|
+
const idx = args.indexOf(name);
|
|
41
|
+
return idx !== -1 ? args[idx + 1] : undefined;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../src/commands/prune.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AASzC;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,KAAK,EAAE,IAAc,EAAE,EAAE;QACrD,MAAM,IAAI,GAAuC,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAA;QACxF,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAClF,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACnF,MAAM,KAAK,GAAI,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QACnC,IAAI,MAAM,EAAE,MAAM;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACxC,IAAI,MAAM,EAAE,MAAM;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACxC,IAAI,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAEnD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAA;QAEvC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAA;YAC/C,OAAM;QACR,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAA;QACpD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAA;QAC7E,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACtD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,cAAc,EAAE,qBAAqB,OAAO,CAAC,MAAM,YAAY,CAAC,CAAA;IAC/G,CAAC,CAAC,CAAC,WAAW,CAAC,6IAA6I,CAAC,CAAA;AAC/J,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,GAAG,CAAC,IAAc,EAAE,IAAY;IAC9C,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAA;IACnD,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACxC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC/C,CAAC"}
|