outlet-orm 2.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/LICENSE +21 -0
- package/README.md +705 -0
- package/bin/convert.js +679 -0
- package/bin/init.js +190 -0
- package/bin/migrate.js +442 -0
- package/lib/Database/DatabaseConnection.js +4 -0
- package/lib/Migrations/Migration.js +48 -0
- package/lib/Migrations/MigrationManager.js +326 -0
- package/lib/Schema/Schema.js +790 -0
- package/package.json +75 -0
- package/src/DatabaseConnection.js +697 -0
- package/src/Model.js +659 -0
- package/src/QueryBuilder.js +710 -0
- package/src/Relations/BelongsToManyRelation.js +466 -0
- package/src/Relations/BelongsToRelation.js +127 -0
- package/src/Relations/HasManyRelation.js +125 -0
- package/src/Relations/HasManyThroughRelation.js +112 -0
- package/src/Relations/HasOneRelation.js +114 -0
- package/src/Relations/HasOneThroughRelation.js +105 -0
- package/src/Relations/MorphManyRelation.js +69 -0
- package/src/Relations/MorphOneRelation.js +68 -0
- package/src/Relations/MorphToRelation.js +110 -0
- package/src/Relations/Relation.js +31 -0
- package/src/index.js +23 -0
- package/types/index.d.ts +272 -0
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// Type definitions for outlet-orm
|
|
2
|
+
|
|
3
|
+
declare module 'outlet-orm' {
|
|
4
|
+
|
|
5
|
+
// ==================== Database Connection ====================
|
|
6
|
+
|
|
7
|
+
export interface DatabaseConfig {
|
|
8
|
+
driver: 'mysql' | 'postgres' | 'postgresql' | 'sqlite';
|
|
9
|
+
host?: string;
|
|
10
|
+
port?: number;
|
|
11
|
+
database?: string;
|
|
12
|
+
user?: string;
|
|
13
|
+
password?: string;
|
|
14
|
+
connectionLimit?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class DatabaseConnection {
|
|
18
|
+
constructor(config?: Partial<DatabaseConfig>);
|
|
19
|
+
connect(): Promise<void>;
|
|
20
|
+
select(table: string, query: QueryObject): Promise<any[]>;
|
|
21
|
+
insert(table: string, data: Record<string, any>): Promise<{ insertId: any; affectedRows: number }>;
|
|
22
|
+
insertMany(table: string, data: Record<string, any>[]): Promise<{ affectedRows: number }>;
|
|
23
|
+
update(table: string, data: Record<string, any>, query: QueryObject): Promise<{ affectedRows: number }>;
|
|
24
|
+
delete(table: string, query: QueryObject): Promise<{ affectedRows: number }>;
|
|
25
|
+
count(table: string, query: QueryObject): Promise<number>;
|
|
26
|
+
executeRawQuery(sql: string, params?: any[]): Promise<any[]>;
|
|
27
|
+
/** Execute raw SQL and return driver-native results (used by migrations) */
|
|
28
|
+
execute(sql: string, params?: any[]): Promise<any>;
|
|
29
|
+
/** Atomically increment a column respecting query wheres */
|
|
30
|
+
increment(table: string, column: string, query: QueryObject, amount?: number): Promise<{ affectedRows: number }>;
|
|
31
|
+
/** Atomically decrement a column respecting query wheres */
|
|
32
|
+
decrement(table: string, column: string, query: QueryObject, amount?: number): Promise<{ affectedRows: number }>;
|
|
33
|
+
close(): Promise<void>;
|
|
34
|
+
/** Backwards-compatible alias used by CLI */
|
|
35
|
+
disconnect(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ==================== Query Builder ====================
|
|
39
|
+
|
|
40
|
+
export interface QueryObject {
|
|
41
|
+
columns?: string[];
|
|
42
|
+
wheres?: WhereClause[];
|
|
43
|
+
orders?: OrderClause[];
|
|
44
|
+
joins?: JoinClause[];
|
|
45
|
+
distinct?: boolean;
|
|
46
|
+
groupBys?: string[];
|
|
47
|
+
havings?: HavingClause[];
|
|
48
|
+
limit?: number | null;
|
|
49
|
+
offset?: number | null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface WhereClause {
|
|
53
|
+
column?: string;
|
|
54
|
+
operator?: string;
|
|
55
|
+
value?: any;
|
|
56
|
+
values?: any[];
|
|
57
|
+
type: 'basic' | 'in' | 'notIn' | 'null' | 'notNull' | 'between' | 'like';
|
|
58
|
+
boolean: 'and' | 'or';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface OrderClause {
|
|
62
|
+
column: string;
|
|
63
|
+
direction: 'asc' | 'desc';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface HavingClause {
|
|
67
|
+
type: 'basic' | 'count';
|
|
68
|
+
column: string;
|
|
69
|
+
operator: string;
|
|
70
|
+
value: any;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface JoinClause {
|
|
74
|
+
table: string;
|
|
75
|
+
first: string;
|
|
76
|
+
operator: string;
|
|
77
|
+
second: string;
|
|
78
|
+
type: 'inner' | 'left';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface PaginationResult<T> {
|
|
82
|
+
data: T[];
|
|
83
|
+
total: number;
|
|
84
|
+
per_page: number;
|
|
85
|
+
current_page: number;
|
|
86
|
+
last_page: number;
|
|
87
|
+
from: number | null;
|
|
88
|
+
to: number;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export class QueryBuilder<T extends Model> {
|
|
92
|
+
constructor(model: typeof Model);
|
|
93
|
+
|
|
94
|
+
select(...columns: string[]): this;
|
|
95
|
+
/** Convenience alias to pass an array of columns */
|
|
96
|
+
columns(cols: string[]): this;
|
|
97
|
+
distinct(): this;
|
|
98
|
+
where(column: string, value: any): this;
|
|
99
|
+
where(column: string, operator: string, value: any): this;
|
|
100
|
+
whereIn(column: string, values: any[]): this;
|
|
101
|
+
whereNotIn(column: string, values: any[]): this;
|
|
102
|
+
whereNull(column: string): this;
|
|
103
|
+
whereNotNull(column: string): this;
|
|
104
|
+
orWhere(column: string, value: any): this;
|
|
105
|
+
orWhere(column: string, operator: string, value: any): this;
|
|
106
|
+
whereBetween(column: string, values: [any, any]): this;
|
|
107
|
+
whereLike(column: string, value: string): this;
|
|
108
|
+
/** Filter parents where a relation has matches */
|
|
109
|
+
whereHas(relationName: string, callback?: (qb: QueryBuilder<any>) => void): this;
|
|
110
|
+
/** Filter parents where relation count matches */
|
|
111
|
+
has(relationName: string, count: number): this;
|
|
112
|
+
has(relationName: string, operator: string, count: number): this;
|
|
113
|
+
/** Filter parents without related rows */
|
|
114
|
+
whereDoesntHave(relationName: string): this;
|
|
115
|
+
orderBy(column: string, direction?: 'asc' | 'desc'): this;
|
|
116
|
+
/** Typo-friendly alias for orderBy */
|
|
117
|
+
ordrer(column: string, direction?: 'asc' | 'desc'): this;
|
|
118
|
+
limit(value: number): this;
|
|
119
|
+
offset(value: number): this;
|
|
120
|
+
skip(value: number): this;
|
|
121
|
+
take(value: number): this;
|
|
122
|
+
with(...relations: string[] | [Record<string, (qb: QueryBuilder<any>) => void> | string[]]): this;
|
|
123
|
+
withCount(relations: string | string[]): this;
|
|
124
|
+
groupBy(...columns: string[]): this;
|
|
125
|
+
having(column: string, operator: string, value: any): this;
|
|
126
|
+
join(table: string, first: string, second: string): this;
|
|
127
|
+
join(table: string, first: string, operator: string, second: string): this;
|
|
128
|
+
leftJoin(table: string, first: string, second: string): this;
|
|
129
|
+
leftJoin(table: string, first: string, operator: string, second: string): this;
|
|
130
|
+
|
|
131
|
+
get(): Promise<T[]>;
|
|
132
|
+
first(): Promise<T | null>;
|
|
133
|
+
firstOrFail(): Promise<T>;
|
|
134
|
+
paginate(page?: number, perPage?: number): Promise<PaginationResult<T>>;
|
|
135
|
+
count(): Promise<number>;
|
|
136
|
+
exists(): Promise<boolean>;
|
|
137
|
+
insert(data: Record<string, any> | Record<string, any>[]): Promise<any>;
|
|
138
|
+
update(attributes: Record<string, any>): Promise<any>;
|
|
139
|
+
/** Update and return first matching row as model, optionally eager-loading relations */
|
|
140
|
+
updateAndFetch(attributes: Record<string, any>, relations?: string[]): Promise<T | null>;
|
|
141
|
+
delete(): Promise<any>;
|
|
142
|
+
increment(column: string, amount?: number): Promise<any>;
|
|
143
|
+
decrement(column: string, amount?: number): Promise<any>;
|
|
144
|
+
|
|
145
|
+
clone(): QueryBuilder<T>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ==================== Model ====================
|
|
149
|
+
|
|
150
|
+
export type CastType = 'int' | 'integer' | 'float' | 'double' | 'string' | 'bool' | 'boolean' | 'array' | 'json' | 'date' | 'datetime' | 'timestamp';
|
|
151
|
+
|
|
152
|
+
export class Model {
|
|
153
|
+
static table: string;
|
|
154
|
+
static primaryKey: string;
|
|
155
|
+
static timestamps: boolean;
|
|
156
|
+
static fillable: string[];
|
|
157
|
+
static hidden: string[];
|
|
158
|
+
static casts: Record<string, CastType>;
|
|
159
|
+
static connection: DatabaseConnection | null;
|
|
160
|
+
|
|
161
|
+
attributes: Record<string, any>;
|
|
162
|
+
original: Record<string, any>;
|
|
163
|
+
relations: Record<string, any>;
|
|
164
|
+
exists: boolean;
|
|
165
|
+
|
|
166
|
+
constructor(attributes?: Record<string, any>);
|
|
167
|
+
|
|
168
|
+
// Static methods
|
|
169
|
+
static setConnection(connection: DatabaseConnection): void;
|
|
170
|
+
static query<T extends Model>(this: new () => T): QueryBuilder<T>;
|
|
171
|
+
static all<T extends Model>(this: new () => T): Promise<T[]>;
|
|
172
|
+
static find<T extends Model>(this: new () => T, id: any): Promise<T | null>;
|
|
173
|
+
static findOrFail<T extends Model>(this: new () => T, id: any): Promise<T>;
|
|
174
|
+
static where<T extends Model>(this: new () => T, column: string, value: any): QueryBuilder<T>;
|
|
175
|
+
static where<T extends Model>(this: new () => T, column: string, operator: string, value: any): QueryBuilder<T>;
|
|
176
|
+
static create<T extends Model>(this: new () => T, attributes: Record<string, any>): Promise<T>;
|
|
177
|
+
static insert(data: Record<string, any> | Record<string, any>[]): Promise<any>;
|
|
178
|
+
static update(attributes: Record<string, any>): Promise<any>;
|
|
179
|
+
/** Update by primary key and return the updated model, optionally eager-loading relations */
|
|
180
|
+
static updateAndFetchById<T extends Model>(this: new () => T, id: any, attributes: Record<string, any>, relations?: string[]): Promise<T | null>;
|
|
181
|
+
/** Update by primary key */
|
|
182
|
+
static updateById<T extends Model>(this: new () => T, id: any, attributes: Record<string, any>): Promise<any>;
|
|
183
|
+
static delete(): Promise<any>;
|
|
184
|
+
static first<T extends Model>(this: new () => T): Promise<T | null>;
|
|
185
|
+
static orderBy<T extends Model>(this: new () => T, column: string, direction?: 'asc' | 'desc'): QueryBuilder<T>;
|
|
186
|
+
static limit<T extends Model>(this: new () => T, value: number): QueryBuilder<T>;
|
|
187
|
+
static offset<T extends Model>(this: new () => T, value: number): QueryBuilder<T>;
|
|
188
|
+
static paginate<T extends Model>(this: new () => T, page?: number, perPage?: number): Promise<PaginationResult<T>>;
|
|
189
|
+
static whereIn<T extends Model>(this: new () => T, column: string, values: any[]): QueryBuilder<T>;
|
|
190
|
+
static whereNull<T extends Model>(this: new () => T, column: string): QueryBuilder<T>;
|
|
191
|
+
static whereNotNull<T extends Model>(this: new () => T, column: string): QueryBuilder<T>;
|
|
192
|
+
static count(): Promise<number>;
|
|
193
|
+
static with<T extends Model>(this: new () => T, ...relations: string[] | [Record<string, (qb: QueryBuilder<any>) => void> | string[]]): QueryBuilder<T>;
|
|
194
|
+
|
|
195
|
+
// Instance methods
|
|
196
|
+
fill(attributes: Record<string, any>): this;
|
|
197
|
+
setAttribute(key: string, value: any): this;
|
|
198
|
+
getAttribute(key: string): any;
|
|
199
|
+
castAttribute(key: string, value: any): any;
|
|
200
|
+
save(): Promise<this>;
|
|
201
|
+
destroy(): Promise<boolean>;
|
|
202
|
+
getDirty(): Record<string, any>;
|
|
203
|
+
isDirty(): boolean;
|
|
204
|
+
toJSON(): Record<string, any>;
|
|
205
|
+
/** Load relations on an existing instance. Supports dot-notation and arrays. */
|
|
206
|
+
load(...relations: string[] | [string[]]): Promise<this>;
|
|
207
|
+
|
|
208
|
+
// Relationships
|
|
209
|
+
hasOne<T extends Model>(related: new () => T, foreignKey?: string, localKey?: string): HasOneRelation<T>;
|
|
210
|
+
hasMany<T extends Model>(related: new () => T, foreignKey?: string, localKey?: string): HasManyRelation<T>;
|
|
211
|
+
belongsTo<T extends Model>(related: new () => T, foreignKey?: string, ownerKey?: string): BelongsToRelation<T>;
|
|
212
|
+
belongsToMany<T extends Model>(
|
|
213
|
+
related: new () => T,
|
|
214
|
+
pivot: string,
|
|
215
|
+
foreignPivotKey?: string,
|
|
216
|
+
relatedPivotKey?: string,
|
|
217
|
+
parentKey?: string,
|
|
218
|
+
relatedKey?: string
|
|
219
|
+
): BelongsToManyRelation<T>;
|
|
220
|
+
hasManyThrough<T extends Model>(
|
|
221
|
+
relatedFinal: new () => T,
|
|
222
|
+
through: new () => Model,
|
|
223
|
+
foreignKeyOnThrough?: string,
|
|
224
|
+
throughKeyOnFinal?: string,
|
|
225
|
+
localKey?: string,
|
|
226
|
+
throughLocalKey?: string
|
|
227
|
+
): HasManyThroughRelation<T>;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ==================== Relations ====================
|
|
231
|
+
|
|
232
|
+
export abstract class Relation<T extends Model> {
|
|
233
|
+
constructor(parent: Model, related: new () => T, foreignKey: string, localKey: string);
|
|
234
|
+
abstract get(): Promise<T | T[] | null>;
|
|
235
|
+
abstract eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export class HasOneRelation<T extends Model> extends Relation<T> {
|
|
239
|
+
get(): Promise<T | null>;
|
|
240
|
+
eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
|
|
241
|
+
where(column: string, value: any): QueryBuilder<T>;
|
|
242
|
+
where(column: string, operator: string, value: any): QueryBuilder<T>;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export class HasManyRelation<T extends Model> extends Relation<T> {
|
|
246
|
+
get(): Promise<T[]>;
|
|
247
|
+
eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
|
|
248
|
+
where(column: string, value: any): QueryBuilder<T>;
|
|
249
|
+
where(column: string, operator: string, value: any): QueryBuilder<T>;
|
|
250
|
+
count(): Promise<number>;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export class BelongsToRelation<T extends Model> extends Relation<T> {
|
|
254
|
+
get(): Promise<T | null>;
|
|
255
|
+
eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
|
|
256
|
+
where(column: string, value: any): QueryBuilder<T>;
|
|
257
|
+
where(column: string, operator: string, value: any): QueryBuilder<T>;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export class BelongsToManyRelation<T extends Model> extends Relation<T> {
|
|
261
|
+
get(): Promise<T[]>;
|
|
262
|
+
eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
|
|
263
|
+
attach(ids: number | number[]): Promise<void>;
|
|
264
|
+
detach(ids?: number | number[] | null): Promise<void>;
|
|
265
|
+
sync(ids: number[]): Promise<void>;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export class HasManyThroughRelation<T extends Model> extends Relation<T> {
|
|
269
|
+
get(): Promise<T[]>;
|
|
270
|
+
eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
|
|
271
|
+
}
|
|
272
|
+
}
|