edinburgh 0.6.1 → 0.6.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/src/models.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as lowlevel from "olmdb/lowlevel";
2
2
  import { DatabaseError } from "olmdb/lowlevel";
3
3
  import DataPack from "./datapack.js";
4
- import { deserializeType, serializeType, TypeWrapper, identifier } from "./types.js";
4
+ import { deserializeType, serializeType, TypeWrapper, identifier, type FieldQueryArg, type FieldValue, type StripQueryArg } from "./types.js";
5
5
  import { transact, currentTxn, type Transaction } from "./edinburgh.js";
6
6
 
7
7
  import { PrimaryKey, NonPrimaryIndex, IndexRangeIterator, UniqueIndex, SecondaryIndex, FindOptions, VersionInfo } from "./indexes.js";
@@ -49,7 +49,7 @@ export interface FieldConfig<T> {
49
49
  * });
50
50
  * ```
51
51
  */
52
- export function field<T>(type: TypeWrapper<T>, options: Partial<FieldConfig<T>> = {}): T {
52
+ export function field<TYPE extends TypeWrapper<any>>(type: TYPE, options: Partial<FieldConfig<FieldValue<TYPE>>> = {}): FieldValue<TYPE> {
53
53
  // Return the config object, but TypeScript sees it as type T
54
54
  options.type = type;
55
55
  return options as any;
@@ -66,28 +66,54 @@ export type Change = Record<any, any> | "created" | "deleted";
66
66
 
67
67
  type FieldsOf<T> = T extends new () => infer I ? I : never;
68
68
 
69
- type PKArgs<FIELDS, PK> =
70
- PK extends readonly (keyof FIELDS & string)[]
71
- ? { [I in keyof PK]: PK[I] extends keyof FIELDS ? FIELDS[PK[I]] : never }
72
- : PK extends keyof FIELDS & string
73
- ? [FIELDS[PK]]
69
+ type PublicFields<FIELDS> = {
70
+ [K in keyof FIELDS]: StripQueryArg<FIELDS[K]>;
71
+ };
72
+
73
+ type QueryFields<FIELDS> = {
74
+ [K in keyof FIELDS]: FieldQueryArg<FIELDS[K]>;
75
+ };
76
+
77
+ type PublicModelOf<T extends new () => any> = Model<PublicFields<FieldsOf<T>>>;
78
+
79
+ type IndexSpec<T extends new () => any> =
80
+ | (keyof FieldsOf<T> & string)
81
+ | readonly (keyof FieldsOf<T> & string)[]
82
+ | ((instance: PublicModelOf<T>) => any);
83
+
84
+ type PKArgs<QUERY_FIELDS, PK> =
85
+ PK extends readonly (keyof QUERY_FIELDS & string)[]
86
+ ? { [I in keyof PK]: PK[I] extends keyof QUERY_FIELDS ? QUERY_FIELDS[PK[I]] : never }
87
+ : PK extends keyof QUERY_FIELDS & string
88
+ ? [QUERY_FIELDS[PK]]
74
89
  : [string];
75
90
 
76
- type IndexArgs<FIELDS, SPEC> =
77
- SPEC extends readonly (keyof FIELDS & string)[]
78
- ? { [I in keyof SPEC]: SPEC[I] extends keyof FIELDS ? FIELDS[SPEC[I]] : never }
79
- : SPEC extends keyof FIELDS & string
80
- ? [FIELDS[SPEC]]
91
+ type IndexArgs<QUERY_FIELDS, SPEC> =
92
+ SPEC extends readonly (keyof QUERY_FIELDS & string)[]
93
+ ? { [I in keyof SPEC]: SPEC[I] extends keyof QUERY_FIELDS ? QUERY_FIELDS[SPEC[I]] : never }
94
+ : SPEC extends keyof QUERY_FIELDS & string
95
+ ? [QUERY_FIELDS[SPEC]]
81
96
  : SPEC extends (instance: any) => infer R
82
97
  ? R extends (infer V)[] ? [V] : [R]
83
98
  : never;
84
99
 
100
+ type PublicIndexSpec<SPEC> =
101
+ SPEC extends (instance: infer INSTANCE) => infer R
102
+ ? (instance: INSTANCE) => R
103
+ : SPEC;
104
+
105
+ type PublicIndexSpecs<SPECS> = {
106
+ [K in keyof SPECS]: PublicIndexSpec<SPECS[K]>;
107
+ };
108
+
85
109
  /**
86
110
  * A model constructor with its generic information erased.
87
111
  *
88
112
  * Useful when accepting or storing arbitrary registered model classes.
89
113
  */
90
- export type AnyModelClass = ModelClass<new () => any, readonly any[], any, any>;
114
+ export type AnyModelClass = ModelClass<object, any, any, readonly any[], any, any>;
115
+
116
+ type StaticMembers<T extends new () => any> = Pick<T, Exclude<keyof T, 'prototype'>>;
91
117
 
92
118
  type SecondaryRegistry<FIELDS> = Record<string, NonPrimaryIndex<Model<FIELDS>, readonly (keyof FIELDS & string)[], readonly any[]>>;
93
119
 
@@ -107,15 +133,15 @@ export const pendingModelInits = new Set<AnyModelClass>();
107
133
 
108
134
  // These static members are attached dynamically in defineModel(), so 'declare' tells TypeScript
109
135
  // they exist at runtime without emitting duplicate class fields that would shadow those assignments.
110
- class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX = {}> extends PrimaryKey<Model<FIELDS>, readonly (keyof FIELDS & string)[], PKA> {
136
+ class ModelClassRuntime<PUBLIC_FIELDS, QUERY_FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX = {}> extends PrimaryKey<Model<PUBLIC_FIELDS>, readonly (keyof PUBLIC_FIELDS & string)[], PKA> {
111
137
  // Runtime table identifier used for index naming and diagnostics.
112
138
  declare tableName: string;
113
139
  // Field schema map used for validation and serialization.
114
140
  declare fields: Record<string | symbol | number, FieldConfig<unknown>>;
115
141
  // Registered unique/secondary indexes for this model.
116
- declare _secondaries?: SecondaryRegistry<FIELDS>;
142
+ declare _secondaries?: SecondaryRegistry<PUBLIC_FIELDS>;
117
143
  // Cached list of non-primary fields used for value serialization.
118
- _nonKeyFields!: (keyof FIELDS & string)[];
144
+ _nonKeyFields!: (keyof PUBLIC_FIELDS & string)[];
119
145
  // Lazy getter/setter descriptors installed on unloaded non-key fields.
120
146
  _lazyDescriptors: Record<string | symbol | number, PropertyDescriptor> = {};
121
147
  // Writable descriptors temporarily installed before hydrating value fields.
@@ -160,13 +186,13 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
160
186
  this._lazyDescriptors[fieldName] = {
161
187
  configurable: true,
162
188
  enumerable: true,
163
- get(this: Model<FIELDS>) {
189
+ get(this: Model<PUBLIC_FIELDS>) {
164
190
  this.constructor._lazyLoad(this);
165
- return this[fieldName];
191
+ return (this as any)[fieldName];
166
192
  },
167
- set(this: Model<FIELDS>, value: any) {
193
+ set(this: Model<PUBLIC_FIELDS>, value: any) {
168
194
  this.constructor._lazyLoad(this);
169
- this[fieldName] = value;
195
+ (this as any)[fieldName] = value;
170
196
  },
171
197
  };
172
198
  this._resetDescriptors[fieldName] = {
@@ -200,20 +226,20 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
200
226
  return index;
201
227
  }
202
228
 
203
- _get(txn: Transaction, args: PKA | Uint8Array, loadNow: false | Uint8Array): Model<FIELDS>;
204
- _get(txn: Transaction, args: PKA | Uint8Array, loadNow: true): Model<FIELDS> | undefined;
205
- _get(txn: Transaction, args: PKA | Uint8Array, loadNow: boolean | Uint8Array): Model<FIELDS> | undefined {
229
+ _get(txn: Transaction, args: PKA | Uint8Array, loadNow: false | Uint8Array): Model<PUBLIC_FIELDS>;
230
+ _get(txn: Transaction, args: PKA | Uint8Array, loadNow: true): Model<PUBLIC_FIELDS> | undefined;
231
+ _get(txn: Transaction, args: PKA | Uint8Array, loadNow: boolean | Uint8Array): Model<PUBLIC_FIELDS> | undefined {
206
232
  let key: Uint8Array;
207
233
  let keyParts: readonly any[] | undefined;
208
234
  if (args instanceof Uint8Array) {
209
235
  key = args;
210
236
  } else {
211
237
  key = this._argsToKeyBytes(args, false).toUint8Array();
212
- keyParts = args;
238
+ keyParts = this._pkToArray(key);
213
239
  }
214
240
 
215
241
  const keyHash = hashBytes(key);
216
- const cached = txn.instances.get(keyHash) as Model<FIELDS> | undefined;
242
+ const cached = txn.instances.get(keyHash) as Model<PUBLIC_FIELDS> | undefined;
217
243
  if (cached) {
218
244
  if (loadNow && loadNow !== true) {
219
245
  Object.defineProperties(cached, this._resetDescriptors);
@@ -232,7 +258,7 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
232
258
  }
233
259
  }
234
260
 
235
- const model = Object.create((this as any).prototype) as Model<FIELDS>;
261
+ const model = Object.create((this as any).prototype) as Model<PUBLIC_FIELDS>;
236
262
  model._txn = txn;
237
263
  model._oldValues = {};
238
264
  txn.instances.set(keyHash, model);
@@ -259,7 +285,7 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
259
285
  return model;
260
286
  }
261
287
 
262
- _lazyLoad(model: Model<FIELDS>) {
288
+ _lazyLoad(model: Model<PUBLIC_FIELDS>) {
263
289
  const key = model._primaryKey!;
264
290
  const valueBuffer = dbGet(model._txn.id, key);
265
291
  if (!valueBuffer) throw new DatabaseError(`Lazy-loaded ${this.tableName}#${key} does not exist`, 'LAZY_FAIL');
