bun-query-builder 0.1.27 → 0.1.28
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 +16 -7
- package/dist/browser.d.ts +5 -2
- package/dist/client.d.ts +14 -7
- package/dist/orm.d.ts +30 -30
- package/dist/src/index.js +15 -6
- package/dist/type-inference.d.ts +34 -104
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -14728,17 +14728,15 @@ function createQueryBuilder(state) {
|
|
|
14728
14728
|
addWhereText("WHERE", `${String(col)} IS ${onlyTrashed ? "NOT " : ""}NULL`);
|
|
14729
14729
|
}
|
|
14730
14730
|
}
|
|
14731
|
+
const cacheKey = useCache ? `${String(finalQuery)}\x00${JSON.stringify(whereParams)}` : "";
|
|
14731
14732
|
if (useCache) {
|
|
14732
|
-
const cacheKey = String(finalQuery);
|
|
14733
14733
|
const cached = queryCache.get(cacheKey);
|
|
14734
14734
|
if (cached)
|
|
14735
14735
|
return cached;
|
|
14736
14736
|
}
|
|
14737
14737
|
const result = await runWithHooks(finalQuery, "select", { signal: abortSignal, timeoutMs });
|
|
14738
|
-
if (useCache)
|
|
14739
|
-
const cacheKey = String(finalQuery);
|
|
14738
|
+
if (useCache)
|
|
14740
14739
|
queryCache.set(cacheKey, result, cacheTtl);
|
|
14741
|
-
}
|
|
14742
14740
|
return hydratePivotRows(result);
|
|
14743
14741
|
},
|
|
14744
14742
|
async executeTakeFirst() {
|
|
@@ -23803,6 +23801,13 @@ function assertValidIdentifier(name, context) {
|
|
|
23803
23801
|
if (!SAFE_SQL_IDENTIFIER.test(name))
|
|
23804
23802
|
throw new TypeError(`[bun-query-builder] ${context}: identifier '${name}' contains characters outside [A-Za-z0-9_] \u2014 refusing to interpolate into SQL`);
|
|
23805
23803
|
}
|
|
23804
|
+
function assertValidOrderByColumn(name, context) {
|
|
23805
|
+
if (typeof name !== "string" || name.length === 0)
|
|
23806
|
+
throw new TypeError(`[bun-query-builder] ${context}: identifier must be a non-empty string, got ${typeof name}`);
|
|
23807
|
+
const parts = name.split(".");
|
|
23808
|
+
if (parts.length > 2 || parts.some((p2) => p2.length === 0 || p2.length > 64 || !SAFE_SQL_IDENTIFIER.test(p2)))
|
|
23809
|
+
throw new TypeError(`[bun-query-builder] ${context}: invalid ORDER BY column '${name}' \u2014 expected 'column' or 'table.column' of [A-Za-z0-9_] \u2014 refusing to interpolate into SQL`);
|
|
23810
|
+
}
|
|
23806
23811
|
function getModelFromRegistry(name) {
|
|
23807
23812
|
if (!_getModel) {
|
|
23808
23813
|
try {
|
|
@@ -24091,12 +24096,16 @@ class ModelInstance {
|
|
|
24091
24096
|
for (const [key, value] of Object.entries(data)) {
|
|
24092
24097
|
const attr = attrs[key];
|
|
24093
24098
|
if (attr?.fillable && !attr?.guarded) {
|
|
24099
|
+
if (this._original === null)
|
|
24100
|
+
this._original = { ...this._attributes };
|
|
24094
24101
|
this._attributes[key] = value;
|
|
24095
24102
|
}
|
|
24096
24103
|
}
|
|
24097
24104
|
return this;
|
|
24098
24105
|
}
|
|
24099
24106
|
forceFill(data) {
|
|
24107
|
+
if (this._original === null)
|
|
24108
|
+
this._original = { ...this._attributes };
|
|
24100
24109
|
Object.assign(this._attributes, data);
|
|
24101
24110
|
return this;
|
|
24102
24111
|
}
|
|
@@ -24492,7 +24501,7 @@ class BelongsToManyRelationBuilder {
|
|
|
24492
24501
|
return this;
|
|
24493
24502
|
}
|
|
24494
24503
|
orderBy(column, direction = "asc") {
|
|
24495
|
-
|
|
24504
|
+
assertValidOrderByColumn(column, "orderBy(column)");
|
|
24496
24505
|
if (direction !== "asc" && direction !== "desc")
|
|
24497
24506
|
throw new TypeError(`[bun-query-builder] orderBy(direction): expected 'asc' or 'desc', got '${direction}'`);
|
|
24498
24507
|
this._orderBy.push(`${column} ${direction.toUpperCase()}`);
|
|
@@ -24833,7 +24842,7 @@ class ModelQueryBuilder {
|
|
|
24833
24842
|
return this;
|
|
24834
24843
|
}
|
|
24835
24844
|
orderBy(column, direction = "asc") {
|
|
24836
|
-
|
|
24845
|
+
assertValidOrderByColumn(column, "orderBy(column)");
|
|
24837
24846
|
if (direction !== "asc" && direction !== "desc")
|
|
24838
24847
|
throw new TypeError(`[bun-query-builder] orderBy(direction): expected 'asc' or 'desc', got '${direction}'`);
|
|
24839
24848
|
this._orderBy.push({ column, direction });
|
|
@@ -29920,7 +29929,7 @@ function getPrefix() {
|
|
|
29920
29929
|
}
|
|
29921
29930
|
var prefix = getPrefix();
|
|
29922
29931
|
// package.json
|
|
29923
|
-
var version2 = "0.1.
|
|
29932
|
+
var version2 = "0.1.28";
|
|
29924
29933
|
|
|
29925
29934
|
// bin/cli.ts
|
|
29926
29935
|
init_actions();
|
package/dist/browser.d.ts
CHANGED
|
@@ -201,9 +201,12 @@ declare type BrowserAttributeKeys<TDef extends BrowserModelDefinition> = keyof T
|
|
|
201
201
|
declare type InferBrowserAttributeType<TAttr> = TAttr extends { type: infer T } ? InferType<T> :
|
|
202
202
|
TAttr extends { factory: (faker: unknown) => infer R } ? R :
|
|
203
203
|
unknown;
|
|
204
|
-
// Build the full attributes type from definition
|
|
204
|
+
// Build the full attributes type from definition. Columns declared
|
|
205
|
+
// `nullable: true` admit null — mirrors InferAttributes in type-inference.ts.
|
|
205
206
|
declare type InferBrowserModelAttributes<TDef extends BrowserModelDefinition> = {
|
|
206
|
-
[K in BrowserAttributeKeys<TDef>]:
|
|
207
|
+
[K in BrowserAttributeKeys<TDef>]: TDef['attributes'][K] extends { nullable: true }
|
|
208
|
+
? InferBrowserAttributeType<TDef['attributes'][K]> | null
|
|
209
|
+
: InferBrowserAttributeType<TDef['attributes'][K]>
|
|
207
210
|
}
|
|
208
211
|
// System fields added by traits
|
|
209
212
|
declare type BrowserSystemFields<TDef extends BrowserModelDefinition> = { id: number } &
|
package/dist/client.d.ts
CHANGED
|
@@ -413,22 +413,29 @@ declare type JoinColumn<DB extends DatabaseSchema<any>, TTables extends string>
|
|
|
413
413
|
*
|
|
414
414
|
* The relation names declared for a table, read from the type-level
|
|
415
415
|
* `relations` map that `DatabaseSchema` carries. Falls back to `string`
|
|
416
|
-
* for hand-written schema types that don't declare relation metadata
|
|
417
|
-
*
|
|
416
|
+
* for hand-written schema types that don't declare relation metadata
|
|
417
|
+
* (inferred `R` is `unknown` when the property is absent), so existing
|
|
418
|
+
* untyped schemas keep compiling. A table that declares ZERO relations
|
|
419
|
+
* yields `never` — every relation name is rejected.
|
|
418
420
|
*/
|
|
419
421
|
export type TableRelationName<DB extends DatabaseSchema<any>, TTable extends keyof DB & string> = DB[TTable] extends { relations?: infer R }
|
|
420
|
-
?
|
|
422
|
+
? unknown extends R ? string : keyof NonNullable<R> & string
|
|
421
423
|
: string;
|
|
422
424
|
/**
|
|
423
425
|
* # `WithRelationArg<DB, TTable>`
|
|
424
426
|
*
|
|
425
427
|
* Argument accepted by `.with()`: a declared relation name, a dotted nested
|
|
426
428
|
* path rooted at a declared relation (`'posts.comments'`), or a record
|
|
427
|
-
* mapping relation names to constraint callbacks.
|
|
429
|
+
* mapping relation names to constraint callbacks. A table with zero declared
|
|
430
|
+
* relations accepts nothing (the bare `Partial<Record<never, ...>>` would be
|
|
431
|
+
* `{}`, which strings are assignable to — hence the explicit never guard).
|
|
428
432
|
*/
|
|
429
|
-
export type WithRelationArg<DB extends DatabaseSchema<any>, TTable extends keyof DB & string> =
|
|
430
|
-
|
|
431
|
-
|
|
433
|
+
export type WithRelationArg<DB extends DatabaseSchema<any>, TTable extends keyof DB & string> = [TableRelationName<DB, TTable>] extends [never]
|
|
434
|
+
? never
|
|
435
|
+
:
|
|
436
|
+
| TableRelationName<DB, TTable>
|
|
437
|
+
| `${TableRelationName<DB, TTable>}.${string}`
|
|
438
|
+
| Partial<Record<TableRelationName<DB, TTable>, (qb: any) => any>>;
|
|
432
439
|
// Convert snake_case to PascalCase at the type level (e.g. created_at -> CreatedAt)
|
|
433
440
|
declare type SnakeToPascal<S extends string> = S extends `${infer H}_${infer T}`
|
|
434
441
|
? `${Capitalize<H>}${SnakeToPascal<T>}`
|
package/dist/orm.d.ts
CHANGED
|
@@ -196,12 +196,17 @@ declare type AttributeKeys<TDef extends ModelDefinition> = keyof TDef['attribute
|
|
|
196
196
|
declare type InferAttributeType<TAttr> = TAttr extends { type: infer T } ? InferType<T> :
|
|
197
197
|
TAttr extends { factory: (faker: Faker) => infer R } ? R :
|
|
198
198
|
unknown;
|
|
199
|
-
// Build the full attributes type from definition
|
|
199
|
+
// Build the full attributes type from definition. Columns declared
|
|
200
|
+
// `nullable: true` admit null — mirrors InferAttributes in type-inference.ts.
|
|
200
201
|
declare type InferModelAttributes<TDef extends ModelDefinition> = {
|
|
201
|
-
[K in AttributeKeys<TDef>]:
|
|
202
|
+
[K in AttributeKeys<TDef>]: TDef['attributes'][K] extends { nullable: true }
|
|
203
|
+
? InferAttributeType<TDef['attributes'][K]> | null
|
|
204
|
+
: InferAttributeType<TDef['attributes'][K]>
|
|
202
205
|
}
|
|
203
|
-
// System fields added by traits
|
|
204
|
-
|
|
206
|
+
// System fields added by traits. The primary-key column honors the model's
|
|
207
|
+
// declared `primaryKey` (default 'id') — a custom-pk model exposes THAT
|
|
208
|
+
// column, not a phantom 'id'. Mirrors InferAttributes in type-inference.ts.
|
|
209
|
+
declare type SystemFields<TDef extends ModelDefinition> = { [K in TDef extends { primaryKey: infer PK extends string } ? PK : 'id']: number } &
|
|
205
210
|
(TDef['traits'] extends { useUuid: true } ? { uuid: string } : {}) &
|
|
206
211
|
(TDef['traits'] extends { useTimestamps: true } ? { created_at: string; updated_at: string | null } : {}) &
|
|
207
212
|
(TDef['traits'] extends { timestampable: true | object } ? { created_at: string; updated_at: string | null } : {}) &
|
|
@@ -213,7 +218,7 @@ declare type SystemFields<TDef extends ModelDefinition> = { id: number } &
|
|
|
213
218
|
declare type ModelAttributes<TDef extends ModelDefinition> = InferModelAttributes<TDef> & SystemFields<TDef>;
|
|
214
219
|
// All valid column names
|
|
215
220
|
declare type ColumnName<TDef extends ModelDefinition> = | AttributeKeys<TDef>
|
|
216
|
-
| 'id'
|
|
221
|
+
| (TDef extends { primaryKey: infer PK extends string } ? PK : 'id')
|
|
217
222
|
| (TDef['traits'] extends { useUuid: true } ? 'uuid' : never)
|
|
218
223
|
| (TDef['traits'] extends { useTimestamps: true } ? 'created_at' | 'updated_at' : never)
|
|
219
224
|
| (TDef['traits'] extends { timestampable: true | object } ? 'created_at' | 'updated_at' : never)
|
|
@@ -233,31 +238,26 @@ declare type FillableKeys<TDef extends ModelDefinition> = {
|
|
|
233
238
|
declare type NumericColumns<TDef extends ModelDefinition> = {
|
|
234
239
|
[K in AttributeKeys<TDef>]: TDef['attributes'][K] extends { type: 'number' } ? K : never
|
|
235
240
|
}[AttributeKeys<TDef>];
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
?
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
declare type
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
? K extends string ? K : never : never);
|
|
257
|
-
declare type InferHasManyThroughNames<TDef> = (TDef extends { hasManyThrough: readonly (infer R)[] }
|
|
258
|
-
? R extends string ? Lowercase<R> : R extends { model: infer M extends string } ? Lowercase<M> : never : never)
|
|
259
|
-
| (TDef extends { hasManyThrough: Readonly<Record<infer K, unknown>> }
|
|
260
|
-
? K extends string ? K : never : never);
|
|
241
|
+
/**
|
|
242
|
+
* Relation names of one relation declaration. Array form lowercases the
|
|
243
|
+
* (unwrapped) model name; record form uses the keys. The array case MUST be
|
|
244
|
+
* checked first: a tuple also structurally matches `Readonly<Record<...>>`
|
|
245
|
+
* and would otherwise leak its own keys ('length', indices, ...) into the
|
|
246
|
+
* relation-name union.
|
|
247
|
+
*/
|
|
248
|
+
declare type RelationKeyOf<V> = V extends readonly (infer E)[]
|
|
249
|
+
? E extends string ? Lowercase<E>
|
|
250
|
+
: E extends { model: infer M extends string } ? Lowercase<M>
|
|
251
|
+
: never
|
|
252
|
+
: V extends Readonly<Record<infer K, unknown>>
|
|
253
|
+
? K & string
|
|
254
|
+
: never;
|
|
255
|
+
declare type InferBelongsToNames<TDef> = TDef extends { belongsTo: infer V } ? RelationKeyOf<V> : never;
|
|
256
|
+
declare type InferHasManyNames<TDef> = TDef extends { hasMany: infer V } ? RelationKeyOf<V> : never;
|
|
257
|
+
declare type InferHasOneNames<TDef> = TDef extends { hasOne: infer V } ? RelationKeyOf<V> : never;
|
|
258
|
+
declare type InferBelongsToManyNames<TDef> = TDef extends { belongsToMany: infer V } ? RelationKeyOf<V> : never;
|
|
259
|
+
declare type InferHasOneThroughNames<TDef> = TDef extends { hasOneThrough: infer V } ? RelationKeyOf<V> : never;
|
|
260
|
+
declare type InferHasManyThroughNames<TDef> = TDef extends { hasManyThrough: infer V } ? RelationKeyOf<V> : never;
|
|
261
261
|
export type InferRelationNames<TDef> = | InferBelongsToNames<TDef>
|
|
262
262
|
| InferHasManyNames<TDef>
|
|
263
263
|
| InferHasOneNames<TDef>
|
package/dist/src/index.js
CHANGED
|
@@ -14728,17 +14728,15 @@ function createQueryBuilder(state) {
|
|
|
14728
14728
|
addWhereText("WHERE", `${String(col)} IS ${onlyTrashed ? "NOT " : ""}NULL`);
|
|
14729
14729
|
}
|
|
14730
14730
|
}
|
|
14731
|
+
const cacheKey = useCache ? `${String(finalQuery)}\x00${JSON.stringify(whereParams)}` : "";
|
|
14731
14732
|
if (useCache) {
|
|
14732
|
-
const cacheKey = String(finalQuery);
|
|
14733
14733
|
const cached = queryCache.get(cacheKey);
|
|
14734
14734
|
if (cached)
|
|
14735
14735
|
return cached;
|
|
14736
14736
|
}
|
|
14737
14737
|
const result = await runWithHooks(finalQuery, "select", { signal: abortSignal, timeoutMs });
|
|
14738
|
-
if (useCache)
|
|
14739
|
-
const cacheKey = String(finalQuery);
|
|
14738
|
+
if (useCache)
|
|
14740
14739
|
queryCache.set(cacheKey, result, cacheTtl);
|
|
14741
|
-
}
|
|
14742
14740
|
return hydratePivotRows(result);
|
|
14743
14741
|
},
|
|
14744
14742
|
async executeTakeFirst() {
|
|
@@ -23803,6 +23801,13 @@ function assertValidIdentifier(name, context) {
|
|
|
23803
23801
|
if (!SAFE_SQL_IDENTIFIER.test(name))
|
|
23804
23802
|
throw new TypeError(`[bun-query-builder] ${context}: identifier '${name}' contains characters outside [A-Za-z0-9_] \u2014 refusing to interpolate into SQL`);
|
|
23805
23803
|
}
|
|
23804
|
+
function assertValidOrderByColumn(name, context) {
|
|
23805
|
+
if (typeof name !== "string" || name.length === 0)
|
|
23806
|
+
throw new TypeError(`[bun-query-builder] ${context}: identifier must be a non-empty string, got ${typeof name}`);
|
|
23807
|
+
const parts = name.split(".");
|
|
23808
|
+
if (parts.length > 2 || parts.some((p2) => p2.length === 0 || p2.length > 64 || !SAFE_SQL_IDENTIFIER.test(p2)))
|
|
23809
|
+
throw new TypeError(`[bun-query-builder] ${context}: invalid ORDER BY column '${name}' \u2014 expected 'column' or 'table.column' of [A-Za-z0-9_] \u2014 refusing to interpolate into SQL`);
|
|
23810
|
+
}
|
|
23806
23811
|
function getModelFromRegistry(name) {
|
|
23807
23812
|
if (!_getModel) {
|
|
23808
23813
|
try {
|
|
@@ -24091,12 +24096,16 @@ class ModelInstance {
|
|
|
24091
24096
|
for (const [key, value] of Object.entries(data)) {
|
|
24092
24097
|
const attr = attrs[key];
|
|
24093
24098
|
if (attr?.fillable && !attr?.guarded) {
|
|
24099
|
+
if (this._original === null)
|
|
24100
|
+
this._original = { ...this._attributes };
|
|
24094
24101
|
this._attributes[key] = value;
|
|
24095
24102
|
}
|
|
24096
24103
|
}
|
|
24097
24104
|
return this;
|
|
24098
24105
|
}
|
|
24099
24106
|
forceFill(data) {
|
|
24107
|
+
if (this._original === null)
|
|
24108
|
+
this._original = { ...this._attributes };
|
|
24100
24109
|
Object.assign(this._attributes, data);
|
|
24101
24110
|
return this;
|
|
24102
24111
|
}
|
|
@@ -24492,7 +24501,7 @@ class BelongsToManyRelationBuilder {
|
|
|
24492
24501
|
return this;
|
|
24493
24502
|
}
|
|
24494
24503
|
orderBy(column, direction = "asc") {
|
|
24495
|
-
|
|
24504
|
+
assertValidOrderByColumn(column, "orderBy(column)");
|
|
24496
24505
|
if (direction !== "asc" && direction !== "desc")
|
|
24497
24506
|
throw new TypeError(`[bun-query-builder] orderBy(direction): expected 'asc' or 'desc', got '${direction}'`);
|
|
24498
24507
|
this._orderBy.push(`${column} ${direction.toUpperCase()}`);
|
|
@@ -24833,7 +24842,7 @@ class ModelQueryBuilder {
|
|
|
24833
24842
|
return this;
|
|
24834
24843
|
}
|
|
24835
24844
|
orderBy(column, direction = "asc") {
|
|
24836
|
-
|
|
24845
|
+
assertValidOrderByColumn(column, "orderBy(column)");
|
|
24837
24846
|
if (direction !== "asc" && direction !== "desc")
|
|
24838
24847
|
throw new TypeError(`[bun-query-builder] orderBy(direction): expected 'asc' or 'desc', got '${direction}'`);
|
|
24839
24848
|
this._orderBy.push({ column, direction });
|
package/dist/type-inference.d.ts
CHANGED
|
@@ -302,112 +302,42 @@ export type InferPivotColumns<TModel, R extends string> = ResolveDefinition<TMod
|
|
|
302
302
|
: Record<string, unknown>
|
|
303
303
|
: Record<string, unknown>
|
|
304
304
|
: Record<string, unknown>;
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
declare type
|
|
313
|
-
?
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
declare type
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
declare type
|
|
325
|
-
? R extends string ? Lowercase<R> : R extends { model: infer M extends string } ? Lowercase<M> : never : never)
|
|
326
|
-
| (TDef extends { hasOneThrough: Readonly<Record<infer K, unknown>> }
|
|
327
|
-
? K extends string ? K : never : never);
|
|
328
|
-
declare type InferHasManyThroughNames<TDef> = (TDef extends { hasManyThrough: readonly (infer R)[] }
|
|
329
|
-
? R extends string ? Lowercase<R> : R extends { model: infer M extends string } ? Lowercase<M> : never : never)
|
|
330
|
-
| (TDef extends { hasManyThrough: Readonly<Record<infer K, unknown>> }
|
|
331
|
-
? K extends string ? K : never : never);
|
|
305
|
+
/**
|
|
306
|
+
* Relation names of one relation declaration. Array form lowercases the
|
|
307
|
+
* (unwrapped) model name; record form uses the keys. The array case MUST be
|
|
308
|
+
* checked first: a tuple also structurally matches `Readonly<Record<...>>`
|
|
309
|
+
* and would otherwise leak its own keys ('length', indices, ...) into the
|
|
310
|
+
* relation-name union.
|
|
311
|
+
*/
|
|
312
|
+
declare type RelationKeyOf<V> = V extends readonly (infer E)[]
|
|
313
|
+
? E extends string ? Lowercase<E>
|
|
314
|
+
: E extends { model: infer M extends string } ? Lowercase<M>
|
|
315
|
+
: never
|
|
316
|
+
: V extends Readonly<Record<infer K, unknown>>
|
|
317
|
+
? K & string
|
|
318
|
+
: never;
|
|
319
|
+
declare type InferBelongsToNames<TDef> = TDef extends { belongsTo: infer V } ? RelationKeyOf<V> : never;
|
|
320
|
+
declare type InferHasManyNames<TDef> = TDef extends { hasMany: infer V } ? RelationKeyOf<V> : never;
|
|
321
|
+
declare type InferHasOneNames<TDef> = TDef extends { hasOne: infer V } ? RelationKeyOf<V> : never;
|
|
322
|
+
declare type InferBelongsToManyNames<TDef> = TDef extends { belongsToMany: infer V } ? RelationKeyOf<V> : never;
|
|
323
|
+
declare type InferHasOneThroughNames<TDef> = TDef extends { hasOneThrough: infer V } ? RelationKeyOf<V> : never;
|
|
324
|
+
declare type InferHasManyThroughNames<TDef> = TDef extends { hasManyThrough: infer V } ? RelationKeyOf<V> : never;
|
|
332
325
|
/**
|
|
333
326
|
* Determine the cardinality of a relation on a model.
|
|
334
|
-
* hasMany
|
|
327
|
+
* hasMany / belongsToMany / hasManyThrough / morphMany / morphToMany /
|
|
328
|
+
* morphedByMany → 'many'; hasOne / belongsTo / hasOneThrough / morphOne →
|
|
329
|
+
* 'one'. Both array and record declaration forms are supported via
|
|
330
|
+
* `RelationKeyOf` (array-first, so tuple keys never leak in).
|
|
335
331
|
*/
|
|
336
332
|
export type RelationCardinality<TModel, R extends string> = ResolveDefinition<TModel> extends infer TDef
|
|
337
|
-
?
|
|
338
|
-
(TDef extends {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
| (TDef extends {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
| (TDef extends {
|
|
347
|
-
? Lowercase<M & string> extends R ? 'one' : never
|
|
348
|
-
: never)
|
|
349
|
-
// hasOne object syntax
|
|
350
|
-
| (TDef extends { hasOne: Readonly<Record<infer K, unknown>> }
|
|
351
|
-
? K extends string ? K extends R ? 'one' : never : never
|
|
352
|
-
: never)
|
|
353
|
-
// belongsTo array syntax
|
|
354
|
-
| (TDef extends { belongsTo: readonly (infer M)[] }
|
|
355
|
-
? Lowercase<M & string> extends R ? 'one' : never
|
|
356
|
-
: never)
|
|
357
|
-
// belongsTo object syntax
|
|
358
|
-
| (TDef extends { belongsTo: Readonly<Record<infer K, unknown>> }
|
|
359
|
-
? K extends string ? K extends R ? 'one' : never : never
|
|
360
|
-
: never)
|
|
361
|
-
// belongsToMany array syntax
|
|
362
|
-
| (TDef extends { belongsToMany: readonly (infer M)[] }
|
|
363
|
-
? M extends string
|
|
364
|
-
? Lowercase<M> extends R ? 'many' : never
|
|
365
|
-
: M extends { model: infer N extends string }
|
|
366
|
-
? Lowercase<N> extends R ? 'many' : never
|
|
367
|
-
: never
|
|
368
|
-
: never)
|
|
369
|
-
// belongsToMany object syntax
|
|
370
|
-
| (TDef extends { belongsToMany: Readonly<Record<infer K, unknown>> }
|
|
371
|
-
? K extends string ? K extends R ? 'many' : never : never
|
|
372
|
-
: never)
|
|
373
|
-
// hasOneThrough array syntax ({ model } entries)
|
|
374
|
-
| (TDef extends { hasOneThrough: readonly (infer M)[] }
|
|
375
|
-
? M extends string
|
|
376
|
-
? Lowercase<M> extends R ? 'one' : never
|
|
377
|
-
: M extends { model: infer N extends string }
|
|
378
|
-
? Lowercase<N> extends R ? 'one' : never
|
|
379
|
-
: never
|
|
380
|
-
: never)
|
|
381
|
-
// hasOneThrough object syntax
|
|
382
|
-
| (TDef extends { hasOneThrough: Readonly<Record<infer K, unknown>> }
|
|
383
|
-
? K extends string ? K extends R ? 'one' : never : never
|
|
384
|
-
: never)
|
|
385
|
-
// hasManyThrough array syntax ({ model } entries)
|
|
386
|
-
| (TDef extends { hasManyThrough: readonly (infer M)[] }
|
|
387
|
-
? M extends string
|
|
388
|
-
? Lowercase<M> extends R ? 'many' : never
|
|
389
|
-
: M extends { model: infer N extends string }
|
|
390
|
-
? Lowercase<N> extends R ? 'many' : never
|
|
391
|
-
: never
|
|
392
|
-
: never)
|
|
393
|
-
// hasManyThrough object syntax
|
|
394
|
-
| (TDef extends { hasManyThrough: Readonly<Record<infer K, unknown>> }
|
|
395
|
-
? K extends string ? K extends R ? 'many' : never : never
|
|
396
|
-
: never)
|
|
397
|
-
// morphOne object syntax
|
|
398
|
-
| (TDef extends { morphOne: Readonly<Record<infer K, unknown>> }
|
|
399
|
-
? K extends string ? K extends R ? 'one' : never : never
|
|
400
|
-
: never)
|
|
401
|
-
// morphMany object syntax
|
|
402
|
-
| (TDef extends { morphMany: Readonly<Record<infer K, unknown>> }
|
|
403
|
-
? K extends string ? K extends R ? 'many' : never : never
|
|
404
|
-
: never)
|
|
405
|
-
// morphToMany object syntax
|
|
406
|
-
| (TDef extends { morphToMany: Readonly<Record<infer K, unknown>> }
|
|
407
|
-
? K extends string ? K extends R ? 'many' : never : never
|
|
408
|
-
: never)
|
|
409
|
-
// morphedByMany object syntax
|
|
410
|
-
| (TDef extends { morphedByMany: Readonly<Record<infer K, unknown>> }
|
|
411
|
-
? K extends string ? K extends R ? 'many' : never : never
|
|
412
|
-
: never)
|
|
333
|
+
? (TDef extends { hasMany: infer V } ? (R extends RelationKeyOf<V> ? 'many' : never) : never)
|
|
334
|
+
| (TDef extends { hasOne: infer V } ? (R extends RelationKeyOf<V> ? 'one' : never) : never)
|
|
335
|
+
| (TDef extends { belongsTo: infer V } ? (R extends RelationKeyOf<V> ? 'one' : never) : never)
|
|
336
|
+
| (TDef extends { belongsToMany: infer V } ? (R extends RelationKeyOf<V> ? 'many' : never) : never)
|
|
337
|
+
| (TDef extends { hasOneThrough: infer V } ? (R extends RelationKeyOf<V> ? 'one' : never) : never)
|
|
338
|
+
| (TDef extends { hasManyThrough: infer V } ? (R extends RelationKeyOf<V> ? 'many' : never) : never)
|
|
339
|
+
| (TDef extends { morphOne: infer V } ? (R extends RelationKeyOf<V> ? 'one' : never) : never)
|
|
340
|
+
| (TDef extends { morphMany: infer V } ? (R extends RelationKeyOf<V> ? 'many' : never) : never)
|
|
341
|
+
| (TDef extends { morphToMany: infer V } ? (R extends RelationKeyOf<V> ? 'many' : never) : never)
|
|
342
|
+
| (TDef extends { morphedByMany: infer V } ? (R extends RelationKeyOf<V> ? 'many' : never) : never)
|
|
413
343
|
: never;
|
package/package.json
CHANGED