peta-orm 0.4.1 → 0.6.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/dist/index.d.mts CHANGED
@@ -1,11 +1,76 @@
1
1
  import { Dialect, Kysely } from "kysely";
2
2
 
3
- //#region src/lib/kysely.d.ts
3
+ //#region src/columns/schema.d.ts
4
+ interface Constraint {
5
+ type: string;
6
+ args: unknown[];
7
+ }
8
+ interface SchemaConfig {
9
+ compile(dataType: string, args: unknown[], constraints: Constraint[]): unknown;
10
+ parse<T>(schema: unknown, value: unknown): T;
11
+ assert<T>(schema: unknown, value: unknown): T;
12
+ }
13
+ //#endregion
14
+ //#region src/columns/column.d.ts
15
+ interface Column<out T = unknown> {
16
+ readonly arkType: unknown;
17
+ readonly dataType: string;
18
+ readonly args: readonly unknown[];
19
+ readonly constraints: readonly Constraint[];
20
+ readonly isNullable: boolean;
21
+ readonly isPrimaryKey: boolean;
22
+ readonly isUnique: boolean;
23
+ readonly defaultValue: unknown;
24
+ hasConstraint(type: string): boolean;
25
+ parse(value: unknown): T;
26
+ assert(value: unknown): T;
27
+ primaryKey(): Column<T>;
28
+ nullable(): Column<T | null>;
29
+ default<V>(value: V): Column<T>;
30
+ unique(): Column<T>;
31
+ index(): Column<T>;
32
+ min(n: number): Column<T>;
33
+ max(n: number): Column<T>;
34
+ email(): Column<T>;
35
+ url(): Column<T>;
36
+ pattern(regex: RegExp | string): Column<T>;
37
+ references(table: () => unknown, columns: string[]): Column<T>;
38
+ }
39
+ declare function createColumn<T>(schema: SchemaConfig, dataType: string, args?: unknown[], constraints?: Constraint[]): Column<T>;
40
+ type ColumnShape = Record<string, Column>;
41
+ type ColumnValue<C> = C extends Column<infer T> ? T : never;
42
+ //#endregion
43
+ //#region src/types.d.ts
4
44
  type Database = Kysely<Record<string, never>>;
45
+ interface ModelLike<TColumns extends ColumnShape = ColumnShape> {
46
+ get<K extends keyof TColumns>(key: K): ColumnValue<TColumns[K]>;
47
+ get(key: string): unknown;
48
+ set(key: string, value: unknown): void;
49
+ }
50
+ interface ORMLike {
51
+ readonly kysely: Database;
52
+ register(model: ModelDefinition<any>): void;
53
+ registerAll(...models: (ModelDefinition<any> | ModelDefinition<any>[])[]): void;
54
+ destroy(): Promise<void>;
55
+ transaction<T>(fn: (orm: ORMLike) => Promise<T>): Promise<T>;
56
+ readonly models: ReadonlyMap<string, ModelDefinition<any>>;
57
+ getModel<T extends ColumnShape = ColumnShape>(name: string): ModelDefinition<T> | undefined;
58
+ /**
59
+ * Discover model definitions by scanning files matching a glob pattern.
60
+ *
61
+ * Uses `fast-glob` to resolve the pattern relative to `cwd`, then dynamically
62
+ * imports each matching file and collects exported `ModelDefinition` values.
63
+ * Does **not** auto-register — use `registerAll(...result)` to register them.
64
+ *
65
+ * @param pattern Glob pattern (e.g. `"./src/models/**\/*.ts"`)
66
+ * @returns Array of discovered model definitions
67
+ */
68
+ discover(pattern: string): Promise<ModelDefinition<any>[]>;
69
+ }
5
70
  //#endregion
6
71
  //#region src/pagination/index.d.ts