@@ -269,23 +295,29 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
269
295
 
270
296
  /**
271
297
  * Load a model by primary key inside the current transaction.
298
+ *
299
+ * For `link(...)` primary-key fields, each argument may be the linked model
300
+ * instance or the linked model's primary key. Composite linked primary keys
301
+ * are passed as a tuple in that argument slot.
272
302
  *
273
303
  * @returns The matching model, or `undefined` if no row exists.
274
304
  */
275
- get(...args: PKA): Model<FIELDS> | undefined {
305
+ get(...args: PKA): Model<PUBLIC_FIELDS> | undefined {
276
306
  return this._get(currentTxn(), args, true);
277
307
  }
278
308
 
279
309
  /**
280
310
  * Load a model by primary key without fetching its non-key fields immediately.
311
+ *
312
+ * Link-valued primary-key fields accept the same shorthand as `get()`.
281
313
  *
282
314
  * Accessing a lazy field later will load the remaining fields transparently.
283
315
  */
284
- getLazy(...args: PKA): Model<FIELDS> {
316
+ getLazy(...args: PKA): Model<PUBLIC_FIELDS> {
285
317
  return this._get(currentTxn(), args, false);
286
318
  }
287
319
 
288
- _pairToInstance(txn: Transaction, keyBuffer: ArrayBuffer, valueBuffer: ArrayBuffer): Model<FIELDS> {
320
+ _pairToInstance(txn: Transaction, keyBuffer: ArrayBuffer, valueBuffer: ArrayBuffer): Model<PUBLIC_FIELDS> {
289
321
  return this._get(txn, new Uint8Array(keyBuffer), new Uint8Array(valueBuffer))!;
290
322
  }
291
323
 
@@ -297,7 +329,7 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
297
329
  * @param obj Partial model data that **must** include every primary key field.
298
330
  * @returns The loaded-and-updated or newly created instance.
299
331
  */
300
- replaceInto(obj: Partial<FIELDS>): Model<FIELDS> {
332
+ replaceInto(obj: Partial<PUBLIC_FIELDS>): Model<PUBLIC_FIELDS> {
301
333
  const keyArgs: any[] = [];
302
334
  for (const fieldName of this._indexFields.keys()) {
303
335
  if (!(fieldName in (obj as any))) {
@@ -305,7 +337,7 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
305
337
  }
306
338
  keyArgs.push((obj as any)[fieldName]);
307
339
  }
308
- const existing = this.get(...keyArgs as any) as Model<FIELDS> | undefined;
340
+ const existing = this.get(...keyArgs as any) as Model<PUBLIC_FIELDS> | undefined;
309
341
  if (existing) {
310
342
  for (const key in obj as any) {
311
343
  if (!this._indexFields.has(key as any)) {
@@ -321,10 +353,12 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
321
353
  * Look up a model through a named unique index.
322
354
  *
323
355
  * @param name The name from the model's `unique` definition.
324
- * @param args The unique-index key values.
356
+ * @param args The unique-index key values. For `link(...)` fields, pass
357
+ * either the linked model instance or the linked model's primary key. If the
358
+ * linked model uses a composite primary key, pass the full tuple in that slot.
325
359
  * @returns The matching model instance, if any.
326
360
  */
327
- getBy<K extends string & keyof UNIQUE>(name: K, ...args: IndexArgs<FIELDS, UNIQUE[K]>): Model<FIELDS> | undefined {
361
+ getBy<K extends string & keyof UNIQUE>(name: K, ...args: IndexArgs<QUERY_FIELDS, UNIQUE[K]>): Model<PUBLIC_FIELDS> | undefined {
328
362
  return (this._getSecondary(name) as any).getPK(...args);
329
363
  }
330
364
 
@@ -332,11 +366,12 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
332
366
  * Query rows through a named unique or secondary index.
333
367
  *
334
368
  * This mirrors `find()`, but targets a named entry from the model's `unique`
335
- * or `index` registration.
369
+ * or `index` registration. Link-valued index fields accept either the linked
370
+ * model instance or the linked model's primary key tuple/value.
336
371
  */
337
- findBy<K extends string & keyof (UNIQUE & INDEX)>(name: K, opts: FindOptions<IndexArgs<FIELDS, (UNIQUE & INDEX)[K]>, 'first'>): Model<FIELDS> | undefined;
338
- findBy<K extends string & keyof (UNIQUE & INDEX)>(name: K, opts: FindOptions<IndexArgs<FIELDS, (UNIQUE & INDEX)[K]>, 'single'>): Model<FIELDS>;
339
- findBy<K extends string & keyof (UNIQUE & INDEX)>(name: K, opts?: FindOptions<IndexArgs<FIELDS, (UNIQUE & INDEX)[K]>>): IndexRangeIterator<Model<FIELDS>>;
372
+ findBy<K extends string & keyof (UNIQUE & INDEX)>(name: K, opts: FindOptions<IndexArgs<QUERY_FIELDS, (UNIQUE & INDEX)[K]>, 'first'>): Model<PUBLIC_FIELDS> | undefined;
373
+ findBy<K extends string & keyof (UNIQUE & INDEX)>(name: K, opts: FindOptions<IndexArgs<QUERY_FIELDS, (UNIQUE & INDEX)[K]>, 'single'>): Model<PUBLIC_FIELDS>;
374
+ findBy<K extends string & keyof (UNIQUE & INDEX)>(name: K, opts?: FindOptions<IndexArgs<QUERY_FIELDS, (UNIQUE & INDEX)[K]>>): IndexRangeIterator<Model<PUBLIC_FIELDS>>;
340
375
  findBy(name: string, opts?: any): any {
341
376
  return this._getSecondary(name).find(opts);
342
377
  }
@@ -348,13 +383,13 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
348
383
  */
349
384
  batchProcessBy<K extends string & keyof (UNIQUE & INDEX)>(
350
385
  name: K,
351
- opts: FindOptions<IndexArgs<FIELDS, (UNIQUE & INDEX)[K]>> & { limitSeconds?: number; limitRows?: number },
352
- callback: (row: Model<FIELDS>) => any,
386
+ opts: FindOptions<IndexArgs<QUERY_FIELDS, (UNIQUE & INDEX)[K]>> & { limitSeconds?: number; limitRows?: number },
387
+ callback: (row: Model<PUBLIC_FIELDS>) => any,
353
388
  ): Promise<void> {
354
389
  return this._getSecondary(name).batchProcess(opts, callback as any);
355
390
  }
356
391
 
357
- _loadValueFields(model: Model<FIELDS>, valueArray: Uint8Array) {
392
+ _loadValueFields(model: Model<PUBLIC_FIELDS>, valueArray: Uint8Array) {
358
393
  const valuePack = new DataPack(valueArray);
359
394
  const version = valuePack.readNumber();
360
395
 
@@ -390,7 +425,7 @@ class ModelClassRuntime<FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX =
390
425
  return info;
391
426
  }
392
427
 
393
- _migrateValueFields(model: Model<FIELDS>, version: number, valuePack: DataPack) {
428
+ _migrateValueFields(model: Model<PUBLIC_FIELDS>, version: number, valuePack: DataPack) {
394
429
  const versionInfo = this._loadVersionInfo(model._txn.id, version);
395
430
  const record: Record<string, any> = {};
396
431
  for (const [name] of this._indexFields.entries()) record[name] = (model as any)[name];
@@ -443,11 +478,11 @@ export const ModelClass = ModelClassRuntime;
443
478
  * @template UNIQUE - Named unique-index specifications.
444
479
  * @template INDEX - Named secondary-index specifications.
445
480
  */
446
- export type ModelClass<T extends new () => any, PKA extends readonly any[], UNIQUE = {}, INDEX = {}> =
447
- T
448
- & ModelClassRuntime<FieldsOf<T>, PKA, UNIQUE, INDEX>
481
+ export type ModelClass<STATICS, PUBLIC_FIELDS, QUERY_FIELDS, PKA extends readonly any[], UNIQUE = {}, INDEX = {}> =
482
+ STATICS
483
+ & ModelClassRuntime<PUBLIC_FIELDS, QUERY_FIELDS, PKA, UNIQUE, INDEX>
449
484
  & {
450
- new (initial?: Partial<FieldsOf<T>>, txn?: Transaction): Model<FieldsOf<T>>;
485
+ new (initial?: Partial<PUBLIC_FIELDS>, txn?: Transaction): Model<PUBLIC_FIELDS>;
451
486
  };
452
487
 
453
488
  /**
@@ -475,13 +510,20 @@ export interface ModelBase {
475
510
  export function defineModel<
476
511
  T extends new () => any,
477
512
  const PK extends (keyof FieldsOf<T> & string) | readonly (keyof FieldsOf<T> & string)[],
478
- const UNIQUE extends Record<string, (keyof FieldsOf<T> & string) | readonly (keyof FieldsOf<T> & string)[] | ((instance: any) => any)>,
479
- const INDEX extends Record<string, (keyof FieldsOf<T> & string) | readonly (keyof FieldsOf<T> & string)[] | ((instance: any) => any)>,
513
+ const UNIQUE extends Record<string, IndexSpec<T>>,
514
+ const INDEX extends Record<string, IndexSpec<T>>,
480
515
  >(
481
516
  tableName: string,
482
517
  cls: T,
483
518
  opts?: { pk?: PK, unique?: UNIQUE, index?: INDEX, override?: boolean }
484
- ): ModelClass<T, PKArgs<FieldsOf<T>, PK>, UNIQUE, INDEX> {
519
+ ): ModelClass<
520
+ StaticMembers<T>,
521
+ PublicFields<FieldsOf<T>>,
522
+ QueryFields<FieldsOf<T>>,
523
+ PKArgs<QueryFields<FieldsOf<T>>, PK>,
524
+ PublicIndexSpecs<UNIQUE>,
525
+ PublicIndexSpecs<INDEX>
526
+ > {
485
527
  Object.setPrototypeOf(cls.prototype, ModelBase.prototype);
486
528
  const MockModel = function(this: any, initial?: Record<string, any>, txn: Transaction = currentTxn()) {
487
529
  this._txn = txn;
package/src/types.ts CHANGED
@@ -2,7 +2,7 @@ import DataPack from "./datapack.js";
2
2
  import { DatabaseError } from "olmdb/lowlevel";
3
3
  import { currentTxn } from "./edinburgh.js";
4
4
  import { Model, modelRegistry } from "./models.js";
5
- import type { AnyModelClass } from "./models.js";
5
+ import type { AnyModelClass, ModelBase as ModelInstanceBase } from "./models.js";
6
6
  import { assert, addErrorPath, dbGet } from "./utils.js";
7
7
 
8
8
 
@@ -87,6 +87,44 @@ export interface TypeWrapper<T> {
87
87
  default?(model: any): T;
88
88
  }
89
89
 
90
+ // Hidden type-only metadata used to widen lookup arguments without widening assignment types.
91
+ export declare const QUERY_ARG: unique symbol;
92
+
93
+ export type LinkTargetPKArgs<T extends new (...args: any) => any> =
94
+ T extends { get(...args: infer PKA): any } ? PKA : never;
95
+
96
+ export type LinkPrimaryKeyInput<PKA extends readonly any[]> =
97
+ PKA extends readonly [infer ONLY]
98
+ ? ONLY | PKA
99
+ : PKA;
100
+
101
+ type QueryArgCarrier<QUERY> = {
102
+ readonly [QUERY_ARG]?: QUERY;
103
+ };
104
+
105
+ type QueryAnnotated<T, QUERY> = T & QueryArgCarrier<QUERY>;
106
+
107
+ export type FieldValue<TYPE extends TypeWrapper<any>> =
108
+ TYPE extends TypeWrapper<infer T>
109
+ ? TYPE extends { readonly [QUERY_ARG]?: infer QUERY }
110
+ ? QueryAnnotated<T, Exclude<QUERY, undefined>>
111
+ : T
112
+ : never;
113
+
114
+ export type StripQueryArg<T> =
115
+ T extends ModelInstanceBase & { readonly [QUERY_ARG]?: any }
116
+ ? Model<{
117
+ [K in Exclude<keyof T, keyof ModelInstanceBase | typeof QUERY_ARG>]: T[K]
118
+ }>
119
+ : T extends { readonly [QUERY_ARG]?: any }
120
+ ? { [K in keyof T as K extends typeof QUERY_ARG ? never : K]: T[K] }
121
+ : T;
122
+
123
+ export type FieldQueryArg<T> =
124
+ T extends { readonly [QUERY_ARG]?: infer QUERY }
125
+ ? Exclude<QUERY, undefined>
126
+ : T;
127
+
90
128
 
91
129
  class StringType extends TypeWrapper<string> {
92
130
  kind = 'string';
@@ -620,7 +658,7 @@ export class LinkType<T extends new (...args: any[]) => Model<any>> extends Type
620
658
  }
621
659
 
622
660
  getLinkedModel(): AnyModelClass {
623
- if (!('getLazy' in this.TargetModel)) this.TargetModel = (this.TargetModel as unknown as () => T)();
661
+ if (!('getLazy' in (this.TargetModel as any))) this.TargetModel = (this.TargetModel as unknown as () => T)();
624
662
  return this.TargetModel as any;
625
663
  }
626
664
 
@@ -628,8 +666,8 @@ export class LinkType<T extends new (...args: any[]) => Model<any>> extends Type
628
666
  pack.write(model.getPrimaryKey());
629
667
  }
630
668
 
631
- deserialize(pack: DataPack) {
632
- return this.getLinkedModel()._get(currentTxn(), pack.readUint8Array(), false);
669
+ deserialize(pack: DataPack): InstanceType<T> {
670
+ return this.getLinkedModel()._get(currentTxn(), pack.readUint8Array(), false) as InstanceType<T>;
633
671
  }
634
672
 
635
673
  getError(value: InstanceType<T>) {
@@ -795,7 +833,9 @@ export function record<const T>(inner: TypeWrapper<T>): TypeWrapper<Record<strin
795
833
  * }, { pk: "id" });
796
834
  * ```
797
835
  */
798
- export function link<const T extends new (...args: any[]) => Model<any>>(TargetModel: T): TypeWrapper<InstanceType<T>>;
836
+ export function link<const T extends new (...args: any[]) => Model<any>>(
837
+ TargetModel: T,
838
+ ): TypeWrapper<InstanceType<T>> & QueryArgCarrier<InstanceType<T> | LinkPrimaryKeyInput<LinkTargetPKArgs<T>>>;
799
839
  export function link<const T extends new (...args: any[]) => Model<any>>(TargetModel: () => T): TypeWrapper<InstanceType<T>>;
800
840
  export function link(TargetModel: any): TypeWrapper<any> {
801
841
  return new LinkType(TargetModel);