peta-orm 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -10
- package/dist/index.d.mts +576 -5
- package/dist/index.mjs +147 -6
- package/package.json +4 -11
- package/bin/peta +0 -3
- package/dist/index-BdJnSMYi.d.mts +0 -480
- package/dist/migrations/cli.d.mts +0 -4
- package/dist/migrations/cli.mjs +0 -74
- package/dist/migrations/index.d.mts +0 -53
- package/dist/migrations/index.mjs +0 -2
- package/dist/runner-DQ7uT6LC.mjs +0 -180
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,493 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Dialect } from "kysely";
|
|
1
|
+
import { Dialect, Kysely } from "kysely";
|
|
3
2
|
|
|
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/lib/kysely.d.ts
|
|
44
|
+
type Database = Kysely<Record<string, never>>;
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/pagination/index.d.ts
|
|
47
|
+
interface Paginator<TColumns extends ColumnShape = ColumnShape> {
|
|
48
|
+
readonly data: Collection<TColumns>;
|
|
49
|
+
readonly total: number;
|
|
50
|
+
readonly perPage: number;
|
|
51
|
+
readonly currentPage: number;
|
|
52
|
+
readonly lastPage: number;
|
|
53
|
+
readonly hasMorePages: boolean;
|
|
54
|
+
readonly hasPages: boolean;
|
|
55
|
+
readonly firstItem: number;
|
|
56
|
+
readonly lastItem: number;
|
|
57
|
+
readonly onFirstPage: boolean;
|
|
58
|
+
readonly onLastPage: boolean;
|
|
59
|
+
readonly count: number;
|
|
60
|
+
map<T>(fn: (item: ModelInstance<TColumns>) => T): T[];
|
|
61
|
+
toJSON(): PaginatorJson<TColumns>;
|
|
62
|
+
}
|
|
63
|
+
interface PaginatorJson<TColumns extends ColumnShape = ColumnShape> {
|
|
64
|
+
data: SerializedShape<TColumns>[];
|
|
65
|
+
total: number;
|
|
66
|
+
perPage: number;
|
|
67
|
+
currentPage: number;
|
|
68
|
+
lastPage: number;
|
|
69
|
+
hasMorePages: boolean;
|
|
70
|
+
hasPages: boolean;
|
|
71
|
+
firstItem: number | null;
|
|
72
|
+
lastItem: number | null;
|
|
73
|
+
onFirstPage: boolean;
|
|
74
|
+
onLastPage: boolean;
|
|
75
|
+
}
|
|
76
|
+
type PaginatedResult = PaginatorJson;
|
|
77
|
+
declare function createPaginator<TColumns extends ColumnShape = ColumnShape>(items: ModelInstance<TColumns>[], total: number, perPage: number, currentPage: number): Paginator<TColumns>;
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/relations/base.d.ts
|
|
80
|
+
type RelationType = "hasMany" | "belongsTo" | "hasOne" | "manyToMany" | "hasManyThrough";
|
|
81
|
+
interface RelationOptions {
|
|
82
|
+
foreignKey?: string;
|
|
83
|
+
localKey?: string;
|
|
84
|
+
through?: string;
|
|
85
|
+
foreignPivotKey?: string;
|
|
86
|
+
relatedPivotKey?: string;
|
|
87
|
+
throughForeignKey?: string;
|
|
88
|
+
throughLocalKey?: string;
|
|
89
|
+
pivotExtras?: string[];
|
|
90
|
+
}
|
|
91
|
+
interface Relation {
|
|
92
|
+
readonly type: RelationType;
|
|
93
|
+
readonly relatedModelClass: ModelDefinition;
|
|
94
|
+
readonly foreignKey: string;
|
|
95
|
+
readonly localKey: string;
|
|
96
|
+
readonly throughTable?: string;
|
|
97
|
+
readonly foreignPivotKey?: string;
|
|
98
|
+
readonly relatedPivotKey?: string;
|
|
99
|
+
readonly throughForeignKey?: string;
|
|
100
|
+
readonly throughLocalKey?: string;
|
|
101
|
+
_morphMap?: Record<string, () => ModelDefinition>;
|
|
102
|
+
_morphType?: string;
|
|
103
|
+
_morphId?: string;
|
|
104
|
+
_morphTypeValue?: string;
|
|
105
|
+
query(parent: ModelInstance): QueryBuilder;
|
|
106
|
+
addEagerConstraints(query: QueryBuilder, models: ModelInstance[]): void;
|
|
107
|
+
match(models: ModelInstance[], results: ModelInstance[], relationName: string): void;
|
|
108
|
+
getResults(parent: ModelInstance): Promise<ModelInstance | ModelInstance[] | null>;
|
|
109
|
+
loadEager(models: ModelInstance[], relationName: string, constraints?: ((qb: QueryBuilder) => void) | null): Promise<void>;
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/relations/graph/types.d.ts
|
|
113
|
+
interface InsertGraphOptions {
|
|
114
|
+
/** Allow `#id` / `#ref` special properties in the graph */
|
|
115
|
+
allowRefs?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* If `true`, objects with an `id` property get related (pivot row / FK set)
|
|
118
|
+
* instead of inserted. Can be an array of relation names to scope.
|
|
119
|
+
*/
|
|
120
|
+
relate?: boolean | string[];
|
|
121
|
+
/**
|
|
122
|
+
* Whitelist of relation paths allowed for this graph operation.
|
|
123
|
+
* Accepts an array of dotted paths or a Set. If not set, all relations are allowed.
|
|
124
|
+
* When used via the query builder, the QB's `allowGraph()` set is forwarded automatically.
|
|
125
|
+
*/
|
|
126
|
+
allowGraph?: string[] | Set<string>;
|
|
127
|
+
}
|
|
128
|
+
interface UpsertGraphOptions extends InsertGraphOptions {
|
|
129
|
+
/** Unrelate (set FK null / remove pivot) instead of deleting missing items */
|
|
130
|
+
unrelate?: boolean | string[];
|
|
131
|
+
/** Prevent deletion for all or specific relation paths */
|
|
132
|
+
noDelete?: boolean | string[];
|
|
133
|
+
/** Prevent insertion for all or specific relation paths */
|
|
134
|
+
noInsert?: boolean | string[];
|
|
135
|
+
/** Prevent update for all or specific relation paths */
|
|
136
|
+
noUpdate?: boolean | string[];
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/query/types.d.ts
|
|
140
|
+
interface QueryBuilder<TColumns extends ColumnShape = ColumnShape> extends PromiseLike<ModelInstance<TColumns>[]> {
|
|
141
|
+
execute(): Promise<ModelInstance<TColumns>[]>;
|
|
142
|
+
collect(): Promise<Collection<TColumns>>;
|
|
143
|
+
executeTakeFirst(): Promise<ModelInstance<TColumns> | undefined>;
|
|
144
|
+
executeTakeFirstOrThrow(): Promise<ModelInstance<TColumns>>;
|
|
145
|
+
find(id: number | string): Promise<ModelInstance<TColumns> | undefined>;
|
|
146
|
+
findOrFail(id: number | string): Promise<ModelInstance<TColumns>>;
|
|
147
|
+
first(): Promise<ModelInstance<TColumns> | undefined>;
|
|
148
|
+
toSQL(): {
|
|
149
|
+
sql: string;
|
|
150
|
+
parameters: readonly unknown[];
|
|
151
|
+
};
|
|
152
|
+
count(): Promise<number>;
|
|
153
|
+
sum(column: string): Promise<number>;
|
|
154
|
+
avg(column: string): Promise<number>;
|
|
155
|
+
min(column: string): Promise<number>;
|
|
156
|
+
max(column: string): Promise<number>;
|
|
157
|
+
withCount(relation: string): QueryBuilder<TColumns>;
|
|
158
|
+
withSum(relation: string, column: string): QueryBuilder<TColumns>;
|
|
159
|
+
withAvg(relation: string, column: string): QueryBuilder<TColumns>;
|
|
160
|
+
withMin(relation: string, column: string): QueryBuilder<TColumns>;
|
|
161
|
+
withMax(relation: string, column: string): QueryBuilder<TColumns>;
|
|
162
|
+
withExists(relation: string): QueryBuilder<TColumns>;
|
|
163
|
+
chunk(size: number, callback: (chunk: ModelInstance<TColumns>[]) => Promise<void>): Promise<void>;
|
|
164
|
+
paginate(page: number, perPage?: number): Promise<Paginator<TColumns>>;
|
|
165
|
+
insertGraph(data: Record<string, unknown> | Record<string, unknown>[], options?: InsertGraphOptions): Promise<any>;
|
|
166
|
+
upsertGraph(data: Record<string, unknown> | Record<string, unknown>[], options?: UpsertGraphOptions): Promise<any>;
|
|
167
|
+
with(...relations: (string | Record<string, (qb: QueryBuilder<TColumns>) => void>)[]): QueryBuilder<TColumns>;
|
|
168
|
+
/**
|
|
169
|
+
* Whitelist allowed relations (and nested paths) for eager loading.
|
|
170
|
+
* Throws if a relation path is not in the allow list.
|
|
171
|
+
*
|
|
172
|
+
* Supports dotted paths for granular control:
|
|
173
|
+
* - `allowGraph("posts")` allows `posts`, `posts.author`, `posts.author.profile`, etc.
|
|
174
|
+
* - `allowGraph("posts.author")` allows `posts.author` and `posts.author.profile`,
|
|
175
|
+
* but NOT bare `posts` or `posts.comments`.
|
|
176
|
+
*
|
|
177
|
+
* Multiple arguments are merged: `allowGraph("posts", "profile")`
|
|
178
|
+
*/
|
|
179
|
+
allowGraph(...expressions: string[]): QueryBuilder<TColumns>;
|
|
180
|
+
updateMany(data: Record<string, unknown>): Promise<number>;
|
|
181
|
+
deleteMany(): Promise<number>;
|
|
182
|
+
withTrashed(): QueryBuilder<TColumns>;
|
|
183
|
+
onlyTrashed(): QueryBuilder<TColumns>;
|
|
184
|
+
whereIn(column: string, values: unknown[]): QueryBuilder<TColumns>;
|
|
185
|
+
whereInPivot(column: string, values: unknown[]): QueryBuilder<TColumns>;
|
|
186
|
+
has(relationName: string): QueryBuilder<TColumns>;
|
|
187
|
+
whereHas(relationName: string, callback?: (qb: QueryBuilder<TColumns>) => void): QueryBuilder<TColumns>;
|
|
188
|
+
whereDoesntHave(relationName: string, callback?: (qb: QueryBuilder<TColumns>) => void): QueryBuilder<TColumns>;
|
|
189
|
+
where(column: string, operator: unknown, value?: unknown): QueryBuilder<TColumns>;
|
|
190
|
+
whereRef(col1: string, operator: string, col2: string): QueryBuilder<TColumns>;
|
|
191
|
+
orWhere(column: string, operator: unknown, value?: unknown): QueryBuilder<TColumns>;
|
|
192
|
+
orderBy(column: string, direction?: "asc" | "desc"): QueryBuilder<TColumns>;
|
|
193
|
+
limit(n: number): QueryBuilder<TColumns>;
|
|
194
|
+
offset(n: number): QueryBuilder<TColumns>;
|
|
195
|
+
select(...columns: string[]): QueryBuilder<TColumns>;
|
|
196
|
+
selectAll(table?: string): QueryBuilder<TColumns>;
|
|
197
|
+
innerJoin(table: string, lhs: string, rhs: string): QueryBuilder<TColumns>;
|
|
198
|
+
leftJoin(table: string, lhs: string, rhs: string): QueryBuilder<TColumns>;
|
|
199
|
+
groupBy(...columns: string[]): QueryBuilder<TColumns>;
|
|
200
|
+
having(column: string, operator: string, value: unknown): QueryBuilder<TColumns>;
|
|
201
|
+
withoutGlobalScope(name: string): QueryBuilder<TColumns>;
|
|
202
|
+
all(): QueryBuilder<TColumns>;
|
|
203
|
+
/** @internal Access underlying Kysely builder for raw SQL operations */
|
|
204
|
+
_getKyselyQb(): any;
|
|
205
|
+
/** @internal Replace the underlying Kysely builder */
|
|
206
|
+
_replaceKyselyQb(newQb: any): void;
|
|
207
|
+
when(condition: unknown, callback: (q: QueryBuilder<TColumns>) => QueryBuilder<TColumns>): QueryBuilder<TColumns>;
|
|
208
|
+
unless(condition: unknown, callback: (q: QueryBuilder<TColumns>) => QueryBuilder<TColumns>): QueryBuilder<TColumns>;
|
|
209
|
+
}
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/query/builder.d.ts
|
|
212
|
+
declare function createQueryBuilder<TColumns extends ColumnShape = ColumnShape>(def: ModelDefinition<TColumns>, peta?: {
|
|
213
|
+
kysely: Database;
|
|
214
|
+
}): QueryBuilder<TColumns>;
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region src/relations/related-query.d.ts
|
|
217
|
+
interface RelationQuery extends QueryBuilder {
|
|
218
|
+
/** Attach related model(s) for many-to-many relations. */
|
|
219
|
+
attach(ids: number | number[] | string | string[], pivotData?: Record<string, unknown>): Promise<void>;
|
|
220
|
+
/** Detach related model(s) for many-to-many relations. */
|
|
221
|
+
detach(ids?: number | number[] | string | string[]): Promise<void>;
|
|
222
|
+
/** Sync related models: attaches new IDs, detaches missing ones. */
|
|
223
|
+
sync(ids: (number | string)[] | Record<number | string, Record<string, unknown>>): Promise<void>;
|
|
224
|
+
/** Sync without detaching existing IDs. */
|
|
225
|
+
syncWithoutDetaching(ids: (number | string)[]): Promise<void>;
|
|
226
|
+
/** Update pivot data for a specific related model. */
|
|
227
|
+
updateExistingPivot(id: number | string, data: Record<string, unknown>): Promise<void>;
|
|
228
|
+
}
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region src/plugins/index.d.ts
|
|
231
|
+
/**
|
|
232
|
+
* A plugin is a function that receives a model definition and can
|
|
233
|
+
* modify it by adding hooks, scopes, columns, or methods.
|
|
234
|
+
*
|
|
235
|
+
* ```ts
|
|
236
|
+
* const myPlugin = (options?: MyOptions): Plugin =>
|
|
237
|
+
* (def) => {
|
|
238
|
+
* def.addGlobalScope?.('active', (q) => q.where('active', true))
|
|
239
|
+
* return def
|
|
240
|
+
* }
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
243
|
+
type Plugin = (def: ModelDefinition) => undefined | ModelDefinition;
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/types.d.ts
|
|
246
|
+
type ModelId = number & {
|
|
247
|
+
readonly __brand: "ModelId";
|
|
248
|
+
};
|
|
249
|
+
interface ModelLike<TColumns extends ColumnShape = ColumnShape> {
|
|
250
|
+
get<K extends keyof TColumns>(key: K): ColumnValue<TColumns[K]>;
|
|
251
|
+
get(key: string): unknown;
|
|
252
|
+
set(key: string, value: unknown): void;
|
|
253
|
+
}
|
|
254
|
+
interface ORMLike {
|
|
255
|
+
readonly kysely: Database;
|
|
256
|
+
register(model: ModelDefinition$1<any>): void;
|
|
257
|
+
registerAll(...models: (ModelDefinition$1<any> | ModelDefinition$1<any>[])[]): void;
|
|
258
|
+
destroy(): Promise<void>;
|
|
259
|
+
transaction<T>(fn: (trx: import("kysely").Kysely<Record<string, never>>) => Promise<T>): Promise<T>;
|
|
260
|
+
readonly models: ReadonlyMap<string, ModelDefinition$1<any>>;
|
|
261
|
+
getModel<T extends ColumnShape = ColumnShape>(name: string): ModelDefinition$1<T> | undefined;
|
|
262
|
+
/**
|
|
263
|
+
* Discover model definitions by scanning files matching a glob pattern.
|
|
264
|
+
*
|
|
265
|
+
* Uses `fast-glob` to resolve the pattern relative to `cwd`, then dynamically
|
|
266
|
+
* imports each matching file and collects exported `ModelDefinition` values.
|
|
267
|
+
* Does **not** auto-register — use `registerAll(...result)` to register them.
|
|
268
|
+
*
|
|
269
|
+
* @param pattern Glob pattern (e.g. `"./src/models/**\/*.ts"`)
|
|
270
|
+
* @returns Array of discovered model definitions
|
|
271
|
+
*/
|
|
272
|
+
discover(pattern: string): Promise<ModelDefinition$1<any>[]>;
|
|
273
|
+
}
|
|
274
|
+
interface ModelDefinition$1<TColumns extends ColumnShape = ColumnShape> {
|
|
275
|
+
readonly table: string;
|
|
276
|
+
readonly columns: TColumns;
|
|
277
|
+
readonly relations: Record<string, Relation>;
|
|
278
|
+
readonly name: string;
|
|
279
|
+
_orm: ORMLike | null;
|
|
280
|
+
query(): QueryBuilder<TColumns>;
|
|
281
|
+
find(id: number | string): Promise<ModelInstance<TColumns> | undefined>;
|
|
282
|
+
findOrFail(id: number | string): Promise<ModelInstance<TColumns>>;
|
|
283
|
+
first(): Promise<ModelInstance<TColumns> | undefined>;
|
|
284
|
+
create(data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
|
|
285
|
+
insert(data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
|
|
286
|
+
insertMany(dataArray: Record<string, unknown>[]): Promise<ModelInstance<TColumns>[]>;
|
|
287
|
+
update(id: number | string, data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
|
|
288
|
+
delete(id: number | string): Promise<void>;
|
|
289
|
+
hydrate(row: Record<string, unknown>): ModelInstance<TColumns>;
|
|
290
|
+
on(event: string, callback: (model: ModelInstance<TColumns>) => void | Promise<void>): () => void;
|
|
291
|
+
getHooks(): HookManager;
|
|
292
|
+
addGlobalScope(name: string, callback: (qb: QueryBuilder) => void): void;
|
|
293
|
+
removeGlobalScope(name: string): void;
|
|
294
|
+
getGlobalScopes(): Map<string, (qb: QueryBuilder) => void> | undefined;
|
|
295
|
+
_init(orm: ORMLike): void;
|
|
296
|
+
}
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/hooks/index.d.ts
|
|
299
|
+
type LifecycleEvent = "beforeCreate" | "afterCreate" | "beforeUpdate" | "afterUpdate" | "beforeSave" | "afterSave" | "beforeDelete" | "afterDelete" | "beforeRestore" | "afterRestore" | "beforeForceDelete" | "afterForceDelete";
|
|
300
|
+
type HookCallback = (model: ModelLike) => void | Promise<void>;
|
|
301
|
+
interface HookManager {
|
|
302
|
+
on(event: LifecycleEvent, callback: HookCallback): () => void;
|
|
303
|
+
off(event: LifecycleEvent, callback: HookCallback): void;
|
|
304
|
+
trigger(event: LifecycleEvent, model: ModelLike): Promise<void>;
|
|
305
|
+
clone(): HookManager;
|
|
306
|
+
}
|
|
307
|
+
declare function createHookManager(): HookManager;
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region src/hooks/static.d.ts
|
|
310
|
+
interface StaticHookArgs {
|
|
311
|
+
/** Transform the mutating query into a SELECT to preview affected rows */
|
|
312
|
+
asFindQuery(): QueryBuilder;
|
|
313
|
+
/** Cancel the mutation and return a custom result */
|
|
314
|
+
cancelQuery(result: unknown): void;
|
|
315
|
+
/** The column data being inserted/updated (for create/update hooks) */
|
|
316
|
+
inputItems?: Record<string, unknown>[];
|
|
317
|
+
}
|
|
318
|
+
type StaticHookCallback = (args: StaticHookArgs) => void | Promise<void>;
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region src/model/computed.d.ts
|
|
321
|
+
interface ComputedColumn<T = unknown> {
|
|
322
|
+
readonly type: "sql" | "runtime" | "batch";
|
|
323
|
+
readonly dependencies: string[];
|
|
324
|
+
/** Compute a value for a single record (runtime) */
|
|
325
|
+
compute?: (record: ModelInstance) => T;
|
|
326
|
+
/** Compute values for a batch of records (batch async) */
|
|
327
|
+
batchCompute?: (records: ModelInstance[]) => Promise<T[]>;
|
|
328
|
+
/** Raw SQL expression to inline in SELECT */
|
|
329
|
+
sql?: string;
|
|
330
|
+
}
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region src/model/attribute.d.ts
|
|
333
|
+
/**
|
|
334
|
+
* Defines an accessor (`get`) and/or mutator (`set`) for a model attribute.
|
|
335
|
+
*
|
|
336
|
+
* ### Accessor (get)
|
|
337
|
+
* Transforms the attribute value when read via `model.get()` or `model.$toJSON()`.
|
|
338
|
+
* Receives the casted value and the model instance.
|
|
339
|
+
*
|
|
340
|
+
* ### Mutator (set)
|
|
341
|
+
* Transforms the attribute value when written via `model.set()`, `model.fill()`,
|
|
342
|
+
* or during model creation (`Model.insert()` / `Model.create()`).
|
|
343
|
+
* Receives the raw input value and the model instance, returns the value to store.
|
|
344
|
+
* Applied **before** type casting.
|
|
345
|
+
*
|
|
346
|
+
* ### Usage
|
|
347
|
+
* ```ts
|
|
348
|
+
* defineModel('users', {
|
|
349
|
+
* columns: { id, name, password, ... },
|
|
350
|
+
* attributes: {
|
|
351
|
+
* password: Attribute.make({
|
|
352
|
+
* set: (value) => Bun.password.hashSync(value, { algorithm: 'bcrypt' }),
|
|
353
|
+
* get: () => '***',
|
|
354
|
+
* }),
|
|
355
|
+
* fullName: Attribute.make({
|
|
356
|
+
* get: (_, instance) => `${instance.get('firstName')} ${instance.get('lastName')}`,
|
|
357
|
+
* }),
|
|
358
|
+
* },
|
|
359
|
+
* })
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
declare class Attribute<T = any> {
|
|
363
|
+
readonly get?: ((value: T, instance: ModelInstance) => any) | undefined;
|
|
364
|
+
readonly set?: ((value: any, instance: ModelInstance) => T) | undefined;
|
|
365
|
+
private constructor();
|
|
366
|
+
static make<T = any>(config: {
|
|
367
|
+
/** Transform the attribute value when read. Receives (castedValue, instance). */get?: (value: T, instance: ModelInstance) => any; /** Transform the attribute value when written. Receives (rawValue, instance), returns value to store. */
|
|
368
|
+
set?: (value: any, instance: ModelInstance) => T;
|
|
369
|
+
}): Attribute<T>;
|
|
370
|
+
}
|
|
371
|
+
//#endregion
|
|
372
|
+
//#region src/model/types.d.ts
|
|
373
|
+
/** Mapped column shape — resolves each column to its JS value type for $toJSON(). */
|
|
374
|
+
type SerializedShape<TColumns extends ColumnShape> = { [K in keyof TColumns]: TColumns[K] extends Column<infer T> ? T : unknown } & Record<string, unknown>;
|
|
375
|
+
interface ModelInstance<TColumns extends ColumnShape = ColumnShape> {
|
|
376
|
+
readonly exists: boolean;
|
|
377
|
+
readonly attributes: Record<string, unknown>;
|
|
378
|
+
readonly dirtyAttributes: Record<string, unknown>;
|
|
379
|
+
isDirty(key?: string): boolean;
|
|
380
|
+
get<K extends keyof TColumns>(key: K): ColumnValue<TColumns[K]>;
|
|
381
|
+
get(key: string): unknown;
|
|
382
|
+
set(key: string, value: unknown): void;
|
|
383
|
+
fill(data: Record<string, unknown>): void;
|
|
384
|
+
reset(): void;
|
|
385
|
+
$getRelation<T = unknown>(name: string): T;
|
|
386
|
+
$setRelation(name: string, value: unknown): void;
|
|
387
|
+
$hasRelation(name: string): boolean;
|
|
388
|
+
$relationData(): Record<string, unknown>;
|
|
389
|
+
$load(...relations: string[]): Promise<void>;
|
|
390
|
+
$related(name: string): RelationQuery;
|
|
391
|
+
$save(): Promise<this>;
|
|
392
|
+
$delete(): Promise<void>;
|
|
393
|
+
$forceDelete(): Promise<void>;
|
|
394
|
+
$restore(): Promise<void>;
|
|
395
|
+
$trashed(): boolean;
|
|
396
|
+
$reload(): Promise<void>;
|
|
397
|
+
$toJSON(): SerializedShape<TColumns>;
|
|
398
|
+
toJSON(): SerializedShape<TColumns>;
|
|
399
|
+
}
|
|
400
|
+
interface ModelDefinition<TColumns extends ColumnShape = ColumnShape> {
|
|
401
|
+
readonly table: string;
|
|
402
|
+
readonly columns: TColumns;
|
|
403
|
+
readonly relations: Record<string, Relation>;
|
|
404
|
+
readonly name: string;
|
|
405
|
+
_orm: ORMLike | null;
|
|
406
|
+
query(): QueryBuilder<TColumns>;
|
|
407
|
+
find(id: number | string): Promise<ModelInstance<TColumns> | undefined>;
|
|
408
|
+
findOrFail(id: number | string): Promise<ModelInstance<TColumns>>;
|
|
409
|
+
first(): Promise<ModelInstance<TColumns> | undefined>;
|
|
410
|
+
create(data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
|
|
411
|
+
insert(data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
|
|
412
|
+
insertMany(dataArray: Record<string, unknown>[]): Promise<ModelInstance<TColumns>[]>;
|
|
413
|
+
update(id: number | string, data: Record<string, unknown>): Promise<ModelInstance<TColumns>>;
|
|
414
|
+
delete(id: number | string): Promise<void>;
|
|
415
|
+
insertGraph(data: Record<string, unknown> | Record<string, unknown>[], options?: InsertGraphOptions): Promise<any>;
|
|
416
|
+
upsertGraph(data: Record<string, unknown> | Record<string, unknown>[], options?: UpsertGraphOptions): Promise<any>;
|
|
417
|
+
hydrate(row: Record<string, unknown>): ModelInstance<TColumns>;
|
|
418
|
+
use(plugin: Plugin): ModelDefinition<TColumns>;
|
|
419
|
+
makeHelper<A extends any[], R>(fn: (qb: QueryBuilder, ...args: A) => R): (...args: A) => R;
|
|
420
|
+
on(event: string, callback: (model: ModelInstance<TColumns>) => void | Promise<void>): () => void;
|
|
421
|
+
getHooks(): HookManager;
|
|
422
|
+
beforeDelete(callback: StaticHookCallback): () => void;
|
|
423
|
+
afterDelete(callback: StaticHookCallback): () => void;
|
|
424
|
+
beforeUpdate(callback: StaticHookCallback): () => void;
|
|
425
|
+
afterUpdate(callback: StaticHookCallback): () => void;
|
|
426
|
+
beforeCreate(callback: StaticHookCallback): () => void;
|
|
427
|
+
afterCreate(callback: StaticHookCallback): () => void;
|
|
428
|
+
beforeFind(callback: StaticHookCallback): () => void;
|
|
429
|
+
afterFind(callback: StaticHookCallback): () => void;
|
|
430
|
+
addGlobalScope(name: string, callback: (qb: QueryBuilder) => void): void;
|
|
431
|
+
removeGlobalScope(name: string): void;
|
|
432
|
+
getGlobalScopes(): Map<string, (qb: QueryBuilder) => void> | undefined;
|
|
433
|
+
registerTimestamps?(createdAtCol?: string, updatedAtCol?: string): void;
|
|
434
|
+
registerSoftDeletes?(deletedAtCol?: string): void;
|
|
435
|
+
_init(orm: ORMLike): void;
|
|
436
|
+
}
|
|
437
|
+
interface ModelConfig<TColumns extends ColumnShape = ColumnShape> {
|
|
438
|
+
columns: TColumns;
|
|
439
|
+
relations?: Record<string, Relation>;
|
|
440
|
+
casts?: Record<string, string>;
|
|
441
|
+
/** Per-attribute accessors (`get`) and/or mutators (`set`). See {@link Attribute.make}. */
|
|
442
|
+
attributes?: Record<string, Attribute<any>>;
|
|
443
|
+
hidden?: string[];
|
|
444
|
+
visible?: string[];
|
|
445
|
+
appends?: string[];
|
|
446
|
+
computed?: Record<string, ComputedColumn>;
|
|
447
|
+
}
|
|
448
|
+
//#endregion
|
|
449
|
+
//#region src/collection/index.d.ts
|
|
450
|
+
interface Collection<TColumns extends ColumnShape = ColumnShape> {
|
|
451
|
+
readonly length: number;
|
|
452
|
+
[Symbol.iterator](): Iterator<ModelInstance<TColumns>>;
|
|
453
|
+
at(index: number): ModelInstance<TColumns> | undefined;
|
|
454
|
+
first(): ModelInstance<TColumns> | undefined;
|
|
455
|
+
last(): ModelInstance<TColumns> | undefined;
|
|
456
|
+
all(): ModelInstance<TColumns>[];
|
|
457
|
+
findBy(id: number | string): ModelInstance<TColumns> | undefined;
|
|
458
|
+
find(callback: (item: ModelInstance<TColumns>, index: number) => boolean): ModelInstance<TColumns> | undefined;
|
|
459
|
+
some(callback: (item: ModelInstance<TColumns>, index: number) => boolean): boolean;
|
|
460
|
+
includes(item: ModelInstance<TColumns>): boolean;
|
|
461
|
+
isEmpty(): boolean;
|
|
462
|
+
isNotEmpty(): boolean;
|
|
463
|
+
get(key: string): unknown[];
|
|
464
|
+
pluck(key: string): unknown[];
|
|
465
|
+
groupBy(key: string): Record<string, ModelInstance<TColumns>[]>;
|
|
466
|
+
keyBy(key: string): Record<string, ModelInstance<TColumns>>;
|
|
467
|
+
map<T>(fn: (item: ModelInstance<TColumns>, index: number) => T): T[];
|
|
468
|
+
filter(fn: (item: ModelInstance<TColumns>, index: number) => boolean): Collection<TColumns>;
|
|
469
|
+
reduce<T>(fn: (acc: T, item: ModelInstance<TColumns>, index: number) => T, initial: T): T;
|
|
470
|
+
forEach(fn: (item: ModelInstance<TColumns>, index: number) => void): void;
|
|
471
|
+
each(fn: (item: ModelInstance<TColumns>, index: number) => void): Collection<TColumns>;
|
|
472
|
+
unique(key?: string): Collection<TColumns>;
|
|
473
|
+
sortBy(key: string, direction?: "asc" | "desc"): Collection<TColumns>;
|
|
474
|
+
shuffle(): Collection<TColumns>;
|
|
475
|
+
take(n: number): Collection<TColumns>;
|
|
476
|
+
skip(n: number): Collection<TColumns>;
|
|
477
|
+
chunk(size: number): Collection<TColumns>[];
|
|
478
|
+
sum(key: string): number;
|
|
479
|
+
avg(key: string): number;
|
|
480
|
+
min(key: string): number;
|
|
481
|
+
max(key: string): number;
|
|
482
|
+
diff(other: Collection<TColumns>): Collection<TColumns>;
|
|
483
|
+
intersect(other: Collection<TColumns>): Collection<TColumns>;
|
|
484
|
+
concat(other: Collection<TColumns>): Collection<TColumns>;
|
|
485
|
+
push(...items: ModelInstance<TColumns>[]): void;
|
|
486
|
+
load(...relations: string[]): Promise<Collection<TColumns>>;
|
|
487
|
+
toJSON(): SerializedShape<TColumns>[];
|
|
488
|
+
}
|
|
489
|
+
declare function createCollection<TColumns extends ColumnShape = ColumnShape>(items?: ModelInstance<TColumns>[]): Collection<TColumns>;
|
|
490
|
+
//#endregion
|
|
4
491
|
//#region src/columns/arktype.d.ts
|
|
5
492
|
declare function createArkTypeSchemaConfig(): SchemaConfig;
|
|
6
493
|
//#endregion
|
|
@@ -26,7 +513,27 @@ interface ColumnTypes {
|
|
|
26
513
|
updatedAt: Column<string>;
|
|
27
514
|
};
|
|
28
515
|
}
|
|
29
|
-
|
|
516
|
+
/**
|
|
517
|
+
* Pre-configured column type factory backed by ArkType validation.
|
|
518
|
+
*
|
|
519
|
+
* The most common usage — just import and use:
|
|
520
|
+
* ```ts
|
|
521
|
+
* import { t } from "peta-orm"
|
|
522
|
+
* const id = t.integer().primaryKey()
|
|
523
|
+
* ```
|
|
524
|
+
*
|
|
525
|
+
* For a custom validation backend, use `createColumnTypes({ schema })` instead.
|
|
526
|
+
*/
|
|
527
|
+
declare const t: ColumnTypes;
|
|
528
|
+
/**
|
|
529
|
+
* Create a column type factory with a custom validation schema backend.
|
|
530
|
+
*
|
|
531
|
+
* @example
|
|
532
|
+
* ```ts
|
|
533
|
+
* const t = createColumnTypes({ schema: myCustomSchemaConfig })
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
declare function createColumnTypes(config: {
|
|
30
537
|
schema: SchemaConfig;
|
|
31
538
|
}): ColumnTypes;
|
|
32
539
|
//#endregion
|
|
@@ -63,14 +570,56 @@ declare class DatabaseError extends Error {
|
|
|
63
570
|
//#region src/errors/normalizer.d.ts
|
|
64
571
|
declare function normalizeError(e: unknown, table?: string): DatabaseError;
|
|
65
572
|
//#endregion
|
|
573
|
+
//#region src/init.d.ts
|
|
574
|
+
/**
|
|
575
|
+
* Create a lazy-initialized singleton factory.
|
|
576
|
+
*
|
|
577
|
+
* The factory function is called only once — on the first call to the returned
|
|
578
|
+
* function. Subsequent calls return the same resolved promise. This avoids
|
|
579
|
+
* module-level side effects: importing a model file won't trigger database
|
|
580
|
+
* connection or schema initialization until the first explicit `await db()`.
|
|
581
|
+
*
|
|
582
|
+
* @example
|
|
583
|
+
* ```ts
|
|
584
|
+
* import { createClient } from "@libsql/client"
|
|
585
|
+
* import { LibsqlDialect } from "@libsql/kysely-libsql"
|
|
586
|
+
* import { createDb, createORM, defineModel, t } from "peta-orm"
|
|
587
|
+
*
|
|
588
|
+
* const User = defineModel("users", { columns: { ... } })
|
|
589
|
+
*
|
|
590
|
+
* async function setup() {
|
|
591
|
+
* const client = createClient({ url: "file:my-app.db" })
|
|
592
|
+
* await client.execute("CREATE TABLE IF NOT EXISTS users (...)") // schema init
|
|
593
|
+
* const orm = createORM({ dialect: new LibsqlDialect({ client }) })
|
|
594
|
+
* orm.registerAll(User)
|
|
595
|
+
* return orm
|
|
596
|
+
* }
|
|
597
|
+
*
|
|
598
|
+
* export const db = createDb(setup)
|
|
599
|
+
* // Usage: const orm = await db()
|
|
600
|
+
* ```
|
|
601
|
+
*/
|
|
602
|
+
declare function createDb<T>(factory: () => Promise<T>): () => Promise<T>;
|
|
603
|
+
//#endregion
|
|
604
|
+
//#region src/model/define.d.ts
|
|
605
|
+
declare function defineModel<TColumns extends ColumnShape>(table: string, config: ModelConfig<TColumns>): ModelDefinition<TColumns>;
|
|
606
|
+
//#endregion
|
|
66
607
|
//#region src/orm/index.d.ts
|
|
67
608
|
interface ORMConfig {
|
|
68
|
-
dialect
|
|
609
|
+
/** Kysely dialect to create an internal Kysely instance. Required unless `kysely` is provided. */
|
|
610
|
+
dialect?: Dialect;
|
|
611
|
+
/** A pre-existing Kysely instance to reuse. Required unless `dialect` is provided. */
|
|
612
|
+
kysely?: Kysely<any>;
|
|
613
|
+
/** Optional map of model definitions to register immediately. */
|
|
69
614
|
models?: Record<string, ModelDefinition>;
|
|
70
615
|
}
|
|
71
616
|
/**
|
|
72
617
|
* Create an ORM instance — the central registry that wires Kysely to model definitions.
|
|
73
618
|
* Replaces createPeta() from v0.x.
|
|
619
|
+
*
|
|
620
|
+
* Pass either `dialect` (to auto-create a Kysely instance) or `kysely` (to reuse one).
|
|
621
|
+
* Passing a pre-existing Kysely instance avoids creating a second connection for
|
|
622
|
+
* migration runners or other tools that already have their own Kysely.
|
|
74
623
|
*/
|
|
75
624
|
declare function createORM(config: ORMConfig): ORMLike & {
|
|
76
625
|
kysely: Database;
|
|
@@ -212,4 +761,26 @@ declare function defineMorphMany(options: MorphManyOptions): Relation;
|
|
|
212
761
|
*/
|
|
213
762
|
declare function defineMorphOne(options: MorphOneOptions): Relation;
|
|
214
763
|
//#endregion
|
|
215
|
-
|
|
764
|
+
//#region src/repo/index.d.ts
|
|
765
|
+
type QueryMethod = (qb: QueryBuilder, ...args: any[]) => QueryBuilder;
|
|
766
|
+
interface RepoMethods {
|
|
767
|
+
queryMethods?: Record<string, QueryMethod>;
|
|
768
|
+
methods?: Record<string, (...args: any[]) => any>;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Create a repository — a composable set of chainable query methods.
|
|
772
|
+
*
|
|
773
|
+
* ```ts
|
|
774
|
+
* const userRepo = createRepo(User, {
|
|
775
|
+
* queryMethods: {
|
|
776
|
+
* search(q, query: string) {
|
|
777
|
+
* return q.where('name', 'like', `%${query}%`)
|
|
778
|
+
* },
|
|
779
|
+
* },
|
|
780
|
+
* })
|
|
781
|
+
* const users = await userRepo.search('john').paginate(1, 20)
|
|
782
|
+
* ```
|
|
783
|
+
*/
|
|
784
|
+
declare function createRepo<TMethods extends RepoMethods>(model: ModelDefinition, methods: TMethods): Record<string, never>;
|
|
785
|
+
//#endregion
|
|
786
|
+
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 QueryMethod, type Relation, 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, defineMorphOne, defineMorphTo, hasMany, hasManyThrough, hasOne, manyToMany, normalizeError, resolveMorphRelation, softDeletes, t, timestamps, ulid };
|