7
- interface Paginator {
8
- readonly data: Collection;
72
+ interface Paginator<TColumns extends ColumnShape = ColumnShape> {
73
+ readonly data: Collection<TColumns>;
9
74
  readonly total: number;
10
75
  readonly perPage: number;
11
76
  readonly currentPage: number;
@@ -16,12 +81,10 @@ interface Paginator {
16
81
  readonly lastItem: number;
17
82
  readonly onFirstPage: boolean;
18
83
  readonly onLastPage: boolean;
19
- readonly count: number;
20
- map<T>(fn: (item: ModelInstance) => T): T[];
21
- toJSON(): PaginatorJson;
84
+ toJSON(): PaginatorJson<TColumns>;
22
85
  }
23
- interface PaginatorJson {
24
- data: Record<string, unknown>[];
86
+ interface PaginatorJson<TColumns extends ColumnShape = ColumnShape> {
87
+ data: SerializedShape<TColumns>[];
25
88
  total: number;
26
89
  perPage: number;
27
90
  currentPage: number;
@@ -33,8 +96,13 @@ interface PaginatorJson {
33
96
  onFirstPage: boolean;
34
97
  onLastPage: boolean;
35
98
  }
36
- type PaginatedResult = PaginatorJson;
37
- declare function createPaginator(items: ModelInstance[], total: number, perPage: number, currentPage: number): Paginator;
99
+ declare function createPaginator<TColumns extends ColumnShape = ColumnShape>(items: ModelInstance<TColumns>[], total: number, perPage: number, currentPage: number): Paginator<TColumns>;
100
+ //#endregion
101
+ //#region src/relations/graph/delete.d.ts
102
+ interface DeleteGraphOptions {
103
+ allowedRelations?: string[];
104
+ }
105
+ declare function deleteGraph(def: ModelDefinition, model: ModelInstance, options?: DeleteGraphOptions): Promise<void>;
38
106
  //#endregion
39
107
  //#region src/relations/base.d.ts
40
108
  type RelationType = "hasMany" | "belongsTo" | "hasOne" | "manyToMany" | "hasManyThrough";
@@ -97,14 +165,14 @@ interface UpsertGraphOptions extends InsertGraphOptions {
97
165
  }
98
166
  //#endregion
99
167
  //#region src/query/types.d.ts
100
- interface QueryBuilder extends PromiseLike<ModelInstance[]> {
101
- execute(): Promise<ModelInstance[]>;
102
- collect(): Promise<Collection>;
103
- executeTakeFirst(): Promise<ModelInstance | undefined>;
104
- executeTakeFirstOrThrow(): Promise<ModelInstance>;
105
- find(id: number | string): Promise<ModelInstance | undefined>;
106
- findOrFail(id: number | string): Promise<ModelInstance>;
107
- first(): Promise<ModelInstance | undefined>;
168
+ interface QueryBuilder<TColumns extends ColumnShape = ColumnShape> extends PromiseLike<ModelInstance<TColumns>[]> {
169
+ execute(): Promise<ModelInstance<TColumns>[]>;
170
+ collect(): Promise<Collection<TColumns>>;
171
+ executeTakeFirst(): Promise<ModelInstance<TColumns> | undefined>;
172
+ executeTakeFirstOrThrow(): Promise<ModelInstance<TColumns>>;
173
+ find(id: number | string): Promise<ModelInstance<TColumns> | undefined>;
174
+ findOrFail(id: number | string): Promise<ModelInstance<TColumns>>;
175
+ first(): Promise<ModelInstance<TColumns> | undefined>;
108
176
  toSQL(): {
109
177
  sql: string;
110
178
  parameters: readonly unknown[];
@@ -114,17 +182,14 @@ interface QueryBuilder extends PromiseLike<ModelInstance[]> {
114
182
  avg(column: string): Promise<number>;
115
183
  min(column: string): Promise<number>;
116
184
  max(column: string): Promise<number>;
117
- withCount(relation: string): QueryBuilder;
118
- withSum(relation: string, column: string): QueryBuilder;
119
- withAvg(relation: string, column: string): QueryBuilder;
120
- withMin(relation: string, column: string): QueryBuilder;
121
- withMax(relation: string, column: string): QueryBuilder;
122
- withExists(relation: string): QueryBuilder;
123
- chunk(size: number, callback: (chunk: ModelInstance[]) => Promise<void>): Promise<void>;
124
- paginate(page: number, perPage?: number): Promise<Paginator>;
185
+ withCount(relation: string): QueryBuilder<TColumns>;
186
+ withSum(relation: string, column: string): QueryBuilder<TColumns>;
187
+ chunk(size: number, callback: (chunk: ModelInstance<TColumns>[]) => Promise<void>): Promise<void>;
188
+ paginate(page: number, perPage?: number): Promise<Paginator<TColumns>>;
125
189
  insertGraph(data: Record<string, unknown> | Record<string, unknown>[], options?: InsertGraphOptions): Promise<any>;
126
190
  upsertGraph(data: Record<string, unknown> | Record<string, unknown>[], options?: UpsertGraphOptions): Promise<any>;
127
- with(...relations: (string | Record<string, (qb: QueryBuilder) => void>)[]): QueryBuilder;
191
+ upsert(data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
192
+ with(...relations: (string | Record<string, (qb: QueryBuilder<TColumns>) => void>)[]): QueryBuilder<TColumns>;
128
193
  /**
129
194
  * Whitelist allowed relations (and nested paths) for eager loading.
130
195
  * Throws if a relation path is not in the allow list.
@@ -136,42 +201,50 @@ interface QueryBuilder extends PromiseLike<ModelInstance[]> {
136
201
  *
137
202
  * Multiple arguments are merged: `allowGraph("posts", "profile")`
138
203
  */
139
- allowGraph(...expressions: string[]): QueryBuilder;
204
+ allowGraph(...expressions: string[]): QueryBuilder<TColumns>;
140
205
  updateMany(data: Record<string, unknown>): Promise<number>;
141
206
  deleteMany(): Promise<number>;
142
- withTrashed(): QueryBuilder;
143
- onlyTrashed(): QueryBuilder;
144
- whereIn(column: string, values: unknown[]): QueryBuilder;
145
- whereInPivot(column: string, values: unknown[]): QueryBuilder;
146
- has(relationName: string): QueryBuilder;
147
- whereHas(relationName: string, callback?: (qb: QueryBuilder) => void): QueryBuilder;
148
- whereDoesntHave(relationName: string, callback?: (qb: QueryBuilder) => void): QueryBuilder;
149
- where(column: string, operator: unknown, value?: unknown): QueryBuilder;
150
- whereRef(col1: string, operator: string, col2: string): QueryBuilder;
151
- orWhere(column: string, operator: unknown, value?: unknown): QueryBuilder;
152
- orderBy(column: string, direction?: "asc" | "desc"): QueryBuilder;
153
- limit(n: number): QueryBuilder;
154
- offset(n: number): QueryBuilder;
155
- select(...columns: string[]): QueryBuilder;
156
- selectAll(table?: string): QueryBuilder;
157
- innerJoin(table: string, lhs: string, rhs: string): QueryBuilder;
158
- leftJoin(table: string, lhs: string, rhs: string): QueryBuilder;
159
- groupBy(...columns: string[]): QueryBuilder;
160
- having(column: string, operator: string, value: unknown): QueryBuilder;
161
- withoutGlobalScope(name: string): QueryBuilder;
162
- all(): QueryBuilder;
207
+ withTrashed(): QueryBuilder<TColumns>;
208
+ onlyTrashed(): QueryBuilder<TColumns>;
209
+ whereIn(column: string, values: unknown[]): QueryBuilder<TColumns>;
210
+ has(relationName: string): QueryBuilder<TColumns>;
211
+ /**
212
+ * Filter rows by related model existence with optional subquery filtering.
213
+ * The callback receives a raw Kysely subquery builder for the related table,
214
+ * not a peta-orm QueryBuilder. Chain `.where(...)` etc. directly on it.
215
+ */
216
+ whereHas(relationName: string, callback?: (subQb: any) => any): QueryBuilder<TColumns>;
217
+ /**
218
+ * Filter rows by absence of related model, with optional subquery filtering.
219
+ * Same callback semantics as `whereHas`.
220
+ */
221
+ whereDoesntHave(relationName: string, callback?: (subQb: any) => any): QueryBuilder<TColumns>;
222
+ where(column: string, operator: unknown, value?: unknown): QueryBuilder<TColumns>;
223
+ whereRef(col1: string, operator: string, col2: string): QueryBuilder<TColumns>;
224
+ orWhere(column: string, operator: unknown, value?: unknown): QueryBuilder<TColumns>;
225
+ orderBy(column: string, direction?: "asc" | "desc"): QueryBuilder<TColumns>;
226
+ limit(n: number): QueryBuilder<TColumns>;
227
+ offset(n: number): QueryBuilder<TColumns>;
228
+ select(...columns: string[]): QueryBuilder<TColumns>;
229
+ selectAll(table?: string): QueryBuilder<TColumns>;
230
+ innerJoin(table: string, lhs: string, rhs: string): QueryBuilder<TColumns>;
231
+ leftJoin(table: string, lhs: string, rhs: string): QueryBuilder<TColumns>;
232
+ groupBy(...columns: string[]): QueryBuilder<TColumns>;
233
+ having(column: string, operator: string, value: unknown): QueryBuilder<TColumns>;
234
+ withoutGlobalScope(name: string): QueryBuilder<TColumns>;
235
+ all(): QueryBuilder<TColumns>;
163
236
  /** @internal Access underlying Kysely builder for raw SQL operations */
164
237
  _getKyselyQb(): any;
165
238
  /** @internal Replace the underlying Kysely builder */
166
239
  _replaceKyselyQb(newQb: any): void;
167
- when(condition: unknown, callback: (q: QueryBuilder) => QueryBuilder): QueryBuilder;
168
- unless(condition: unknown, callback: (q: QueryBuilder) => QueryBuilder): QueryBuilder;
240
+ when(condition: unknown, callback: (q: QueryBuilder<TColumns>) => QueryBuilder<TColumns>): QueryBuilder<TColumns>;
241
+ unless(condition: unknown, callback: (q: QueryBuilder<TColumns>) => QueryBuilder<TColumns>): QueryBuilder<TColumns>;
169
242
  }
170
243
  //#endregion
171
244
  //#region src/query/builder.d.ts
172
- declare function createQueryBuilder(def: ModelDefinition, peta?: {
245
+ declare function createQueryBuilder<TColumns extends ColumnShape = ColumnShape>(def: ModelDefinition<TColumns>, peta?: {
173
246
  kysely: Database;
174
- }): QueryBuilder;
247
+ }): QueryBuilder<TColumns>;
175
248
  //#endregion
176
249
  //#region src/relations/related-query.d.ts
177
250
  interface RelationQuery extends QueryBuilder {
@@ -202,87 +275,6 @@ interface RelationQuery extends QueryBuilder {
202
275
  */
203
276
  type Plugin = (def: ModelDefinition) => undefined | ModelDefinition;
204
277
  //#endregion
205
- //#region src/columns/schema.d.ts
206
- interface Constraint {
207
- type: string;
208
- args: unknown[];
209
- }
210
- interface SchemaConfig {
211
- compile(dataType: string, args: unknown[], constraints: Constraint[]): unknown;
212
- parse<T>(schema: unknown, value: unknown): T;
213
- assert<T>(schema: unknown, value: unknown): T;
214
- }
215
- //#endregion
216
- //#region src/columns/column.d.ts
217
- interface Column<out T = unknown> {
218
- readonly arkType: unknown;
219
- readonly dataType: string;
220
- readonly args: readonly unknown[];
221
- readonly constraints: readonly Constraint[];
222
- readonly isNullable: boolean;
223
- readonly isPrimaryKey: boolean;
224
- readonly isUnique: boolean;
225
- readonly defaultValue: unknown;
226
- hasConstraint(type: string): boolean;
227
- parse(value: unknown): T;
228
- assert(value: unknown): T;
229
- primaryKey(): Column<T>;
230
- nullable(): Column<T | null>;
231
- default<V>(value: V): Column<T>;
232
- unique(): Column<T>;
233
- index(): Column<T>;
234
- min(n: number): Column<T>;
235
- max(n: number): Column<T>;
236
- email(): Column<T>;
237
- url(): Column<T>;
238
- pattern(regex: RegExp | string): Column<T>;
239
- references(table: () => unknown, columns: string[]): Column<T>;
240
- }
241
- declare function createColumn<T>(schema: SchemaConfig, dataType: string, args?: unknown[], constraints?: Constraint[]): Column<T>;
242
- type ColumnShape = Record<string, Column>;
243
- type ColumnValue<C> = C extends Column<infer T> ? T : never;
244
- //#endregion
245
- //#region src/types.d.ts
246
- type ModelId = number & {
247
- readonly __brand: "ModelId";
248
- };
249
- interface ModelLike {
250
- get<T = unknown>(key: string): T;
251
- set(key: string, value: unknown): void;
252
- }
253
- interface ORMLike {
254
- readonly kysely: Database;
255
- register(model: ModelDefinition$1<any>): void;
256
- registerAll(...models: (ModelDefinition$1<any> | ModelDefinition$1<any>[])[]): void;
257
- destroy(): Promise<void>;
258
- transaction<T>(fn: (trx: import("kysely").Kysely<Record<string, never>>) => Promise<T>): Promise<T>;
259
- readonly models: ReadonlyMap<string, ModelDefinition$1<any>>;
260
- getModel<T extends ColumnShape = ColumnShape>(name: string): ModelDefinition$1<T> | undefined;
261
- }
262
- interface ModelDefinition$1<TColumns extends ColumnShape = ColumnShape> {
263
- readonly table: string;
264
- readonly columns: TColumns;
265
- readonly relations: Record<string, Relation>;
266
- readonly name: string;
267
- _orm: ORMLike | null;
268
- query(): QueryBuilder;
269
- find(id: number | string): Promise<ModelInstance | undefined>;
270
- findOrFail(id: number | string): Promise<ModelInstance>;
271
- first(): Promise<ModelInstance | undefined>;
272
- create(data: Record<string, unknown>): Promise<ModelInstance>;
273
- insert(data: Record<string, unknown>): Promise<ModelInstance>;
274
- insertMany(dataArray: Record<string, unknown>[]): Promise<ModelInstance[]>;
275
- update(id: number | string, data: Record<string, unknown>): Promise<ModelInstance>;
276
- delete(id: number | string): Promise<void>;
277
- hydrate(row: Record<string, unknown>): ModelInstance;
278
- on(event: string, callback: (model: ModelInstance) => void | Promise<void>): () => void;
279
- getHooks(): HookManager;
280
- addGlobalScope(name: string, callback: (qb: QueryBuilder) => void): void;
281
- removeGlobalScope(name: string): void;
282
- getGlobalScopes(): Map<string, (qb: QueryBuilder) => void> | undefined;
283
- _init(orm: ORMLike): void;
284
- }
285
- //#endregion
286
278
  //#region src/hooks/index.d.ts
287
279
  type LifecycleEvent = "beforeCreate" | "afterCreate" | "beforeUpdate" | "afterUpdate" | "beforeSave" | "afterSave" | "beforeDelete" | "afterDelete" | "beforeRestore" | "afterRestore" | "beforeForceDelete" | "afterForceDelete";
288
280
  type HookCallback = (model: ModelLike) => void | Promise<void>;
@@ -290,7 +282,6 @@ interface HookManager {
290
282
  on(event: LifecycleEvent, callback: HookCallback): () => void;
291
283
  off(event: LifecycleEvent, callback: HookCallback): void;
292
284
  trigger(event: LifecycleEvent, model: ModelLike): Promise<void>;
293
- clone(): HookManager;
294
285
  }
295
286
  declare function createHookManager(): HookManager;
296
287
  //#endregion
@@ -307,14 +298,12 @@ type StaticHookCallback = (args: StaticHookArgs) => void | Promise<void>;
307
298
  //#endregion
308
299
  //#region src/model/computed.d.ts
309
300
  interface ComputedColumn<T = unknown> {
310
- readonly type: "sql" | "runtime" | "batch";
301
+ readonly type: "runtime" | "batch";
311
302
  readonly dependencies: string[];
312
303
  /** Compute a value for a single record (runtime) */
313
304
  compute?: (record: ModelInstance) => T;
314
305
  /** Compute values for a batch of records (batch async) */
315
306
  batchCompute?: (records: ModelInstance[]) => Promise<T[]>;
316
- /** Raw SQL expression to inline in SELECT */
317
- sql?: string;
318
307
  }
319
308
  //#endregion
320
309
  //#region src/model/attribute.d.ts
@@ -358,12 +347,15 @@ declare class Attribute<T = any> {
358
347
  }
359
348
  //#endregion
360
349
  //#region src/model/types.d.ts
361
- interface ModelInstance {
350
+ /** Mapped column shape — resolves each column to its JS value type for $toJSON(). */
351
+ type SerializedShape<TColumns extends ColumnShape> = { [K in keyof TColumns]: TColumns[K] extends Column<infer T> ? T : unknown } & Record<string, unknown>;
352
+ interface ModelInstance<TColumns extends ColumnShape = ColumnShape> {
362
353
  readonly exists: boolean;
363
354
  readonly attributes: Record<string, unknown>;
364
355
  readonly dirtyAttributes: Record<string, unknown>;
365
356
  isDirty(key?: string): boolean;
366
- get<T = unknown>(key: string): T;
357
+ get<K extends keyof TColumns>(key: K): ColumnValue<TColumns[K]>;
358
+ get(key: string): unknown;
367
359
  set(key: string, value: unknown): void;
368
360
  fill(data: Record<string, unknown>): void;
369
361
  reset(): void;
@@ -379,8 +371,8 @@ interface ModelInstance {
379
371
  $restore(): Promise<void>;
380
372
  $trashed(): boolean;
381
373
  $reload(): Promise<void>;
382
- $toJSON(): Record<string, unknown>;
383
- toJSON(): Record<string, unknown>;
374
+ $toJSON(): SerializedShape<TColumns>;
375
+ toJSON(): SerializedShape<TColumns>;
384
376
  }
385
377
  interface ModelDefinition<TColumns extends ColumnShape = ColumnShape> {
386
378
  readonly table: string;
@@ -388,36 +380,34 @@ interface ModelDefinition<TColumns extends ColumnShape = ColumnShape> {
388
380
  readonly relations: Record<string, Relation>;
389
381
  readonly name: string;
390
382
  _orm: ORMLike | null;
391
- query(): QueryBuilder;
392
- find(id: number | string): Promise<ModelInstance | undefined>;
393
- findOrFail(id: number | string): Promise<ModelInstance>;
394
- first(): Promise<ModelInstance | undefined>;
395
- create(data: Record<string, unknown>): Promise<ModelInstance>;
396
- insert(data: Record<string, unknown>): Promise<ModelInstance>;
397
- insertMany(dataArray: Record<string, unknown>[]): Promise<ModelInstance[]>;
398
- update(id: number | string, data: Record<string, unknown>): Promise<ModelInstance>;
383
+ query(): QueryBuilder<TColumns>;
384
+ find(id: number | string): Promise<ModelInstance<TColumns> | undefined>;
385
+ findOrFail(id: number | string): Promise<ModelInstance<TColumns>>;
386
+ first(): Promise<ModelInstance<TColumns> | undefined>;
387
+ create(data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
388
+ insert(data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
389
+ insertMany(dataArray: Record<string, unknown>[]): Promise<ModelInstance<TColumns>[]>;
390
+ updateMany(data: Record<string, unknown>, where: Record<string, unknown>[]): Promise<number>;
391
+ deleteMany(where: Record<string, unknown>[]): Promise<number>;
392
+ update(id: number | string, data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
399
393
  delete(id: number | string): Promise<void>;
394
+ deleteGraph(idOrInstance: any, options?: DeleteGraphOptions): Promise<void>;
400
395
  insertGraph(data: Record<string, unknown> | Record<string, unknown>[], options?: InsertGraphOptions): Promise<any>;
401
396
  upsertGraph(data: Record<string, unknown> | Record<string, unknown>[], options?: UpsertGraphOptions): Promise<any>;
402
- hydrate(row: Record<string, unknown>): ModelInstance;
403
- use(plugin: Plugin): ModelDefinition;
397
+ upsert(data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
398
+ hydrate(row: Record<string, unknown>): ModelInstance<TColumns>;
399
+ use(plugin: Plugin): ModelDefinition<TColumns>;
404
400
  makeHelper<A extends any[], R>(fn: (qb: QueryBuilder, ...args: A) => R): (...args: A) => R;
405
- on(event: string, callback: (model: ModelInstance) => void | Promise<void>): () => void;
401
+ on(event: string, callback: (model: ModelInstance<TColumns>) => void | Promise<void>): () => void;
406
402
  getHooks(): HookManager;
407
403
  beforeDelete(callback: StaticHookCallback): () => void;
408
404
  afterDelete(callback: StaticHookCallback): () => void;
409
405
  beforeUpdate(callback: StaticHookCallback): () => void;
410
- afterUpdate(callback: StaticHookCallback): () => void;
411
- beforeCreate(callback: StaticHookCallback): () => void;
412
- afterCreate(callback: StaticHookCallback): () => void;
413
- beforeFind(callback: StaticHookCallback): () => void;
414
- afterFind(callback: StaticHookCallback): () => void;
415
406
  addGlobalScope(name: string, callback: (qb: QueryBuilder) => void): void;
416
407
  removeGlobalScope(name: string): void;
417
408
  getGlobalScopes(): Map<string, (qb: QueryBuilder) => void> | undefined;
418
409
  registerTimestamps?(createdAtCol?: string, updatedAtCol?: string): void;
419
410
  registerSoftDeletes?(deletedAtCol?: string): void;
420
- discover?(): Promise<never>;
421
411
  _init(orm: ORMLike): void;
422
412
  }
423
413
  interface ModelConfig<TColumns extends ColumnShape = ColumnShape> {
@@ -433,46 +423,45 @@ interface ModelConfig<TColumns extends ColumnShape = ColumnShape> {
433
423
  }
434
424
  //#endregion
435
425
  //#region src/collection/index.d.ts
436
- interface Collection {
426
+ interface Collection<TColumns extends ColumnShape = ColumnShape> {
437
427
  readonly length: number;
438
- [Symbol.iterator](): Iterator<ModelInstance>;
439
- at(index: number): ModelInstance | undefined;
440
- first(): ModelInstance | undefined;
441
- last(): ModelInstance | undefined;
442
- all(): ModelInstance[];
443
- findBy(id: number | string): ModelInstance | undefined;
444
- find(callback: (item: ModelInstance, index: number) => boolean): ModelInstance | undefined;
445
- some(callback: (item: ModelInstance, index: number) => boolean): boolean;
446
- includes(item: ModelInstance): boolean;
428
+ [Symbol.iterator](): Iterator<ModelInstance<TColumns>>;
429
+ at(index: number): ModelInstance<TColumns> | undefined;
430
+ first(): ModelInstance<TColumns> | undefined;
431
+ last(): ModelInstance<TColumns> | undefined;
432
+ all(): ModelInstance<TColumns>[];
433
+ findBy(id: number | string): ModelInstance<TColumns> | undefined;
434
+ find(callback: (item: ModelInstance<TColumns>, index: number) => boolean): ModelInstance<TColumns> | undefined;
435
+ some(callback: (item: ModelInstance<TColumns>, index: number) => boolean): boolean;
436
+ includes(item: ModelInstance<TColumns>): boolean;
447
437
  isEmpty(): boolean;
448
438
  isNotEmpty(): boolean;
449
439
  get(key: string): unknown[];
450
440
  pluck(key: string): unknown[];
451
- groupBy(key: string): Record<string, ModelInstance[]>;
452
- keyBy(key: string): Record<string, ModelInstance>;
453
- map<T>(fn: (item: ModelInstance, index: number) => T): T[];
454
- filter(fn: (item: ModelInstance, index: number) => boolean): Collection;
455
- reduce<T>(fn: (acc: T, item: ModelInstance, index: number) => T, initial: T): T;
456
- forEach(fn: (item: ModelInstance, index: number) => void): void;
457
- each(fn: (item: ModelInstance, index: number) => void): Collection;
458
- unique(key?: string): Collection;
459
- sortBy(key: string, direction?: "asc" | "desc"): Collection;
460
- shuffle(): Collection;
461
- take(n: number): Collection;
462
- skip(n: number): Collection;
463
- chunk(size: number): Collection[];
441
+ groupBy(key: string): Record<string, ModelInstance<TColumns>[]>;
442
+ keyBy(key: string): Record<string, ModelInstance<TColumns>>;
443
+ map<T>(fn: (item: ModelInstance<TColumns>, index: number) => T): T[];
444
+ filter(fn: (item: ModelInstance<TColumns>, index: number) => boolean): Collection<TColumns>;
445
+ reduce<T>(fn: (acc: T, item: ModelInstance<TColumns>, index: number) => T, initial: T): T;
446
+ forEach(fn: (item: ModelInstance<TColumns>, index: number) => void): void;
447
+ unique(key?: string): Collection<TColumns>;
448
+ sortBy(key: string, direction?: "asc" | "desc"): Collection<TColumns>;
449
+ shuffle(): Collection<TColumns>;
450
+ take(n: number): Collection<TColumns>;
451
+ skip(n: number): Collection<TColumns>;
452
+ chunk(size: number): Collection<TColumns>[];
464
453
  sum(key: string): number;
465
454
  avg(key: string): number;
466
455
  min(key: string): number;
467
456
  max(key: string): number;
468
- diff(other: Collection): Collection;
469
- intersect(other: Collection): Collection;
470
- concat(other: Collection): Collection;
471
- push(...items: ModelInstance[]): void;
472
- load(...relations: string[]): Promise<Collection>;
473
- toJSON(): Record<string, unknown>[];
474
- }
475
- declare function createCollection(items?: ModelInstance[]): Collection;
457
+ diff(other: Collection<TColumns>): Collection<TColumns>;
458
+ intersect(other: Collection<TColumns>): Collection<TColumns>;
459
+ concat(other: Collection<TColumns>): Collection<TColumns>;
460
+ push(...items: ModelInstance<TColumns>[]): void;
461
+ load(...relations: string[]): Promise<Collection<TColumns>>;
462
+ toJSON(): SerializedShape<TColumns>[];
463
+ }
464
+ declare function createCollection<TColumns extends ColumnShape = ColumnShape>(items?: ModelInstance<TColumns>[]): Collection<TColumns>;
476
465
  //#endregion
477
466
  //#region src/columns/arktype.d.ts
478
467
  declare function createArkTypeSchemaConfig(): SchemaConfig;
@@ -499,7 +488,27 @@ interface ColumnTypes {
499
488
  updatedAt: Column<string>;
500
489
  };
501
490
  }
502
- declare function t(config: {
491
+ /**
492
+ * Pre-configured column type factory backed by ArkType validation.
493
+ *
494
+ * The most common usage — just import and use:
495
+ * ```ts
496
+ * import { t } from "peta-orm"
497
+ * const id = t.integer().primaryKey()
498
+ * ```
499
+ *
500
+ * For a custom validation backend, use `createColumnTypes({ schema })` instead.
501
+ */
502
+ declare const t: ColumnTypes;
503
+ /**
504
+ * Create a column type factory with a custom validation schema backend.
505
+ *
506
+ * @example
507
+ * ```ts
508
+ * const t = createColumnTypes({ schema: myCustomSchemaConfig })
509
+ * ```
510
+ */
511
+ declare function createColumnTypes(config: {
503
512
  schema: SchemaConfig;
504
513
  }): ColumnTypes;
505
514
  //#endregion
@@ -536,17 +545,74 @@ declare class DatabaseError extends Error {
536
545
  //#region src/errors/normalizer.d.ts
537
546
  declare function normalizeError(e: unknown, table?: string): DatabaseError;
538
547
  //#endregion
548
+ //#region src/init.d.ts
549
+ /**
550
+ * Create a lazy-initialized singleton factory.
551
+ *
552
+ * The factory function is called only once — on the first call to the returned
553
+ * function. Subsequent calls return the same resolved promise. This avoids
554
+ * module-level side effects: importing a model file won't trigger database
555
+ * connection or schema initialization until the first explicit `await db()`.
556
+ *
557
+ * @example
558
+ * ```ts
559
+ * import { createClient } from "@libsql/client"
560
+ * import { LibsqlDialect } from "@libsql/kysely-libsql"
561
+ * import { createDb, createORM, defineModel, t } from "peta-orm"
562
+ *
563
+ * const User = defineModel("users", { columns: { ... } })
564
+ *
565
+ * async function setup() {
566
+ * const client = createClient({ url: "file:my-app.db" })
567
+ * await client.execute("CREATE TABLE IF NOT EXISTS users (...)") // schema init
568
+ * const orm = createORM({ dialect: new LibsqlDialect({ client }) })
569
+ * orm.registerAll(User)
570
+ * return orm
571
+ * }
572
+ *
573
+ * export const db = createDb(setup)
574
+ * // Usage: const orm = await db()
575
+ * ```
576
+ */
577
+ declare function createDb<T>(factory: () => Promise<T>): () => Promise<T>;
578
+ //#endregion
579
+ //#region src/integrations/elysia.d.ts
580
+ interface PetaElysiaPluginOptions {
581
+ peta: ORMLike;
582
+ }
583
+ /**
584
+ * Elysia.js plugin that attaches the ORM instance to the app context.
585
+ */
586
+ declare function petaPlugin(options: PetaElysiaPluginOptions): (app: any) => any;
587
+ //#endregion
588
+ //#region src/integrations/hono.d.ts
589
+ interface PetaHonoMiddlewareOptions {
590
+ peta: ORMLike;
591
+ }
592
+ /**
593
+ * Hono middleware that sets the ORM instance on the context.
594
+ */
595
+ declare function petaMiddleware(options: PetaHonoMiddlewareOptions): (c: any, next: any) => Promise<void>;
596
+ //#endregion
539
597
  //#region src/model/define.d.ts
540
598
  declare function defineModel<TColumns extends ColumnShape>(table: string, config: ModelConfig<TColumns>): ModelDefinition<TColumns>;
541
599
  //#endregion
542
600
  //#region src/orm/index.d.ts
543
601
  interface ORMConfig {
544
- dialect: Dialect;
602
+ /** Kysely dialect to create an internal Kysely instance. Required unless `kysely` is provided. */
603
+ dialect?: Dialect;
604
+ /** A pre-existing Kysely instance to reuse. Required unless `dialect` is provided. */
605
+ kysely?: Kysely<any>;
606
+ /** Optional map of model definitions to register immediately. */
545
607
  models?: Record<string, ModelDefinition>;
546
608
  }
547
609
  /**
548
610
  * Create an ORM instance — the central registry that wires Kysely to model definitions.
549
611
  * Replaces createPeta() from v0.x.
612
+ *
613
+ * Pass either `dialect` (to auto-create a Kysely instance) or `kysely` (to reuse one).
614
+ * Passing a pre-existing Kysely instance avoids creating a second connection for
615
+ * migration runners or other tools that already have their own Kysely.
550
616
  */
551
617
  declare function createORM(config: ORMConfig): ORMLike & {
552
618
  kysely: Database;
@@ -596,6 +662,42 @@ declare function timestamps(opts?: {
596
662
  */
597
663
  declare function ulid(): Plugin;
598
664
  //#endregion
665
+ //#region src/relations/crud.d.ts
666
+ interface BelongsToOp {
667
+ create?: Record<string, unknown>;
668
+ connect?: Record<string, unknown>;
669
+ connectOrCreate?: {
670
+ where: Record<string, unknown>;
671
+ create: Record<string, unknown>;
672
+ };
673
+ update?: Record<string, unknown>;
674
+ upsert?: {
675
+ update: Record<string, unknown>;
676
+ create: Record<string, unknown>;
677
+ };
678
+ delete?: boolean;
679
+ disconnect?: boolean;
680
+ set?: Record<string, unknown>;
681
+ }
682
+ interface HasManyOp {
683
+ create?: Record<string, unknown>[];
684
+ connect?: (number | string | Record<string, unknown>)[];
685
+ set?: (number | string | Record<string, unknown>)[];
686
+ delete?: Record<string, unknown> | Record<string, unknown>[];
687
+ update?: {
688
+ where: Record<string, unknown> | Record<string, unknown>[];
689
+ data: Record<string, unknown>;
690
+ };
691
+ }
692
+ interface ManyToManyOp {
693
+ create?: Record<string, unknown>[];
694
+ connect?: (number | string | Record<string, unknown>)[];
695
+ disconnect?: Record<string, unknown> | Record<string, unknown>[];
696
+ set?: (number | string | Record<string, unknown>)[];
697
+ add?: (number | string | Record<string, unknown>)[];
698
+ }
699
+ type RelationData = BelongsToOp | HasManyOp | ManyToManyOp;
700
+ //#endregion
599
701
  //#region src/relations/has-many.d.ts
600
702
  declare function hasMany(relatedThunk: () => ModelDefinition, options?: RelationOptions): Relation;
601
703
  declare function hasOne(relatedThunk: () => ModelDefinition, options?: RelationOptions): Relation;
@@ -636,13 +738,6 @@ interface MorphManyOptions {
636
738
  */
637
739
  typeValue?: string;
638
740
  }
639
- interface MorphOneOptions {
640
- name: string;
641
- related: () => ModelDefinition;
642
- type?: string;
643
- id?: string;
644
- typeValue?: string;
645
- }
646
741
  /**
647
742
  * Resolve the related model for a MorphTo relation given a parent instance.
648
743
  * Looks up the parent's `{name}Type` column value in the relation's morphMap
@@ -683,9 +778,27 @@ declare function defineMorphTo(options: MorphToOptions): Relation;
683
778
  * The related table stores the parent's type and id.
684
779
  */
685
780
  declare function defineMorphMany(options: MorphManyOptions): Relation;
781
+ //#endregion
782
+ //#region src/repo/index.d.ts
783
+ type QueryMethod = (qb: QueryBuilder, ...args: any[]) => QueryBuilder;
784
+ interface RepoMethods {
785
+ queryMethods?: Record<string, QueryMethod>;
786
+ methods?: Record<string, (...args: any[]) => any>;
787
+ }
686
788
  /**
687
- * Define a polymorphic hasOne relationship.
789
+ * Create a repository a composable set of chainable query methods.
790
+ *
791
+ * ```ts
792
+ * const userRepo = createRepo(User, {
793
+ * queryMethods: {
794
+ * search(q, query: string) {
795
+ * return q.where('name', 'like', `%${query}%`)
796
+ * },
797
+ * },
798
+ * })
799
+ * const users = await userRepo.search('john').paginate(1, 20)
800
+ * ```
688
801
  */
689
- declare function defineMorphOne(options: MorphOneOptions): Relation;
802
+ declare function createRepo<TMethods extends RepoMethods>(model: ModelDefinition, methods: TMethods): Record<string, never>;
690
803
  //#endregion
691
- export { Attribute, type Collection, type Column, type ColumnShape, type ColumnTypes, type ColumnValue, type Constraint, DatabaseError, type DatabaseErrorCode, type HookCallback, type HookManager, type InsertGraphOptions, type LifecycleEvent, type ModelConfig, type ModelDefinition, type ModelId, type ModelInstance, ModelNotFoundError, ModelNotRegisteredError, type MorphManyOptions, type MorphOneOptions, type MorphToOptions, type ORMConfig, type ORMLike, type PaginatedResult, type Paginator, type PaginatorJson, type Plugin, type QueryBuilder, type Relation, RelationNotAllowedError, RelationNotFoundError, type RelationOptions, type RelationType, type SchemaConfig, type UpsertGraphOptions, ValidationError, belongsTo, createArkTypeSchemaConfig, createCollection, createColumn, createHookManager, createORM, createORM as createPeta, createPaginator, createQueryBuilder, defineModel, defineMorphMany, defineMorphOne, defineMorphTo, hasMany, hasManyThrough, hasOne, manyToMany, normalizeError, resolveMorphRelation, softDeletes, t, timestamps, ulid };
804
+ export { Attribute, type BelongsToOp, type Collection, type Column, type ColumnShape, type ColumnTypes, type ColumnValue, type Constraint, DatabaseError, type DatabaseErrorCode, type DeleteGraphOptions, type HasManyOp, type HookCallback, type HookManager, type InsertGraphOptions, type LifecycleEvent, type ManyToManyOp, type ModelConfig, type ModelDefinition, type ModelInstance, ModelNotFoundError, ModelNotRegisteredError, type MorphManyOptions, type MorphToOptions, type ORMConfig, type ORMLike, type Paginator, type PaginatorJson, type Plugin, type QueryBuilder, type QueryMethod, type Relation, type RelationData, RelationNotAllowedError, RelationNotFoundError, type RelationOptions, type RelationType, type RepoMethods, type SchemaConfig, type SerializedShape, type UpsertGraphOptions, ValidationError, belongsTo, createArkTypeSchemaConfig, createCollection, createColumn, createColumnTypes, createDb, createHookManager, createORM, createORM as createPeta, createPaginator, createQueryBuilder, createRepo, defineModel, defineMorphMany, defineMorphTo, deleteGraph, hasMany, hasManyThrough, hasOne, manyToMany, normalizeError, petaMiddleware, petaPlugin, resolveMorphRelation, softDeletes, t, timestamps, ulid };