objection 4.0.0-rc.2 → 4.0.0-rc.3
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/lib/queryBuilder/graph/GraphLoader.js +201 -126
- package/lib/queryBuilder/graph/GraphNode.js +10 -3
- package/lib/queryBuilder/graph/GraphOptions.js +24 -49
- package/lib/queryBuilder/graph/GraphPlan.js +92 -108
- package/lib/queryBuilder/graph/GraphSchedule.js +27 -18
- package/lib/queryBuilder/graph/GraphUpsert.js +46 -548
- package/lib/queryBuilder/graph/GraphWriter.js +257 -14
- package/lib/queryBuilder/graph/graphChecks.js +497 -0
- package/lib/queryBuilder/graph/graphKeys.js +109 -404
- package/package.json +2 -2
- package/typings/objection/index.d.ts +437 -85
|
@@ -18,7 +18,8 @@ import { Knex } from 'knex';
|
|
|
18
18
|
// Only the declarations marked with `export` are exported.
|
|
19
19
|
export {};
|
|
20
20
|
|
|
21
|
-
// Phantom brand of the relation types, used by `TypedRelationMappings
|
|
21
|
+
// Phantom brand of the relation types, used by `TypedRelationMappings` and
|
|
22
|
+
// `FromModel`.
|
|
22
23
|
declare const relationKind: unique symbol;
|
|
23
24
|
// Phantom brand of `Generated` properties.
|
|
24
25
|
declare const generated: unique symbol;
|
|
@@ -197,7 +198,7 @@ export interface CallbackVoid<T> {
|
|
|
197
198
|
}
|
|
198
199
|
|
|
199
200
|
export type Identity<T> = (value: T) => T;
|
|
200
|
-
export type AnyQueryBuilder = QueryBuilder<any, any>;
|
|
201
|
+
export type AnyQueryBuilder = QueryBuilder<any, any, any>;
|
|
201
202
|
export type AnyModelConstructor = ModelConstructor<Model>;
|
|
202
203
|
export type ModifierFunction<QB extends AnyQueryBuilder> = (qb: QB, ...args: any[]) => void;
|
|
203
204
|
export type Modifier<QB extends AnyQueryBuilder = AnyQueryBuilder> =
|
|
@@ -398,7 +399,7 @@ export type WithGraphTreeQueryBuilder<QB extends AnyQueryBuilder, T> = [keyof T]
|
|
|
398
399
|
? QB
|
|
399
400
|
: WithResultKind<
|
|
400
401
|
QB,
|
|
401
|
-
WithGraph<ModelType<QB>, T>['QueryBuilderType'],
|
|
402
|
+
KeepExtra<WithGraph<ModelType<QB>, T>['QueryBuilderType'], ExtraType<QB>>,
|
|
402
403
|
ModelType<QB>,
|
|
403
404
|
ResultType<QB>,
|
|
404
405
|
T
|
|
@@ -477,8 +478,9 @@ export type NonFunctionPropertyNames<T> = {
|
|
|
477
478
|
[K in keyof T]: T[K] extends Function ? never : K;
|
|
478
479
|
}[keyof T];
|
|
479
480
|
|
|
480
|
-
// The type-only members of models, which aren't data
|
|
481
|
-
|
|
481
|
+
// The type-only members of models, which aren't data, also the keys of the
|
|
482
|
+
// virtual attributes that `FromModel` adds.
|
|
483
|
+
type ModelTypeMembers = 'QueryBuilderType' | 'ColumnNameMapping' | `~virtual:${string}`;
|
|
482
484
|
|
|
483
485
|
/**
|
|
484
486
|
* Type that attempts to only select the user-defined model properties.
|
|
@@ -501,15 +503,24 @@ export type ModelObject<T extends Model> = Pick<T, DataPropertyNames<T>>;
|
|
|
501
503
|
|
|
502
504
|
/**
|
|
503
505
|
* The JSON of model M, as `toJSON()` returns it: its properties without
|
|
504
|
-
* methods,
|
|
505
|
-
*
|
|
506
|
+
* methods, the results of the methods in `virtualAttributes` on models with
|
|
507
|
+
* `FromModel`, and the related models as JSON too. Values aren't converted,
|
|
508
|
+
* e.g. dates stay dates.
|
|
506
509
|
*/
|
|
507
510
|
export type ModelJson<M> = {
|
|
508
|
-
[
|
|
511
|
+
[
|
|
512
|
+
K in keyof Pick<M, (DataPropertyNames<M> | VirtualAttributeNames<M>) & keyof M>
|
|
513
|
+
]: K extends RelationPropertyNames<M>
|
|
509
514
|
? RelationJson<M[K]>
|
|
510
|
-
: M[K]
|
|
515
|
+
: M[K] extends (...args: any) => infer R
|
|
516
|
+
? RelationJson<R>
|
|
517
|
+
: M[K];
|
|
511
518
|
};
|
|
512
519
|
|
|
520
|
+
type VirtualAttributeNames<M> = {
|
|
521
|
+
[K in keyof M]: K extends `~virtual:${infer N}` ? N : never;
|
|
522
|
+
}[keyof M];
|
|
523
|
+
|
|
513
524
|
type RelationJson<P> = P extends (infer I)[]
|
|
514
525
|
? ModelJson<I>[]
|
|
515
526
|
: P extends readonly (infer I)[]
|
|
@@ -728,16 +739,34 @@ export type ModelType<T extends { ModelType: any }> = T['ModelType'];
|
|
|
728
739
|
export type ResultType<T extends { ResultType: any }> = T['ResultType'];
|
|
729
740
|
|
|
730
741
|
/**
|
|
731
|
-
* Re-instantiates the query builder QB with the model type M
|
|
732
|
-
* type R, through its `RebindType`. The `~rebind` slot is
|
|
733
|
-
* intersection resolves it to exactly `[M, R]`.
|
|
734
|
-
* `RebindType` instead of QB keeps the intersection small,
|
|
735
|
-
* checks much faster.
|
|
742
|
+
* Re-instantiates the query builder QB with the model type M, the result
|
|
743
|
+
* type R and the extra type X, through its `RebindType`. The `~rebind` slot is
|
|
744
|
+
* `unknown`, so the intersection resolves it to exactly `[M, R, X]`.
|
|
745
|
+
* Rebinding QB's own `RebindType` instead of QB keeps the intersection small,
|
|
746
|
+
* which TypeScript checks much faster.
|
|
736
747
|
*/
|
|
737
|
-
type Rebind<
|
|
738
|
-
|
|
748
|
+
type Rebind<
|
|
749
|
+
QB extends AnyQueryBuilder,
|
|
750
|
+
M extends Model,
|
|
751
|
+
R,
|
|
752
|
+
X = IfStrict<unknown, ExtraType<QB>>,
|
|
753
|
+
> = (QB['RebindType'] & {
|
|
754
|
+
'~rebind': [M, R, X];
|
|
739
755
|
})['RebindType'];
|
|
740
756
|
|
|
757
|
+
/**
|
|
758
|
+
* Gets the extra type from a query builder type: what the types know about
|
|
759
|
+
* the query beyond its model and result, see `QueryExtra`.
|
|
760
|
+
*/
|
|
761
|
+
export type ExtraType<T extends { ExtraType: any }> = T['ExtraType'];
|
|
762
|
+
|
|
763
|
+
type WithExtra<QB extends AnyQueryBuilder, X> = Rebind<QB, ModelType<QB>, ResultType<QB>, X>;
|
|
764
|
+
|
|
765
|
+
// The narrowed query builders of `withGraph*()` start without the extra type
|
|
766
|
+
// of QB, so it is passed on, if there is one.
|
|
767
|
+
type KeepExtra<NQB extends AnyQueryBuilder, X> =
|
|
768
|
+
X extends QueryExtra<any, any, any> ? WithExtra<NQB, X> : NQB;
|
|
769
|
+
|
|
741
770
|
/**
|
|
742
771
|
* Gets the single item query builder type for a query builder.
|
|
743
772
|
*/
|
|
@@ -763,18 +792,18 @@ export type NumberQueryBuilder<QB extends AnyQueryBuilder> = QB['~number'];
|
|
|
763
792
|
*/
|
|
764
793
|
export type PageQueryBuilder<QB extends AnyQueryBuilder> = QB['~page'];
|
|
765
794
|
|
|
766
|
-
// Strict mode
|
|
767
|
-
//
|
|
795
|
+
// Strict mode checks the column names and values of queries against the
|
|
796
|
+
// models. Augment `TypeConfig` to opt in:
|
|
768
797
|
//
|
|
769
798
|
// declare module 'objection' {
|
|
770
799
|
// interface TypeConfig {
|
|
771
|
-
// strict:
|
|
800
|
+
// strict: true;
|
|
772
801
|
// }
|
|
773
802
|
// }
|
|
774
803
|
|
|
775
804
|
export interface TypeConfig {}
|
|
776
805
|
|
|
777
|
-
type IsStrict = TypeConfig extends { strict:
|
|
806
|
+
type IsStrict = TypeConfig extends { strict: true } ? true : false;
|
|
778
807
|
|
|
779
808
|
// As IsStrict isn't generic, IfStrict resolves eagerly.
|
|
780
809
|
type IfStrict<Loose, Strict> = IsStrict extends true ? Strict : Loose;
|
|
@@ -1159,6 +1188,18 @@ export type SelectedBrand<A> = { readonly [selected]: A };
|
|
|
1159
1188
|
*/
|
|
1160
1189
|
export type ExtractedBrand<A> = { readonly [extracted]: A };
|
|
1161
1190
|
|
|
1191
|
+
/**
|
|
1192
|
+
* The extra type of queries in strict mode: the model class C that started the
|
|
1193
|
+
* query, e.g. with `Person.query()`, and the modifiers P registered with
|
|
1194
|
+
* `modifiers()`, to check the names of modifiers, and the id I of the class,
|
|
1195
|
+
* for `findById()` and the other `*ById()` methods.
|
|
1196
|
+
*/
|
|
1197
|
+
export interface QueryExtra<C = unknown, P = unknown, I = MaybeCompositeId> {
|
|
1198
|
+
modelClass: C;
|
|
1199
|
+
registered: P;
|
|
1200
|
+
id: I;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1162
1203
|
// The results whose rows have `jsonExtract()` values, which `withGraph*()`
|
|
1163
1204
|
// keeps instead of converting the result kind:
|
|
1164
1205
|
type ExtractedRows =
|
|
@@ -1276,17 +1317,222 @@ type UnknownRelations<M, T> = {
|
|
|
1276
1317
|
|
|
1277
1318
|
/**
|
|
1278
1319
|
* In strict mode, relation expressions are intersected with this, to reject
|
|
1279
|
-
* the names of unknown relations
|
|
1320
|
+
* the names of unknown relations, and of unknown modifiers, checked against
|
|
1321
|
+
* the related class of each node and the modifiers registered on query
|
|
1322
|
+
* builder QB.
|
|
1280
1323
|
*/
|
|
1281
|
-
type CheckRelationExpression<M, E> = IfStrict<
|
|
1324
|
+
type CheckRelationExpression<M, E, QB extends AnyQueryBuilder = never> = IfStrict<
|
|
1282
1325
|
unknown,
|
|
1283
1326
|
IsConcreteModel<M> extends true
|
|
1284
1327
|
? [UnknownRelations<M, ParseRelationExpression<E>>] extends [never]
|
|
1285
|
-
?
|
|
1328
|
+
? CheckModifierExpression<E, QB>
|
|
1286
1329
|
: { '~unknownRelation': UnknownRelations<M, ParseRelationExpression<E>> }
|
|
1287
1330
|
: unknown
|
|
1288
1331
|
>;
|
|
1289
1332
|
|
|
1333
|
+
type CheckModifierExpression<E, QB extends AnyQueryBuilder> =
|
|
1334
|
+
HasQueryClass<QB> extends true
|
|
1335
|
+
? [CheckedModifiers<E, QB>] extends [never]
|
|
1336
|
+
? unknown
|
|
1337
|
+
: { '~unknownModifier': CheckedModifiers<E, QB> }
|
|
1338
|
+
: unknown;
|
|
1339
|
+
|
|
1340
|
+
// Queries in generic code, where the model class can't be resolved, aren't
|
|
1341
|
+
// checked.
|
|
1342
|
+
type HasQueryClass<QB extends AnyQueryBuilder> =
|
|
1343
|
+
IsConcreteModel<ModelType<QB>> extends false
|
|
1344
|
+
? false
|
|
1345
|
+
: [QueryClass<QB>] extends [never]
|
|
1346
|
+
? false
|
|
1347
|
+
: true;
|
|
1348
|
+
|
|
1349
|
+
// Only expressions with modifiers are checked for them.
|
|
1350
|
+
type CheckedModifiers<E, QB> = E extends `${string}(${string}` | object
|
|
1351
|
+
? UnknownModifiers<
|
|
1352
|
+
ClassMappings<QueryClass<QB>>,
|
|
1353
|
+
ParseModifierExpression<E>,
|
|
1354
|
+
keyof RegisteredModifiers<QB>
|
|
1355
|
+
>
|
|
1356
|
+
: never;
|
|
1357
|
+
|
|
1358
|
+
/**
|
|
1359
|
+
* The modifiers that a modifier name can refer to on query builder QB: the
|
|
1360
|
+
* `modifiers` of the model class that started the query, and those registered
|
|
1361
|
+
* with `modifiers()` before. Unknown names are only rejected in strict mode,
|
|
1362
|
+
* and only on queries of model classes with literal `modifiers`.
|
|
1363
|
+
*/
|
|
1364
|
+
type KnownModifiers<QB> = ClassModifiers<QueryClass<QB>> & RegisteredModifiers<QB>;
|
|
1365
|
+
|
|
1366
|
+
// The model class that started the query, if any.
|
|
1367
|
+
type QueryClass<QB> = [QB] extends [never]
|
|
1368
|
+
? never
|
|
1369
|
+
: QB extends { ExtraType: QueryExtra<infer C, any, any> }
|
|
1370
|
+
? unknown extends C
|
|
1371
|
+
? never
|
|
1372
|
+
: C
|
|
1373
|
+
: never;
|
|
1374
|
+
|
|
1375
|
+
type ClassModifiers<C> = C extends { modifiers: infer O } ? O : {};
|
|
1376
|
+
|
|
1377
|
+
type ClassMappings<C> = C extends { relationMappings: infer T }
|
|
1378
|
+
? T extends () => infer R
|
|
1379
|
+
? R
|
|
1380
|
+
: T
|
|
1381
|
+
: {};
|
|
1382
|
+
|
|
1383
|
+
type RegisteredModifiers<QB> = [QB] extends [never]
|
|
1384
|
+
? {}
|
|
1385
|
+
: QB extends { ExtraType: { registered: infer P } }
|
|
1386
|
+
? P
|
|
1387
|
+
: {};
|
|
1388
|
+
|
|
1389
|
+
/**
|
|
1390
|
+
* The id that `findById()` and the other `*ById()` methods take on query
|
|
1391
|
+
* builder QB: in strict mode, the type of the property of the class's literal
|
|
1392
|
+
* `idColumn`, or a tuple of them for composite ids, e.g. with
|
|
1393
|
+
* `static idColumn = ['groupId', 'memberId'] as const`.
|
|
1394
|
+
*/
|
|
1395
|
+
type IdArg<QB extends AnyQueryBuilder> = IfStrict<
|
|
1396
|
+
MaybeCompositeId,
|
|
1397
|
+
[QueryClass<QB>] extends [never]
|
|
1398
|
+
? MaybeCompositeId
|
|
1399
|
+
: QB extends { ExtraType: QueryExtra<any, any, infer I> }
|
|
1400
|
+
? I
|
|
1401
|
+
: MaybeCompositeId
|
|
1402
|
+
>;
|
|
1403
|
+
|
|
1404
|
+
// The id of a related class, read from its instances.
|
|
1405
|
+
type ClassId<C> = C extends { idColumn: infer K; prototype: infer M }
|
|
1406
|
+
? ColumnsId<K, M>
|
|
1407
|
+
: MaybeCompositeId;
|
|
1408
|
+
|
|
1409
|
+
// The inherited `idColumn` and other general types give any id.
|
|
1410
|
+
type ColumnsId<K, M> = [K] extends [string]
|
|
1411
|
+
? string extends K
|
|
1412
|
+
? MaybeCompositeId
|
|
1413
|
+
: PropertyId<M, K, MaybeCompositeId>
|
|
1414
|
+
: [K] extends [readonly string[]]
|
|
1415
|
+
? string extends K[number]
|
|
1416
|
+
? MaybeCompositeId
|
|
1417
|
+
: { readonly [I in keyof K]: PropertyId<M, K[I] & string, Id> }
|
|
1418
|
+
: MaybeCompositeId;
|
|
1419
|
+
|
|
1420
|
+
// The id column is a database column, named after the property by the
|
|
1421
|
+
// model's `ColumnNameMapping`. Columns without a property give the fallback F.
|
|
1422
|
+
type PropertyId<M, C extends string, F> =
|
|
1423
|
+
ResultKey<M, C> extends infer P extends keyof M ? NonNullable<M[P]> : F;
|
|
1424
|
+
|
|
1425
|
+
// Modifiers with their general type, e.g. inherited from `Model`, aren't
|
|
1426
|
+
// checked.
|
|
1427
|
+
type ChecksModifiers<QB extends AnyQueryBuilder> = IfStrict<
|
|
1428
|
+
false,
|
|
1429
|
+
HasQueryClass<QB> extends true ? ChecksClassModifiers<ClassModifiers<QueryClass<QB>>> : false
|
|
1430
|
+
>;
|
|
1431
|
+
|
|
1432
|
+
type ChecksClassModifiers<O> = string extends keyof O ? false : true;
|
|
1433
|
+
|
|
1434
|
+
// The names that `modify()` takes on query builder QB, also in lists. Names
|
|
1435
|
+
// in variables typed `string` are rejected where they are checked.
|
|
1436
|
+
type ModifierName<QB extends AnyQueryBuilder> =
|
|
1437
|
+
ChecksModifiers<QB> extends true ? keyof KnownModifiers<QB> & string : string;
|
|
1438
|
+
|
|
1439
|
+
type ModifyArg<QB extends AnyQueryBuilder> =
|
|
1440
|
+
| ModifierName<QB>
|
|
1441
|
+
| ModifierName<QB>[]
|
|
1442
|
+
| ModifierFunction<QB>
|
|
1443
|
+
| Record<string, Expression<PrimitiveValue>>;
|
|
1444
|
+
|
|
1445
|
+
// The related classes are found through the relation mappings, at each step
|
|
1446
|
+
// of the path. P are the names registered with `modifiers()`.
|
|
1447
|
+
type UnknownModifiers<Mappings, T, P> = T extends unknown
|
|
1448
|
+
? {
|
|
1449
|
+
[K in keyof T & string]: T[K] extends { names: infer N; children: infer Children }
|
|
1450
|
+
? MappedClass<Mappings, K> extends infer C
|
|
1451
|
+
? [C] extends [never]
|
|
1452
|
+
? never
|
|
1453
|
+
: | (ChecksClassModifiers<ClassModifiers<C>> extends true
|
|
1454
|
+
? Exclude<N, keyof ClassModifiers<C> | P>
|
|
1455
|
+
: never)
|
|
1456
|
+
| UnknownModifiers<ClassMappings<C>, Children, P>
|
|
1457
|
+
: never
|
|
1458
|
+
: never;
|
|
1459
|
+
}[keyof T & string]
|
|
1460
|
+
: never;
|
|
1461
|
+
|
|
1462
|
+
// Mappings with their general type, e.g. inherited from `Model`, give no class.
|
|
1463
|
+
type MappedClass<Mappings, K> = string extends keyof Mappings
|
|
1464
|
+
? never
|
|
1465
|
+
: K extends keyof Mappings
|
|
1466
|
+
? Mappings[K] extends { modelClass: infer C }
|
|
1467
|
+
? C extends abstract new (...args: any) => any
|
|
1468
|
+
? C
|
|
1469
|
+
: C extends () => infer RC
|
|
1470
|
+
? RC
|
|
1471
|
+
: never
|
|
1472
|
+
: never
|
|
1473
|
+
: never;
|
|
1474
|
+
|
|
1475
|
+
/**
|
|
1476
|
+
* Parses the modifiers of relation expressions into a tree of the relations
|
|
1477
|
+
* with their modifier names: 'pets(a, b).owner' ->
|
|
1478
|
+
* `{ pets: { names: 'a' | 'b', children: { owner: ... } } }`. It is separate
|
|
1479
|
+
* from `ParseRelationExpression`, so that the narrowing types don't carry the
|
|
1480
|
+
* names.
|
|
1481
|
+
*/
|
|
1482
|
+
type ParseModifierExpression<E> = string extends E
|
|
1483
|
+
? {}
|
|
1484
|
+
: E extends string
|
|
1485
|
+
? ParseModifierString<E>
|
|
1486
|
+
: ParseModifierObject<E>;
|
|
1487
|
+
|
|
1488
|
+
// A union of the trees of the list items, as they can name the same relation.
|
|
1489
|
+
type ParseModifierList<L extends string[], Acc = never> = L extends [
|
|
1490
|
+
infer H extends string,
|
|
1491
|
+
...infer T extends string[],
|
|
1492
|
+
]
|
|
1493
|
+
? ParseModifierList<T, Acc | ParseModifierString<H>>
|
|
1494
|
+
: Acc;
|
|
1495
|
+
|
|
1496
|
+
type ParseModifierString<S extends string> =
|
|
1497
|
+
Trim<S> extends `[${infer Inner}]`
|
|
1498
|
+
? ParseModifierList<SplitList<Inner>>
|
|
1499
|
+
: Trim<S> extends `${infer Head}.${infer Rest}`
|
|
1500
|
+
? IsBalanced<Head> extends true
|
|
1501
|
+
? ModifierNode<Head, ParseModifierString<Rest>>
|
|
1502
|
+
: {}
|
|
1503
|
+
: ModifierNode<S, {}>;
|
|
1504
|
+
|
|
1505
|
+
type ModifierNode<S extends string, Children> = [RelationName<S>] extends [never]
|
|
1506
|
+
? {}
|
|
1507
|
+
: { [K in RelationName<S>]: { names: ModifierNames<S>; children: Children } };
|
|
1508
|
+
|
|
1509
|
+
// Empty arguments, e.g. of 'pets()' or a trailing comma, are no names.
|
|
1510
|
+
type ModifierNames<S extends string> =
|
|
1511
|
+
Trim<S> extends `${string}(${infer Args})` ? Exclude<Trim<SplitList<Args>[number]>, ''> : never;
|
|
1512
|
+
|
|
1513
|
+
type ParseModifierObject<E> = string extends keyof E
|
|
1514
|
+
? {}
|
|
1515
|
+
: {
|
|
1516
|
+
[
|
|
1517
|
+
K in keyof E as K extends `$${string}`
|
|
1518
|
+
? never
|
|
1519
|
+
: false extends E[K]
|
|
1520
|
+
? never
|
|
1521
|
+
: E[K] extends { $relation: any }
|
|
1522
|
+
? never
|
|
1523
|
+
: K
|
|
1524
|
+
]: {
|
|
1525
|
+
names: E[K] extends { $modify: infer N }
|
|
1526
|
+
? N extends readonly (infer I extends string)[]
|
|
1527
|
+
? I
|
|
1528
|
+
: N extends string
|
|
1529
|
+
? N
|
|
1530
|
+
: never
|
|
1531
|
+
: never;
|
|
1532
|
+
children: E[K] extends object ? ParseModifierObject<E[K]> : {};
|
|
1533
|
+
};
|
|
1534
|
+
};
|
|
1535
|
+
|
|
1290
1536
|
export interface ForClassMethod {
|
|
1291
1537
|
<M extends Model>(modelClass: ModelConstructor<M>): QueryBuilderType<M>;
|
|
1292
1538
|
}
|
|
@@ -1664,7 +1910,7 @@ export interface JoinRelatedOptions {
|
|
|
1664
1910
|
|
|
1665
1911
|
export interface JoinRelatedMethod<out QB extends AnyQueryBuilder> {
|
|
1666
1912
|
<QBP extends QB, const E extends RelationExpression<ModelType<QBP>> = never>(
|
|
1667
|
-
expr: E & CheckRelationExpression<ModelType<QBP>, E>,
|
|
1913
|
+
expr: E & CheckRelationExpression<ModelType<QBP>, E, QBP>,
|
|
1668
1914
|
opt?: JoinRelatedOptions,
|
|
1669
1915
|
): QB;
|
|
1670
1916
|
}
|
|
@@ -2033,11 +2279,24 @@ export interface ClearContextMethod<out QB extends AnyQueryBuilder> {
|
|
|
2033
2279
|
}
|
|
2034
2280
|
|
|
2035
2281
|
export interface ModifyMethod<out QB extends AnyQueryBuilder> {
|
|
2036
|
-
(modifier:
|
|
2282
|
+
(modifier: ModifyArg<QB> | ModifyArg<QB>[], ...args: any[]): QB;
|
|
2037
2283
|
}
|
|
2038
2284
|
|
|
2039
|
-
|
|
2040
|
-
|
|
2285
|
+
// Registered modifiers add up, on queries with and without a model class.
|
|
2286
|
+
type RegisterModifiers<X, O> =
|
|
2287
|
+
X extends QueryExtra<infer C, infer P, infer I>
|
|
2288
|
+
? QueryExtra<C, P & O, I>
|
|
2289
|
+
: QueryExtra<unknown, O>;
|
|
2290
|
+
|
|
2291
|
+
export interface ModifiersMethod<
|
|
2292
|
+
out QB extends AnyQueryBuilder,
|
|
2293
|
+
M extends Model = ModelType<QB>,
|
|
2294
|
+
R = ResultType<QB>,
|
|
2295
|
+
X = ExtraType<QB>,
|
|
2296
|
+
> {
|
|
2297
|
+
<const O extends Modifiers>(
|
|
2298
|
+
modifiers: O,
|
|
2299
|
+
): IfStrict<QB, Rebind<QB, M, R, RegisterModifiers<X, O>>>;
|
|
2041
2300
|
(): QB;
|
|
2042
2301
|
}
|
|
2043
2302
|
|
|
@@ -2051,7 +2310,11 @@ export interface CatchablePromiseLike<R> extends PromiseLike<R> {
|
|
|
2051
2310
|
): Promise<R | FR>;
|
|
2052
2311
|
}
|
|
2053
2312
|
|
|
2054
|
-
export class QueryBuilder<
|
|
2313
|
+
export class QueryBuilder<
|
|
2314
|
+
M extends Model,
|
|
2315
|
+
R = M[],
|
|
2316
|
+
X = unknown,
|
|
2317
|
+
> implements CatchablePromiseLike<R> {
|
|
2055
2318
|
static forClass: ForClassMethod;
|
|
2056
2319
|
|
|
2057
2320
|
constructor(modelClass: ModelConstructor<M>);
|
|
@@ -2240,35 +2503,35 @@ export class QueryBuilder<M extends Model, R = M[]> implements CatchablePromiseL
|
|
|
2240
2503
|
groupBy: GroupByMethod<this>;
|
|
2241
2504
|
groupByRaw: RawInterface<this>;
|
|
2242
2505
|
|
|
2243
|
-
findById(id:
|
|
2244
|
-
findByIds(ids:
|
|
2506
|
+
findById(id: IdArg<this>): MaybeSingleQueryBuilder<this>;
|
|
2507
|
+
findByIds(ids: IdArg<this>[]): this;
|
|
2245
2508
|
findOne: WhereMethod<MaybeSingleQueryBuilder<this>>;
|
|
2246
2509
|
|
|
2247
2510
|
execute(): Promise<R>;
|
|
2248
2511
|
castTo<MC extends Model>(modelClass: ModelConstructor<MC>): QueryBuilderType<MC>;
|
|
2249
|
-
castTo<R>(): QueryBuilder<M, R>;
|
|
2512
|
+
castTo<R>(): QueryBuilder<M, R, X>;
|
|
2250
2513
|
|
|
2251
2514
|
update(update: PartialModelRow<M>): NumberQueryBuilder<this>;
|
|
2252
2515
|
update(): NumberQueryBuilder<this>;
|
|
2253
2516
|
updateById(
|
|
2254
|
-
id:
|
|
2517
|
+
id: IdArg<this>,
|
|
2255
2518
|
update: PartialModelRow<M>,
|
|
2256
2519
|
): NumberQueryBuilder<MaybeSingleQueryBuilder<this>>;
|
|
2257
2520
|
updateAndFetch(update: PartialModelRow<M>): SingleQueryBuilder<this>;
|
|
2258
|
-
updateAndFetchById(id:
|
|
2521
|
+
updateAndFetchById(id: IdArg<this>, update: PartialModelRow<M>): SingleQueryBuilder<this>;
|
|
2259
2522
|
|
|
2260
2523
|
patch(update: PartialModelPatch<M>): NumberQueryBuilder<this>;
|
|
2261
2524
|
patch(): NumberQueryBuilder<this>;
|
|
2262
2525
|
patchById(
|
|
2263
|
-
id:
|
|
2526
|
+
id: IdArg<this>,
|
|
2264
2527
|
update: PartialModelPatch<M>,
|
|
2265
2528
|
): NumberQueryBuilder<MaybeSingleQueryBuilder<this>>;
|
|
2266
2529
|
patchAndFetch(update: PartialModelPatch<M>): SingleQueryBuilder<this>;
|
|
2267
|
-
patchAndFetchById(id:
|
|
2530
|
+
patchAndFetchById(id: IdArg<this>, update: PartialModelPatch<M>): SingleQueryBuilder<this>;
|
|
2268
2531
|
|
|
2269
2532
|
del(): NumberQueryBuilder<this>;
|
|
2270
2533
|
delete(): NumberQueryBuilder<this>;
|
|
2271
|
-
deleteById(id:
|
|
2534
|
+
deleteById(id: IdArg<this>): NumberQueryBuilder<MaybeSingleQueryBuilder<this>>;
|
|
2272
2535
|
|
|
2273
2536
|
insert(insert: PartialModelRow<M>): SingleQueryBuilder<this>;
|
|
2274
2537
|
insert(insert: PartialModelRow<M>[]): ArrayQueryBuilder<this>;
|
|
@@ -2292,15 +2555,15 @@ export class QueryBuilder<M extends Model, R = M[]> implements CatchablePromiseL
|
|
|
2292
2555
|
// With literal relation expressions, the fetched relations become required
|
|
2293
2556
|
// on the result type, see WithGraphQueryBuilder.
|
|
2294
2557
|
withGraphFetched<const E extends RelationExpression<M>>(
|
|
2295
|
-
expr: E & CheckRelationExpression<M, E>,
|
|
2558
|
+
expr: E & CheckRelationExpression<M, E, this>,
|
|
2296
2559
|
options?: GraphOptions,
|
|
2297
2560
|
): WithGraphQueryBuilder<this, E>;
|
|
2298
2561
|
withGraphJoined<const E extends RelationExpression<M>>(
|
|
2299
|
-
expr: E & CheckRelationExpression<M, E>,
|
|
2562
|
+
expr: E & CheckRelationExpression<M, E, this>,
|
|
2300
2563
|
options?: GraphOptions,
|
|
2301
2564
|
): WithGraphQueryBuilder<this, E>;
|
|
2302
2565
|
withGraph<const E extends RelationExpression<M>>(
|
|
2303
|
-
expr: E & CheckRelationExpression<M, E>,
|
|
2566
|
+
expr: E & CheckRelationExpression<M, E, this>,
|
|
2304
2567
|
options?: WithGraphOptions,
|
|
2305
2568
|
): WithGraphQueryBuilder<this, E>;
|
|
2306
2569
|
|
|
@@ -2378,7 +2641,7 @@ export class QueryBuilder<M extends Model, R = M[]> implements CatchablePromiseL
|
|
|
2378
2641
|
clearContext: ClearContextMethod<this>;
|
|
2379
2642
|
|
|
2380
2643
|
modify: ModifyMethod<this>;
|
|
2381
|
-
modifiers: ModifiersMethod<this>;
|
|
2644
|
+
modifiers: ModifiersMethod<this, M, R, X>;
|
|
2382
2645
|
|
|
2383
2646
|
isFind: BooleanReturningMethod;
|
|
2384
2647
|
isExecutable: BooleanReturningMethod;
|
|
@@ -2404,27 +2667,29 @@ export class QueryBuilder<M extends Model, R = M[]> implements CatchablePromiseL
|
|
|
2404
2667
|
|
|
2405
2668
|
ModelType: M;
|
|
2406
2669
|
ResultType: R;
|
|
2670
|
+
ExtraType: X;
|
|
2407
2671
|
|
|
2408
|
-
// The model and
|
|
2409
|
-
// are `any` where `this` isn't rebound, e.g. when TypeScript
|
|
2410
|
-
// members of a custom query builder against this class.
|
|
2672
|
+
// The model, result and extra types that `RebindType` is instantiated
|
|
2673
|
+
// with. They are `any` where `this` isn't rebound, e.g. when TypeScript
|
|
2674
|
+
// checks the members of a custom query builder against this class.
|
|
2411
2675
|
'~rebind': unknown;
|
|
2412
|
-
'~M': this['~rebind'] extends [any, any] ? this['~rebind'][0] : any;
|
|
2413
|
-
'~R': this['~rebind'] extends [any, any] ? this['~rebind'][1] : any;
|
|
2676
|
+
'~M': this['~rebind'] extends [any, any, any] ? this['~rebind'][0] : any;
|
|
2677
|
+
'~R': this['~rebind'] extends [any, any, any] ? this['~rebind'][1] : any;
|
|
2678
|
+
'~X': this['~rebind'] extends [any, any, any] ? this['~rebind'][2] : any;
|
|
2414
2679
|
|
|
2415
2680
|
/**
|
|
2416
|
-
* This query builder, re-instantiated with other model and
|
|
2417
|
-
* e.g. by `first()` or `page()`. Custom query builders redeclare it
|
|
2418
|
-
* their own type:
|
|
2681
|
+
* This query builder, re-instantiated with other model, result and extra
|
|
2682
|
+
* types, e.g. by `first()` or `page()`. Custom query builders redeclare it
|
|
2683
|
+
* to keep their own type:
|
|
2419
2684
|
*
|
|
2420
|
-
* declare RebindType: MyQueryBuilder<this['~M'], this['~R']>;
|
|
2685
|
+
* declare RebindType: MyQueryBuilder<this['~M'], this['~R'], this['~X']>;
|
|
2421
2686
|
*/
|
|
2422
|
-
RebindType: QueryBuilder<this['~M'], this['~R']>;
|
|
2687
|
+
RebindType: QueryBuilder<this['~M'], this['~R'], this['~X']>;
|
|
2423
2688
|
|
|
2424
2689
|
// The query builder rebound to the result kinds of the helper types, e.g.
|
|
2425
2690
|
// `SingleQueryBuilder`. As members, they also resolve where `this` is
|
|
2426
2691
|
// generic, e.g. in the methods of custom query builders. Of the members
|
|
2427
|
-
// starting with `~`, only `~M` and `~
|
|
2692
|
+
// starting with `~`, only `~M`, `~R` and `~X` are API, for `RebindType`.
|
|
2428
2693
|
'~single': Rebind<this, M, ResultItem<R, M>>;
|
|
2429
2694
|
'~maybeSingle': Rebind<this, M, ResultItem<R, M> | undefined>;
|
|
2430
2695
|
'~array': Rebind<this, M, ResultItem<R, M>[]>;
|
|
@@ -2808,7 +3073,7 @@ export interface ModelClass<M extends Model> extends ModelConstructor<M> {
|
|
|
2808
3073
|
relationMappings: RelationMappings | RelationMappingsThunk;
|
|
2809
3074
|
modelPaths: string[];
|
|
2810
3075
|
jsonAttributes: string[] | readonly string[];
|
|
2811
|
-
virtualAttributes: string[];
|
|
3076
|
+
virtualAttributes: readonly string[];
|
|
2812
3077
|
uidProp: string;
|
|
2813
3078
|
uidRefProp: string;
|
|
2814
3079
|
dbRefProp: string;
|
|
@@ -2921,7 +3186,7 @@ export class Model {
|
|
|
2921
3186
|
static relationMappings: RelationMappings | RelationMappingsThunk;
|
|
2922
3187
|
static modelPaths: string[];
|
|
2923
3188
|
static jsonAttributes: string[] | readonly string[];
|
|
2924
|
-
static virtualAttributes: string[];
|
|
3189
|
+
static virtualAttributes: readonly string[];
|
|
2925
3190
|
static uidProp: string;
|
|
2926
3191
|
static uidRefProp: string;
|
|
2927
3192
|
static dbRefProp: string;
|
|
@@ -2949,16 +3214,28 @@ export class Model {
|
|
|
2949
3214
|
|
|
2950
3215
|
static defaultGraphOptions?: GraphOptions;
|
|
2951
3216
|
|
|
2952
|
-
|
|
2953
|
-
|
|
3217
|
+
// The id column K is inferred separately from the class C, so that it
|
|
3218
|
+
// resolves through the constraint of a generic class, e.g. in static helpers
|
|
3219
|
+
// with `this: T`.
|
|
3220
|
+
static query<M extends Model, C = unknown, K = unknown>(
|
|
3221
|
+
this: ConstructorType<M> & IfStrict<unknown, C & { idColumn?: K }>,
|
|
2954
3222
|
trxOrKnex?: TransactionOrKnex,
|
|
2955
|
-
):
|
|
3223
|
+
): IfStrict<
|
|
3224
|
+
QueryBuilderType<M>,
|
|
3225
|
+
WithExtra<QueryBuilderType<M>, QueryExtra<C, {}, ColumnsId<K, M>>>
|
|
3226
|
+
>;
|
|
2956
3227
|
|
|
2957
|
-
static relatedQuery<M extends Model, K extends keyof M>(
|
|
2958
|
-
this: ConstructorType<M>,
|
|
3228
|
+
static relatedQuery<M extends Model, K extends keyof M, C = unknown>(
|
|
3229
|
+
this: ConstructorType<M> & IfStrict<unknown, C>,
|
|
2959
3230
|
relationName: K,
|
|
2960
3231
|
trxOrKnex?: TransactionOrKnex,
|
|
2961
|
-
):
|
|
3232
|
+
): IfStrict<
|
|
3233
|
+
ArrayRelatedQueryBuilder<M[K]>,
|
|
3234
|
+
WithExtra<
|
|
3235
|
+
ArrayRelatedQueryBuilder<M[K]>,
|
|
3236
|
+
QueryExtra<MappedClass<ClassMappings<C>, K>, {}, ClassId<MappedClass<ClassMappings<C>, K>>>
|
|
3237
|
+
>
|
|
3238
|
+
>;
|
|
2962
3239
|
|
|
2963
3240
|
static relatedQuery<RM extends Model>(
|
|
2964
3241
|
relationName: string,
|
|
@@ -3215,32 +3492,26 @@ export interface initialize {
|
|
|
3215
3492
|
|
|
3216
3493
|
/**
|
|
3217
3494
|
* The type of the values that a JSON schema declared with `as const`
|
|
3218
|
-
* describes, e.g.
|
|
3495
|
+
* describes, e.g. of JSON columns, or of models that subclasses extend, whose
|
|
3496
|
+
* `jsonSchema` has the general type for `FromModel`:
|
|
3219
3497
|
*
|
|
3220
|
-
*
|
|
3221
|
-
* static jsonSchema = {
|
|
3222
|
-
* type: 'object',
|
|
3223
|
-
* required: ['firstName'],
|
|
3224
|
-
* properties: {
|
|
3225
|
-
* id: { type: 'integer' },
|
|
3226
|
-
* firstName: { type: 'string' },
|
|
3227
|
-
* age: { type: ['integer', 'null'] },
|
|
3228
|
-
* },
|
|
3229
|
-
* } as const;
|
|
3498
|
+
* const entrySchema = { type: 'object', properties: { ... } } as const;
|
|
3230
3499
|
*
|
|
3231
|
-
*
|
|
3500
|
+
* class Entry extends Model {
|
|
3501
|
+
* static jsonSchema: ReadonlyJSONSchema = entrySchema;
|
|
3232
3502
|
* }
|
|
3233
3503
|
*
|
|
3234
|
-
* interface
|
|
3504
|
+
* interface Entry extends FromJSONSchema<typeof entrySchema>, FromModel<typeof Entry> {}
|
|
3235
3505
|
*
|
|
3236
3506
|
* Supports `type` (also as an array), `required`, `nullable`, `enum`,
|
|
3237
3507
|
* `const`, `items` (also as a tuple), nested `properties`, `anyOf` and
|
|
3238
|
-
* `oneOf`. Formats like 'date-time' stay strings, as in JSON
|
|
3239
|
-
*
|
|
3240
|
-
*
|
|
3241
|
-
* don't change
|
|
3508
|
+
* `oneOf`. Formats like 'date-time' stay strings, as in JSON, see the
|
|
3509
|
+
* timestamps recipe for the dates that drivers return. Properties that aren't
|
|
3510
|
+
* required are optional. Next to `type` or `properties`, `anyOf` and `oneOf`
|
|
3511
|
+
* only add constraints, e.g. alternative `required` lists, and don't change
|
|
3512
|
+
* the type.
|
|
3242
3513
|
*/
|
|
3243
|
-
export type
|
|
3514
|
+
export type FromJSONSchema<S> = S extends boolean
|
|
3244
3515
|
? unknown
|
|
3245
3516
|
: S extends { const: infer C }
|
|
3246
3517
|
? Extract<C, SchemaType<S>>
|
|
@@ -3251,7 +3522,7 @@ export type FromSchema<S> = S extends boolean
|
|
|
3251
3522
|
: S extends { properties: object }
|
|
3252
3523
|
? SchemaObject<S>
|
|
3253
3524
|
: S extends { anyOf: readonly (infer A)[] } | { oneOf: readonly (infer A)[] }
|
|
3254
|
-
?
|
|
3525
|
+
? FromJSONSchema<A> | SchemaNullable<S>
|
|
3255
3526
|
: unknown;
|
|
3256
3527
|
|
|
3257
3528
|
// The type that `type` allows, which `enum` and `const` values are narrowed
|
|
@@ -3280,7 +3551,7 @@ type SchemaTypeName<N, S> = N extends 'string'
|
|
|
3280
3551
|
type SchemaArray<S> = S extends { items: infer I }
|
|
3281
3552
|
? I extends readonly unknown[]
|
|
3282
3553
|
? SchemaTuple<I, S>
|
|
3283
|
-
:
|
|
3554
|
+
: FromJSONSchema<I>[]
|
|
3284
3555
|
: unknown[];
|
|
3285
3556
|
|
|
3286
3557
|
// Tuple `items` only check the items that are present: they are required
|
|
@@ -3288,12 +3559,12 @@ type SchemaArray<S> = S extends { items: infer I }
|
|
|
3288
3559
|
// `additionalItems` restricts them.
|
|
3289
3560
|
type SchemaTuple<I extends readonly unknown[], S> = [
|
|
3290
3561
|
...(S extends { minItems: I['length'] }
|
|
3291
|
-
? { -readonly [K in keyof I]:
|
|
3292
|
-
: { -readonly [K in keyof I]?:
|
|
3562
|
+
? { -readonly [K in keyof I]: FromJSONSchema<I[K]> }
|
|
3563
|
+
: { -readonly [K in keyof I]?: FromJSONSchema<I[K]> }),
|
|
3293
3564
|
...(S extends { additionalItems: false }
|
|
3294
3565
|
? []
|
|
3295
3566
|
: S extends { additionalItems: infer A }
|
|
3296
|
-
?
|
|
3567
|
+
? FromJSONSchema<A>[]
|
|
3297
3568
|
: unknown[]),
|
|
3298
3569
|
];
|
|
3299
3570
|
|
|
@@ -3305,16 +3576,97 @@ type SchemaObject<S> = S extends { properties: infer P }
|
|
|
3305
3576
|
|
|
3306
3577
|
// The intersection is flattened into one object type for readable hovers.
|
|
3307
3578
|
type SchemaProperties<P, R> = {
|
|
3308
|
-
-readonly [K in keyof P as K extends R ? K : never]:
|
|
3579
|
+
-readonly [K in keyof P as K extends R ? K : never]: FromJSONSchema<P[K]>;
|
|
3309
3580
|
} & {
|
|
3310
|
-
-readonly [K in keyof P as K extends R ? never : K]?:
|
|
3581
|
+
-readonly [K in keyof P as K extends R ? never : K]?: FromJSONSchema<P[K]>;
|
|
3311
3582
|
} extends infer O
|
|
3312
3583
|
? { [K in keyof O]: O[K] }
|
|
3313
3584
|
: never;
|
|
3314
3585
|
|
|
3586
|
+
/**
|
|
3587
|
+
* The properties of a model class, derived from its `jsonSchema` declared
|
|
3588
|
+
* `as const` and its `relationMappings`:
|
|
3589
|
+
*
|
|
3590
|
+
* class Person extends Model {
|
|
3591
|
+
* static jsonSchema = { ... } as const;
|
|
3592
|
+
*
|
|
3593
|
+
* static relationMappings = () => ({
|
|
3594
|
+
* parent: {
|
|
3595
|
+
* relation: Model.BelongsToOneRelation,
|
|
3596
|
+
* modelClass: Person,
|
|
3597
|
+
* join: { from: 'persons.parentId', to: 'persons.id' },
|
|
3598
|
+
* },
|
|
3599
|
+
* });
|
|
3600
|
+
* }
|
|
3601
|
+
*
|
|
3602
|
+
* interface Person extends FromModel<typeof Person> {}
|
|
3603
|
+
*
|
|
3604
|
+
* The properties are typed as with `FromJSONSchema`. Relations are optional, as
|
|
3605
|
+
* they are only present when fetched: to-one relations are typed `M | null`,
|
|
3606
|
+
* as `withGraphFetched()` sets missing ones to `null`, and to-many relations
|
|
3607
|
+
* `M[]`. Relations with a module path as `modelClass`, and mappings declared
|
|
3608
|
+
* as `RelationMapping` instead of inferred, are left out, as are a schema and
|
|
3609
|
+
* mappings with their general types, e.g. inherited from `Model`. The names of
|
|
3610
|
+
* `virtualAttributes` declared `as const` are kept for `ModelJson`.
|
|
3611
|
+
*/
|
|
3612
|
+
export type FromModel<C extends { jsonSchema: unknown; relationMappings: unknown }> =
|
|
3613
|
+
ModelSchemaProperties<C['jsonSchema']> &
|
|
3614
|
+
ModelRelationProperties<C['relationMappings']> &
|
|
3615
|
+
VirtualAttributeKeys<C>;
|
|
3616
|
+
|
|
3617
|
+
// One key per name, so that subclasses that add virtual attributes have the
|
|
3618
|
+
// same keys as their parent for the inherited ones.
|
|
3619
|
+
type VirtualAttributeKeys<C> = C extends { virtualAttributes: infer V extends readonly string[] }
|
|
3620
|
+
? string extends V[number]
|
|
3621
|
+
? {}
|
|
3622
|
+
: { readonly [K in V[number] as `~virtual:${K}`]?: true }
|
|
3623
|
+
: {};
|
|
3624
|
+
|
|
3625
|
+
type ModelSchemaProperties<S> = ReadonlyJSONSchema extends S
|
|
3626
|
+
? {}
|
|
3627
|
+
: FromJSONSchema<S> extends infer P extends object
|
|
3628
|
+
? P
|
|
3629
|
+
: {};
|
|
3630
|
+
|
|
3631
|
+
// Relations are picked by their mappings, as resolving the related models
|
|
3632
|
+
// while the model's own type is built would make it its own base type.
|
|
3633
|
+
type ModelRelationProperties<T, R = T extends () => infer M ? M : T> = string extends keyof R
|
|
3634
|
+
? {}
|
|
3635
|
+
: {
|
|
3636
|
+
-readonly [K in keyof R as IsMappedRelation<R[K]> extends true ? K : never]?: MappedRelation<
|
|
3637
|
+
R[K]
|
|
3638
|
+
>;
|
|
3639
|
+
};
|
|
3640
|
+
|
|
3641
|
+
// Relation types without a brand and module paths can't be resolved.
|
|
3642
|
+
type IsMappedRelation<M> = M extends { relation: infer T; modelClass: infer C }
|
|
3643
|
+
? [MappedKind<T>] extends [never]
|
|
3644
|
+
? false
|
|
3645
|
+
: C extends string
|
|
3646
|
+
? false
|
|
3647
|
+
: true
|
|
3648
|
+
: false;
|
|
3649
|
+
|
|
3650
|
+
// The related model is inferred from the constructor without checking it
|
|
3651
|
+
// against `Model`, as that check would circle back through the relations of
|
|
3652
|
+
// self-referencing models.
|
|
3653
|
+
type MappedRelation<M> = M extends { relation: infer T; modelClass: infer C }
|
|
3654
|
+
? MappedKind<T> extends 'HasMany' | 'ManyToMany' | 'BelongsToMany'
|
|
3655
|
+
? MappedModel<C>[]
|
|
3656
|
+
: MappedModel<C> | null
|
|
3657
|
+
: never;
|
|
3658
|
+
|
|
3659
|
+
type MappedKind<T> = T extends { readonly [relationKind]?: infer K } ? K : never;
|
|
3660
|
+
|
|
3661
|
+
type MappedModel<C> = C extends abstract new (...args: any) => infer I
|
|
3662
|
+
? I
|
|
3663
|
+
: C extends () => abstract new (...args: any) => infer I
|
|
3664
|
+
? I
|
|
3665
|
+
: never;
|
|
3666
|
+
|
|
3315
3667
|
/**
|
|
3316
3668
|
* A JSON schema with readonly arrays, the type of `static jsonSchema`, so that
|
|
3317
|
-
* it takes schemas declared `as const`, for `
|
|
3669
|
+
* it takes schemas declared `as const`, for `FromJSONSchema`. A `JSONSchema` is
|
|
3318
3670
|
* assignable to it.
|
|
3319
3671
|
*/
|
|
3320
3672
|
export type ReadonlyJSONSchema = ReadonlyDeep<JSONSchema>;
|