ilana-orm 1.0.14 → 1.0.16
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 +178 -115
- package/database/connection.js +21 -10
- package/database/schema-builder.js +18 -12
- package/index.js +1 -0
- package/index.mjs +1 -0
- package/orm/Factory.js +20 -18
- package/orm/Model.d.ts +26 -3
- package/orm/Model.js +159 -68
- package/orm/QueryBuilder.d.ts +24 -2
- package/orm/QueryBuilder.js +437 -75
- package/orm/Relation.d.ts +15 -3
- package/orm/Relation.js +74 -11
- package/orm/Relation.mjs +1 -1
- package/package.json +10 -9
package/orm/Relation.d.ts
CHANGED
|
@@ -52,9 +52,11 @@ export class BelongsToMany extends Relation {
|
|
|
52
52
|
withTimestamps(): this;
|
|
53
53
|
addConstraints(): void;
|
|
54
54
|
getResults(): Promise<Model[]>;
|
|
55
|
-
attach(id: any, attributes?: any): Promise<void>;
|
|
55
|
+
attach(id: any, attributes?: Record<string, any>): Promise<void>;
|
|
56
56
|
detach(id?: any): Promise<number>;
|
|
57
|
-
sync(ids: any[]): Promise<void>;
|
|
57
|
+
sync(ids: any[] | Record<string | number, Record<string, any>>): Promise<void>;
|
|
58
|
+
toggle(ids: any | any[]): Promise<void>;
|
|
59
|
+
updateExistingPivot(id: any, attributes: Record<string, any>): Promise<number>;
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
export class HasManyThrough extends Relation {
|
|
@@ -96,4 +98,14 @@ export class MorphMany extends Relation {
|
|
|
96
98
|
|
|
97
99
|
addConstraints(): void;
|
|
98
100
|
getResults(): Promise<Collection<Model>>;
|
|
99
|
-
}
|
|
101
|
+
}
|
|
102
|
+
export class MorphOne extends Relation {
|
|
103
|
+
protected morphType: string;
|
|
104
|
+
protected morphId: string;
|
|
105
|
+
protected morphClass: string;
|
|
106
|
+
|
|
107
|
+
constructor(parent: Model, related: string | typeof Model, morphType: string, morphId: string, morphClass: string);
|
|
108
|
+
|
|
109
|
+
addConstraints(): void;
|
|
110
|
+
getResults(): Promise<Model | null>;
|
|
111
|
+
}
|
package/orm/Relation.js
CHANGED
|
@@ -198,10 +198,39 @@ class BelongsToMany extends Relation {
|
|
|
198
198
|
|
|
199
199
|
async sync(ids) {
|
|
200
200
|
await this.detach();
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
if (Array.isArray(ids)) {
|
|
202
|
+
for (const id of ids) {
|
|
203
|
+
await this.attach(id);
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
// Object form: { id: { pivot_col: val } }
|
|
207
|
+
for (const [id, attrs] of Object.entries(ids)) {
|
|
208
|
+
await this.attach(id, attrs);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async toggle(ids) {
|
|
214
|
+
const current = await this.getResults();
|
|
215
|
+
const currentIds = current.map(m => String(m.getAttribute(this.relatedKey)));
|
|
216
|
+
const list = Array.isArray(ids) ? ids : [ids];
|
|
217
|
+
for (const id of list) {
|
|
218
|
+
if (currentIds.includes(String(id))) {
|
|
219
|
+
await this.detach(id);
|
|
220
|
+
} else {
|
|
221
|
+
await this.attach(id);
|
|
222
|
+
}
|
|
203
223
|
}
|
|
204
224
|
}
|
|
225
|
+
|
|
226
|
+
async updateExistingPivot(id, attributes) {
|
|
227
|
+
const data = { ...attributes };
|
|
228
|
+
if (this.pivotTimestamps) data.updated_at = new Date();
|
|
229
|
+
return new QueryBuilder(this.pivotTable)
|
|
230
|
+
.where(this.parentPivotKey, this.parent.getAttribute(this.parentKey))
|
|
231
|
+
.where(this.relatedPivotKey, id)
|
|
232
|
+
.update(data);
|
|
233
|
+
}
|
|
205
234
|
}
|
|
206
235
|
|
|
207
236
|
class HasManyThrough extends Relation {
|
|
@@ -227,10 +256,16 @@ class HasManyThrough extends Relation {
|
|
|
227
256
|
}
|
|
228
257
|
|
|
229
258
|
async getResults() {
|
|
259
|
+
const relatedClass = this.getRelatedClass();
|
|
260
|
+
const throughClass = ModelRegistry.get(this.through) || null;
|
|
261
|
+
const throughTable = throughClass
|
|
262
|
+
? throughClass.getTableName()
|
|
263
|
+
: (typeof this.through === 'string' ? this.through : this.through.getTableName());
|
|
264
|
+
const relatedTable = relatedClass.getTableName();
|
|
230
265
|
return this.newQuery()
|
|
231
|
-
.select(`${
|
|
232
|
-
.join(
|
|
233
|
-
.where(`${
|
|
266
|
+
.select(`${relatedTable}.*`)
|
|
267
|
+
.join(throughTable, `${relatedTable}.${this.secondKey}`, `${throughTable}.${this.secondLocalKey}`)
|
|
268
|
+
.where(`${throughTable}.${this.firstKey}`, this.parent.getAttribute(this.localKey))
|
|
234
269
|
.get();
|
|
235
270
|
}
|
|
236
271
|
}
|
|
@@ -238,9 +273,12 @@ class HasManyThrough extends Relation {
|
|
|
238
273
|
// Polymorphic Relations
|
|
239
274
|
class MorphTo extends Relation {
|
|
240
275
|
constructor(parent, morphType, morphId) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
276
|
+
// Accept either a base name ('commentable') or full column names ('commentable_type', 'commentable_id')
|
|
277
|
+
const typeCol = morphType && !morphType.endsWith('_type') ? `${morphType}_type` : morphType;
|
|
278
|
+
const idCol = morphId || (morphType ? `${morphType.replace(/_type$/, '')}_id` : undefined);
|
|
279
|
+
super(parent, Model, idCol, 'id');
|
|
280
|
+
this.morphType = typeCol;
|
|
281
|
+
this.morphId = idCol;
|
|
244
282
|
}
|
|
245
283
|
|
|
246
284
|
addConstraints() {
|
|
@@ -269,9 +307,12 @@ class MorphTo extends Relation {
|
|
|
269
307
|
|
|
270
308
|
class MorphMany extends Relation {
|
|
271
309
|
constructor(parent, related, morphType, morphId, morphClass) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
310
|
+
// Accept either a base name ('commentable') or full column names ('commentable_type', 'commentable_id')
|
|
311
|
+
const typeCol = morphType && !morphType.endsWith('_type') ? `${morphType}_type` : morphType;
|
|
312
|
+
const idCol = morphId || (morphType ? `${morphType.replace(/_type$/, '')}_id` : undefined);
|
|
313
|
+
super(parent, related, idCol, 'id');
|
|
314
|
+
this.morphType = typeCol;
|
|
315
|
+
this.morphId = idCol;
|
|
275
316
|
this.morphClass = morphClass;
|
|
276
317
|
}
|
|
277
318
|
|
|
@@ -287,6 +328,27 @@ class MorphMany extends Relation {
|
|
|
287
328
|
}
|
|
288
329
|
}
|
|
289
330
|
|
|
331
|
+
class MorphOne extends Relation {
|
|
332
|
+
constructor(parent, related, morphType, morphId, morphClass) {
|
|
333
|
+
// Accept either a base name ('imageable') or full column names ('imageable_type', 'imageable_id')
|
|
334
|
+
const typeCol = morphType && !morphType.endsWith('_type') ? `${morphType}_type` : morphType;
|
|
335
|
+
const idCol = morphId || (morphType ? `${morphType.replace(/_type$/, '')}_id` : undefined);
|
|
336
|
+
super(parent, related, idCol, 'id');
|
|
337
|
+
this.morphType = typeCol;
|
|
338
|
+
this.morphId = idCol;
|
|
339
|
+
this.morphClass = morphClass;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
addConstraints() {}
|
|
343
|
+
|
|
344
|
+
async getResults() {
|
|
345
|
+
return this.newQuery()
|
|
346
|
+
.where(this.morphType, this.morphClass)
|
|
347
|
+
.where(this.morphId, this.parent.getAttribute(this.localKey))
|
|
348
|
+
.first();
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
290
352
|
module.exports = {
|
|
291
353
|
Relation,
|
|
292
354
|
HasOne,
|
|
@@ -295,5 +357,6 @@ module.exports = {
|
|
|
295
357
|
BelongsToMany,
|
|
296
358
|
HasManyThrough,
|
|
297
359
|
MorphTo,
|
|
360
|
+
MorphOne,
|
|
298
361
|
MorphMany
|
|
299
362
|
};
|
package/orm/Relation.mjs
CHANGED
|
@@ -4,4 +4,4 @@ const require = createRequire(import.meta.url);
|
|
|
4
4
|
|
|
5
5
|
const Relations = require('./Relation.js');
|
|
6
6
|
|
|
7
|
-
export const { Relation, HasOne, HasMany, BelongsTo, BelongsToMany, HasManyThrough, MorphTo, MorphMany } = Relations;
|
|
7
|
+
export const { Relation, HasOne, HasMany, BelongsTo, BelongsToMany, HasManyThrough, MorphTo, MorphOne, MorphMany } = Relations;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ilana-orm",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "A fully-featured, Eloquent-style ORM for Node.js with TypeScript support",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -114,14 +114,15 @@
|
|
|
114
114
|
"ilana.png"
|
|
115
115
|
],
|
|
116
116
|
"dependencies": {
|
|
117
|
-
"knex": "^3.
|
|
118
|
-
"uuid": "^
|
|
119
|
-
"@faker-js/faker": "^
|
|
120
|
-
"
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
"
|
|
124
|
-
"
|
|
117
|
+
"knex": "^3.1.0",
|
|
118
|
+
"uuid": "^10.0.0",
|
|
119
|
+
"@faker-js/faker": "^9.0.0",
|
|
120
|
+
"dotenv": "^16.4.0"
|
|
121
|
+
},
|
|
122
|
+
"optionalDependencies": {
|
|
123
|
+
"pg": "^8.13.0",
|
|
124
|
+
"mysql2": "^3.11.0",
|
|
125
|
+
"sqlite3": "^5.1.7"
|
|
125
126
|
},
|
|
126
127
|
"devDependencies": {
|
|
127
128
|
"@types/node": "^20.0.0",
|