@t4h.framework/orm 0.10.2 → 0.11.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/CHANGELOG.md +26 -0
- package/README.md +37 -2
- package/dist/activities/ORMLoadActivity.d.ts +16 -0
- package/dist/activities/ORMLoadActivity.d.ts.map +1 -0
- package/dist/activities/ORMLoadActivity.js +90 -0
- package/dist/activities/ORMLoadActivity.js.map +1 -0
- package/dist/activities/ORMLoadRelationActivity.d.ts +13 -0
- package/dist/activities/ORMLoadRelationActivity.d.ts.map +1 -0
- package/dist/activities/ORMLoadRelationActivity.js +23 -0
- package/dist/activities/ORMLoadRelationActivity.js.map +1 -0
- package/dist/claims/ORMClaim.d.ts +7 -1
- package/dist/claims/ORMClaim.d.ts.map +1 -1
- package/dist/claims/ORMClaim.js +5 -0
- package/dist/claims/ORMClaim.js.map +1 -1
- package/dist/decorators/ManyToOne.d.ts +6 -0
- package/dist/decorators/ManyToOne.d.ts.map +1 -0
- package/dist/decorators/ManyToOne.js +15 -0
- package/dist/decorators/ManyToOne.js.map +1 -0
- package/dist/decorators/OneToMany.d.ts +7 -0
- package/dist/decorators/OneToMany.d.ts.map +1 -0
- package/dist/decorators/OneToMany.js +17 -0
- package/dist/decorators/OneToMany.js.map +1 -0
- package/dist/decorators/metadata.d.ts +17 -0
- package/dist/decorators/metadata.d.ts.map +1 -1
- package/dist/decorators/metadata.js +11 -1
- package/dist/decorators/metadata.js.map +1 -1
- package/dist/helpers/Insert.d.ts +22 -0
- package/dist/helpers/Insert.d.ts.map +1 -0
- package/dist/helpers/Insert.js +73 -0
- package/dist/helpers/Insert.js.map +1 -0
- package/dist/helpers/Populate.d.ts +13 -0
- package/dist/helpers/Populate.d.ts.map +1 -0
- package/dist/helpers/Populate.js +31 -0
- package/dist/helpers/Populate.js.map +1 -0
- package/dist/helpers/Serialize.d.ts +11 -0
- package/dist/helpers/Serialize.d.ts.map +1 -0
- package/dist/helpers/Serialize.js +60 -0
- package/dist/helpers/Serialize.js.map +1 -0
- package/dist/helpers/hydrateEntity.d.ts +4 -0
- package/dist/helpers/hydrateEntity.d.ts.map +1 -0
- package/dist/helpers/hydrateEntity.js +30 -0
- package/dist/helpers/hydrateEntity.js.map +1 -0
- package/dist/helpers/isPlainObject.d.ts +2 -0
- package/dist/helpers/isPlainObject.d.ts.map +1 -0
- package/dist/helpers/isPlainObject.js +7 -0
- package/dist/helpers/isPlainObject.js.map +1 -0
- package/dist/helpers/refs.d.ts +5 -0
- package/dist/helpers/refs.d.ts.map +1 -0
- package/dist/helpers/refs.js +3 -0
- package/dist/helpers/refs.js.map +1 -0
- package/dist/helpers/toRefKey.d.ts +3 -0
- package/dist/helpers/toRefKey.d.ts.map +1 -0
- package/dist/helpers/toRefKey.js +4 -0
- package/dist/helpers/toRefKey.js.map +1 -0
- package/dist/models/MapCollection.d.ts +46 -0
- package/dist/models/MapCollection.d.ts.map +1 -0
- package/dist/models/MapCollection.js +126 -0
- package/dist/models/MapCollection.js.map +1 -0
- package/dist/models/ORM.d.ts +16 -3
- package/dist/models/ORM.d.ts.map +1 -1
- package/dist/models/ORM.js +43 -13
- package/dist/models/ORM.js.map +1 -1
- package/dist/models/Ref.d.ts +8 -1
- package/dist/models/Ref.d.ts.map +1 -1
- package/dist/models/Ref.js +17 -14
- package/dist/models/Ref.js.map +1 -1
- package/dist/models/RefCollection.d.ts +10 -1
- package/dist/models/RefCollection.d.ts.map +1 -1
- package/dist/models/RefCollection.js +62 -2
- package/dist/models/RefCollection.js.map +1 -1
- package/dist/orm.d.ts +6 -0
- package/dist/orm.d.ts.map +1 -1
- package/dist/orm.js +6 -0
- package/dist/orm.js.map +1 -1
- package/dist/typings/FindWhere.d.ts +2 -1
- package/dist/typings/FindWhere.d.ts.map +1 -1
- package/dist/typings/ORM.d.ts +42 -4
- package/dist/typings/ORM.d.ts.map +1 -1
- package/dist/typings/Relations.d.ts +27 -0
- package/dist/typings/Relations.d.ts.map +1 -0
- package/dist/typings/Relations.js +2 -0
- package/dist/typings/Relations.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @t4h.framework/orm
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#201](https://github.com/tech4humans-brasil/framework/pull/201) [`374e2d7`](https://github.com/tech4humans-brasil/framework/commit/374e2d759ac1fda954981545a791652dede445ae) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Relations: `@ManyToOne` and `@OneToMany` link entities. The to-one side is a
|
|
8
|
+
`Ref<T>`, the many side is a lazy `MapCollection<T>` (`map`, `filter`,
|
|
9
|
+
`toArray`, `toRefCollection`, …), and `populate` on `getSnapshot` reads the
|
|
10
|
+
row and its nested relations in a single `ORMLoadActivity`, one query per
|
|
11
|
+
relation and level. The result is typed `Populated<T, P>`: a populated
|
|
12
|
+
`@ManyToOne` is the related row's snapshot (`null` when it no longer exists)
|
|
13
|
+
instead of a `Ref`. `RefCollection.getSnapshots`
|
|
14
|
+
reads every row of a collection in one activity, and a `RefCollection` now
|
|
15
|
+
serializes its `orm` and `table` too. `load(relation)` on a `Ref` or a
|
|
16
|
+
`RefCollection` follows a relation and returns refs only: a `@ManyToOne`
|
|
17
|
+
gives the related refs through one `ORMLoadRelationActivity`, a `@OneToMany`
|
|
18
|
+
gives a `MapCollection` (over every parent, for a collection) read only when
|
|
19
|
+
used. Owning columns store the related row ref and are indexed; `create`,
|
|
20
|
+
`update`, `upsert` and `where` accept a `Ref` for them, and `create` also
|
|
21
|
+
takes the data of new related rows on either side (`EntityCreateData`),
|
|
22
|
+
created level by level in one `ORMCreateActivity` per relation. `ORMClaim` gains the abstract
|
|
23
|
+
`getSnapshots`, which reads several rows at once and must be implemented by
|
|
24
|
+
every claim. `Ref.getSnapshot` now always runs `ORMLoadActivity` instead of
|
|
25
|
+
`ORMGetSnapshotActivity`, so runs started on an older version do not replay
|
|
26
|
+
it. Hosts must register `ORMLoadActivity`,
|
|
27
|
+
`ORMLoadRelationActivity` and the `orm:map-collection` codec kind.
|
|
28
|
+
|
|
3
29
|
## 0.10.2
|
|
4
30
|
|
|
5
31
|
## 0.10.1
|
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ abstract class ORMClaim<R extends SerializableRowRef> {
|
|
|
21
21
|
public abstract getSnapshot(input: SerializableGetSnapshotInput<R>): SerializedRow | Promise<SerializedRow>
|
|
22
22
|
public abstract update(input: SerializableUpdateInput<R>): void | Promise<void>
|
|
23
23
|
public abstract remove(input: SerializableRemoveInput<R>): void | Promise<void>
|
|
24
|
+
public abstract getSnapshots(input: SerializableGetSnapshotsInput<R>): (SerializedRow | null)[] | Promise<(SerializedRow | null)[]>
|
|
24
25
|
public abstract delete(input: SerializableDeleteInput): number | Promise<number>
|
|
25
26
|
|
|
26
27
|
// Default: find, then create or update. Override for a native upsert.
|
|
@@ -222,11 +223,43 @@ const usersRef = await orm.find(User, { where: { active: true } })
|
|
|
222
223
|
|
|
223
224
|
const users = usersRef.toArray() // Ref<User>[]
|
|
224
225
|
usersRef.forEach(ref => { /* ... */ })
|
|
225
|
-
usersRef.
|
|
226
|
+
await usersRef.getSnapshots() // (User | null)[] in one activity
|
|
226
227
|
usersRef.filter(ref => { /* ... */ })
|
|
227
228
|
usersRef.at(0) // Ref<User> | undefined
|
|
228
229
|
```
|
|
229
230
|
|
|
231
|
+
## Relations
|
|
232
|
+
|
|
233
|
+
`@ManyToOne` owns the relation and stores the related row in a column; `@OneToMany` reads it back from the other table. The to-one side is a `Ref<T>`, the many side a lazy `MapCollection<T>`:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
@Entity({ tableName: 'users' })
|
|
237
|
+
class User {
|
|
238
|
+
@OneToMany(() => Post, { mappedBy: 'author' })
|
|
239
|
+
public posts!: MapCollection<Post>
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
@Entity({ tableName: 'posts' })
|
|
243
|
+
class Post {
|
|
244
|
+
@ManyToOne(() => User)
|
|
245
|
+
public author!: Ref<User>
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
await orm.create(Post, { title: 'Hello', author: userRef })
|
|
249
|
+
|
|
250
|
+
const aliceRef = await orm.findOne(User, { where: { name: 'Alice' } })
|
|
251
|
+
|
|
252
|
+
const user = await aliceRef!.getSnapshot({
|
|
253
|
+
populate: ['posts'], // read in the same activity
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
await user!.posts.map(post => post.title)
|
|
257
|
+
|
|
258
|
+
const posts = await aliceRef!.load('posts') // MapCollection<Post>, read when used
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
See [docs/relations.md](./docs/relations.md).
|
|
262
|
+
|
|
230
263
|
## Query Operators
|
|
231
264
|
|
|
232
265
|
The `where` clause supports the following operators:
|
|
@@ -251,7 +284,9 @@ The package includes the following activities (used internally by `ORM` and `Ref
|
|
|
251
284
|
- `ORMCreateActivity` -- creates one or more rows
|
|
252
285
|
- `ORMFindActivity` -- finds multiple rows
|
|
253
286
|
- `ORMFindOneActivity` -- finds a single row
|
|
254
|
-
- `ORMGetSnapshotActivity` -- retrieves full entity data from a ref
|
|
287
|
+
- `ORMGetSnapshotActivity` -- retrieves full entity data from a ref (no longer used by `Ref.getSnapshot`)
|
|
288
|
+
- `ORMLoadActivity` -- backs `getSnapshot` / `getSnapshots`: retrieves rows with their relations and `populate` in one activity
|
|
289
|
+
- `ORMLoadRelationActivity` -- follows a to-one relation from one or more refs, returning refs
|
|
255
290
|
- `ORMUpdateActivity` -- updates a row
|
|
256
291
|
- `ORMUpsertActivity` -- inserts or updates rows by `conflictOn` (via `ORMClaim.upsert`)
|
|
257
292
|
- `ORMRemoveActivity` -- removes a row
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SyncActivity } from '@t4h.framework/core';
|
|
2
|
+
import type { SerializableLoadInput, SerializableLoadedRow } from '../typings/ORM.js';
|
|
3
|
+
declare const CLAIMS_KEY: unique symbol;
|
|
4
|
+
export declare class ORMLoadActivity extends SyncActivity<[
|
|
5
|
+
input: SerializableLoadInput
|
|
6
|
+
], SerializableLoadInput, (SerializableLoadedRow | null)[], (SerializableLoadedRow | null)[]> {
|
|
7
|
+
private readonly [CLAIMS_KEY];
|
|
8
|
+
toInput(input: SerializableLoadInput): SerializableLoadInput;
|
|
9
|
+
run(input: SerializableLoadInput): Promise<(SerializableLoadedRow | null)[]>;
|
|
10
|
+
toOutput(output: (SerializableLoadedRow | null)[]): (SerializableLoadedRow | null)[];
|
|
11
|
+
private read;
|
|
12
|
+
private fetch;
|
|
13
|
+
private populate;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=ORMLoadActivity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ORMLoadActivity.d.ts","sourceRoot":"","sources":["../../src/activities/ORMLoadActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAS,MAAM,qBAAqB,CAAA;AAYzD,OAAO,KAAK,EAEV,qBAAqB,EACrB,qBAAqB,EAEtB,MAAM,mBAAmB,CAAA;AAE1B,QAAA,MAAM,UAAU,eAAqC,CAAA;AAErD,qBAAa,eAAgB,SAAQ,YAAY,CAC/C;IAAC,KAAK,EAAE,qBAAqB;CAAC,EAC9B,qBAAqB,EACrB,CAAC,qBAAqB,GAAG,IAAI,CAAC,EAAE,EAChC,CAAC,qBAAqB,GAAG,IAAI,CAAC,EAAE,CACjC;IACC,OAAO,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAE3B;IAEK,OAAO,CAAC,KAAK,EAAE,qBAAqB,GAAG,qBAAqB;IAItD,GAAG,CAAC,KAAK,EAAE,qBAAqB;IAyBtC,QAAQ,CACb,MAAM,EAAE,CAAC,qBAAqB,GAAG,IAAI,CAAC,EAAE,GACvC,CAAC,qBAAqB,GAAG,IAAI,CAAC,EAAE;YAIrB,IAAI;YA0BJ,KAAK;YAUL,QAAQ;CAyDvB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { SyncActivity, Claim } from '@t4h.framework/core';
|
|
2
|
+
import { ORMClaim } from '../claims/ORMClaim.js';
|
|
3
|
+
import { getEntityByTableName, getEntityRelations, getEntityTableName, getInverseRelation, } from '../decorators/metadata.js';
|
|
4
|
+
import { Populate } from '../helpers/Populate.js';
|
|
5
|
+
import { toRefKey } from '../helpers/toRefKey.js';
|
|
6
|
+
const CLAIMS_KEY = Symbol('orm-load-activity-claims');
|
|
7
|
+
export class ORMLoadActivity extends SyncActivity {
|
|
8
|
+
[CLAIMS_KEY] = new Claim({
|
|
9
|
+
orm: ORMClaim,
|
|
10
|
+
});
|
|
11
|
+
toInput(input) {
|
|
12
|
+
return input;
|
|
13
|
+
}
|
|
14
|
+
async run(input) {
|
|
15
|
+
const { orm, table } = input;
|
|
16
|
+
const tree = Populate.toTree(input.populate);
|
|
17
|
+
if ('where' in input) {
|
|
18
|
+
const rows = await this.fetch({
|
|
19
|
+
orm,
|
|
20
|
+
table,
|
|
21
|
+
where: input.where,
|
|
22
|
+
orderBy: input.orderBy,
|
|
23
|
+
});
|
|
24
|
+
await this.populate(orm, table, rows, tree);
|
|
25
|
+
return rows;
|
|
26
|
+
}
|
|
27
|
+
const rows = await this.read(orm, table, input.refs);
|
|
28
|
+
await this.populate(orm, table, [...rows.values()], tree);
|
|
29
|
+
return input.refs.map(ref => rows.get(toRefKey(ref)) ?? null);
|
|
30
|
+
}
|
|
31
|
+
toOutput(output) {
|
|
32
|
+
return output;
|
|
33
|
+
}
|
|
34
|
+
async read(orm, table, refs) {
|
|
35
|
+
const unique = [...new Map(refs.map(ref => [toRefKey(ref), ref])).values()];
|
|
36
|
+
const rows = new Map();
|
|
37
|
+
if (!unique.length)
|
|
38
|
+
return rows;
|
|
39
|
+
const snapshots = await this[CLAIMS_KEY].orm.getSnapshots({
|
|
40
|
+
orm,
|
|
41
|
+
table,
|
|
42
|
+
refs: unique,
|
|
43
|
+
});
|
|
44
|
+
unique.forEach((ref, index) => {
|
|
45
|
+
const data = snapshots[index];
|
|
46
|
+
if (data)
|
|
47
|
+
rows.set(toRefKey(ref), { ref, data, relations: {} });
|
|
48
|
+
});
|
|
49
|
+
return rows;
|
|
50
|
+
}
|
|
51
|
+
async fetch(input) {
|
|
52
|
+
const refs = await this[CLAIMS_KEY].orm.find(input);
|
|
53
|
+
const rows = await this.read(input.orm, input.table, refs);
|
|
54
|
+
return refs.flatMap(ref => rows.get(toRefKey(ref)) ?? []);
|
|
55
|
+
}
|
|
56
|
+
async populate(orm, table, rows, tree) {
|
|
57
|
+
if (!rows.length)
|
|
58
|
+
return;
|
|
59
|
+
const entity = getEntityByTableName(table);
|
|
60
|
+
for (const relation of getEntityRelations(entity).values()) {
|
|
61
|
+
const nested = tree.get(relation.name);
|
|
62
|
+
if (!nested)
|
|
63
|
+
continue;
|
|
64
|
+
const target = getEntityTableName(relation.entity());
|
|
65
|
+
if (relation.kind === 'one-to-many') {
|
|
66
|
+
const mappedBy = getInverseRelation(entity, relation).name;
|
|
67
|
+
const children = await this.fetch({
|
|
68
|
+
orm,
|
|
69
|
+
table: target,
|
|
70
|
+
where: { [mappedBy]: { $in: rows.map(row => row.ref) } },
|
|
71
|
+
orderBy: relation.orderBy,
|
|
72
|
+
});
|
|
73
|
+
await this.populate(orm, target, children, nested);
|
|
74
|
+
const groups = Map.groupBy(children, child => toRefKey(child.data[mappedBy]));
|
|
75
|
+
for (const row of rows)
|
|
76
|
+
row.relations[relation.name] = groups.get(toRefKey(row.ref)) ?? [];
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const refs = rows.map(row => row.data[relation.name] ?? null);
|
|
80
|
+
const related = await this.read(orm, target, refs.filter(ref => ref !== null));
|
|
81
|
+
await this.populate(orm, target, [...related.values()], nested);
|
|
82
|
+
rows.forEach((row, index) => {
|
|
83
|
+
const ref = refs[index];
|
|
84
|
+
if (ref !== null)
|
|
85
|
+
row.relations[relation.name] = related.get(toRefKey(ref)) ?? null;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=ORMLoadActivity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ORMLoadActivity.js","sourceRoot":"","sources":["../../src/activities/ORMLoadActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAEzD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AASjD,MAAM,UAAU,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAA;AAErD,MAAM,OAAO,eAAgB,SAAQ,YAKpC;IACkB,CAAC,UAAU,CAAC,GAAG,IAAI,KAAK,CAAC;QACxC,GAAG,EAAE,QAAQ;KACd,CAAC,CAAA;IAEK,OAAO,CAAC,KAA4B;QACzC,OAAO,KAAK,CAAA;IACd,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,KAA4B;QAC3C,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;QAE5B,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAE5C,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;gBAC5B,GAAG;gBACH,KAAK;gBACL,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC,CAAA;YAEF,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;YAE3C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QAEpD,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;QAEzD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAA;IAC/D,CAAC;IAEM,QAAQ,CACb,MAAwC;QAExC,OAAO,MAAM,CAAA;IACf,CAAC;IAEO,KAAK,CAAC,IAAI,CAChB,GAAQ,EACR,KAAa,EACb,IAA0B;QAE1B,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;QAE3E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAiC,CAAA;QAErD,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QAE/B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;YACxD,GAAG;YACH,KAAK;YACL,IAAI,EAAE,MAAM;SACb,CAAC,CAAA;QAEF,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YAC5B,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;YAE7B,IAAI,IAAI;gBAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAA;QACjE,CAAC,CAAC,CAAA;QAEF,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,KAAK,CAAC,KAAK,CACjB,KAA4B;QAE5B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAEnD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAE1D,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IAC3D,CAAC;IAEO,KAAK,CAAC,QAAQ,CACpB,GAAQ,EACR,KAAa,EACb,IAA6B,EAC7B,IAAmB;QAEnB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAM;QAExB,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAA;QAE1C,KAAK,MAAM,QAAQ,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YAEtC,IAAI,CAAC,MAAM;gBAAE,SAAQ;YAErB,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;YAEpD,IAAI,QAAQ,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;gBACpC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAA;gBAE1D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;oBAChC,GAAG;oBACH,KAAK,EAAE,MAAM;oBACb,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE;oBACxD,OAAO,EAAE,QAAQ,CAAC,OAAO;iBAC1B,CAAC,CAAA;gBAEF,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;gBAElD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAC3C,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAE,CAAC,CAChC,CAAA;gBAED,KAAK,MAAM,GAAG,IAAI,IAAI;oBACpB,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;gBAEpE,SAAQ;YACV,CAAC;YAED,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAA;YAE7D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAC7B,GAAG,EACH,MAAM,EACN,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CACjC,CAAA;YAED,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;YAE/D,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;gBAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAE,CAAA;gBAExB,IAAI,GAAG,KAAK,IAAI;oBACd,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAA;YACrE,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SyncActivity } from '@t4h.framework/core';
|
|
2
|
+
import type { SerializableLoadRelationInput, SerializableRowRef } from '../typings/ORM.js';
|
|
3
|
+
declare const CLAIMS_KEY: unique symbol;
|
|
4
|
+
export declare class ORMLoadRelationActivity extends SyncActivity<[
|
|
5
|
+
input: SerializableLoadRelationInput
|
|
6
|
+
], SerializableLoadRelationInput, (SerializableRowRef | null)[], (SerializableRowRef | null)[]> {
|
|
7
|
+
private readonly [CLAIMS_KEY];
|
|
8
|
+
toInput(input: SerializableLoadRelationInput): SerializableLoadRelationInput;
|
|
9
|
+
run({ orm, table, refs, relation: name, }: SerializableLoadRelationInput): Promise<(SerializableRowRef | null)[]>;
|
|
10
|
+
toOutput(output: (SerializableRowRef | null)[]): (SerializableRowRef | null)[];
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=ORMLoadRelationActivity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ORMLoadRelationActivity.d.ts","sourceRoot":"","sources":["../../src/activities/ORMLoadRelationActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAS,MAAM,qBAAqB,CAAA;AAOzD,OAAO,KAAK,EACV,6BAA6B,EAC7B,kBAAkB,EACnB,MAAM,mBAAmB,CAAA;AAE1B,QAAA,MAAM,UAAU,eAA8C,CAAA;AAE9D,qBAAa,uBAAwB,SAAQ,YAAY,CACvD;IAAC,KAAK,EAAE,6BAA6B;CAAC,EACtC,6BAA6B,EAC7B,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAAE,EAC7B,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAAE,CAC9B;IACC,OAAO,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAE3B;IAEK,OAAO,CACZ,KAAK,EAAE,6BAA6B,GACnC,6BAA6B;IAInB,GAAG,CAAC,EACf,GAAG,EACH,KAAK,EACL,IAAI,EACJ,QAAQ,EAAE,IAAI,GACf,EAAE,6BAA6B,GAAG,OAAO,CAAC,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAAE,CAAC;IAWlE,QAAQ,CACb,MAAM,EAAE,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAAE,GACpC,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAAE;CAGjC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SyncActivity, Claim } from '@t4h.framework/core';
|
|
2
|
+
import { ORMClaim } from '../claims/ORMClaim.js';
|
|
3
|
+
import { getEntityByTableName, getEntityRelations, } from '../decorators/metadata.js';
|
|
4
|
+
const CLAIMS_KEY = Symbol('orm-load-relation-activity-claims');
|
|
5
|
+
export class ORMLoadRelationActivity extends SyncActivity {
|
|
6
|
+
[CLAIMS_KEY] = new Claim({
|
|
7
|
+
orm: ORMClaim,
|
|
8
|
+
});
|
|
9
|
+
toInput(input) {
|
|
10
|
+
return input;
|
|
11
|
+
}
|
|
12
|
+
async run({ orm, table, refs, relation: name, }) {
|
|
13
|
+
const relation = getEntityRelations(getEntityByTableName(table)).get(name);
|
|
14
|
+
if (relation?.kind !== 'many-to-one')
|
|
15
|
+
throw new Error(`Table "${table}" has no @ManyToOne "${name}"`);
|
|
16
|
+
const rows = await this[CLAIMS_KEY].orm.getSnapshots({ orm, table, refs });
|
|
17
|
+
return rows.map(row => row?.[name] ?? null);
|
|
18
|
+
}
|
|
19
|
+
toOutput(output) {
|
|
20
|
+
return output;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=ORMLoadRelationActivity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ORMLoadRelationActivity.js","sourceRoot":"","sources":["../../src/activities/ORMLoadRelationActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAEzD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EACL,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,2BAA2B,CAAA;AAMlC,MAAM,UAAU,GAAG,MAAM,CAAC,mCAAmC,CAAC,CAAA;AAE9D,MAAM,OAAO,uBAAwB,SAAQ,YAK5C;IACkB,CAAC,UAAU,CAAC,GAAG,IAAI,KAAK,CAAC;QACxC,GAAG,EAAE,QAAQ;KACd,CAAC,CAAA;IAEK,OAAO,CACZ,KAAoC;QAEpC,OAAO,KAAK,CAAA;IACd,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,EACf,GAAG,EACH,KAAK,EACL,IAAI,EACJ,QAAQ,EAAE,IAAI,GACgB;QAC9B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAE1E,IAAI,QAAQ,EAAE,IAAI,KAAK,aAAa;YAClC,MAAM,IAAI,KAAK,CAAC,UAAU,KAAK,wBAAwB,IAAI,GAAG,CAAC,CAAA;QAEjE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAE1E,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAA;IAC7C,CAAC;IAEM,QAAQ,CACb,MAAqC;QAErC,OAAO,MAAM,CAAA;IACf,CAAC;CACF"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import type { SerializableCreateInput, SerializableFindInput, SerializableGetSnapshotInput, SerializableRemoveInput, SerializableDeleteInput, SerializableUpdateInput, SerializableUpsertInput, SerializableRowRef, SerializedRow } from '../typings/ORM.js';
|
|
1
|
+
import type { SerializableCreateInput, SerializableFindInput, SerializableGetSnapshotInput, SerializableGetSnapshotsInput, SerializableRemoveInput, SerializableDeleteInput, SerializableUpdateInput, SerializableUpsertInput, SerializableRowRef, SerializedRow } from '../typings/ORM.js';
|
|
2
|
+
/**
|
|
3
|
+
* A @ManyToOne column must come back from `getSnapshot(s)` exactly as the ref
|
|
4
|
+
* `create` / `find` returned (same type, same key order): relations match rows
|
|
5
|
+
* by comparing the two.
|
|
6
|
+
*/
|
|
2
7
|
export declare abstract class ORMClaim<R extends SerializableRowRef> {
|
|
3
8
|
abstract find(input: SerializableFindInput): R[] | Promise<R[]>;
|
|
4
9
|
abstract create(input: SerializableCreateInput): R[] | Promise<R[]>;
|
|
5
10
|
abstract getSnapshot(input: SerializableGetSnapshotInput<R>): SerializedRow | null | Promise<SerializedRow | null>;
|
|
11
|
+
abstract getSnapshots(input: SerializableGetSnapshotsInput<R>): (SerializedRow | null)[] | Promise<(SerializedRow | null)[]>;
|
|
6
12
|
abstract update(input: SerializableUpdateInput<R>): void | Promise<void>;
|
|
7
13
|
abstract remove(input: SerializableRemoveInput<R>): void | Promise<void>;
|
|
8
14
|
upsert({ orm, table, conflictOn, data, }: SerializableUpsertInput): Promise<R[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ORMClaim.d.ts","sourceRoot":"","sources":["../../src/claims/ORMClaim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,aAAa,EACd,MAAM,mBAAmB,CAAA;AAE1B,8BAAsB,QAAQ,CAAC,CAAC,SAAS,kBAAkB;aACzC,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAEtD,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAE1D,WAAW,CACzB,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,GACrC,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;aAEvC,MAAM,CACpB,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAChC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;aAEP,MAAM,CACpB,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAChC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAEV,MAAM,CAAC,EAClB,GAAG,EACH,KAAK,EACL,UAAU,EACV,IAAI,GACL,EAAE,uBAAuB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAwBzB,MAAM,CACpB,KAAK,EAAE,uBAAuB,GAC7B,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAC5B"}
|
|
1
|
+
{"version":3,"file":"ORMClaim.d.ts","sourceRoot":"","sources":["../../src/claims/ORMClaim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACrB,4BAA4B,EAC5B,6BAA6B,EAC7B,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,aAAa,EACd,MAAM,mBAAmB,CAAA;AAE1B;;;;GAIG;AACH,8BAAsB,QAAQ,CAAC,CAAC,SAAS,kBAAkB;aACzC,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAEtD,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAE1D,WAAW,CACzB,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,GACrC,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;aAEvC,YAAY,CAC1B,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,GACtC,CAAC,aAAa,GAAG,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,aAAa,GAAG,IAAI,CAAC,EAAE,CAAC;aAE/C,MAAM,CACpB,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAChC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;aAEP,MAAM,CACpB,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAChC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAEV,MAAM,CAAC,EAClB,GAAG,EACH,KAAK,EACL,UAAU,EACV,IAAI,GACL,EAAE,uBAAuB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;aAwBzB,MAAM,CACpB,KAAK,EAAE,uBAAuB,GAC7B,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAC5B"}
|
package/dist/claims/ORMClaim.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A @ManyToOne column must come back from `getSnapshot(s)` exactly as the ref
|
|
3
|
+
* `create` / `find` returned (same type, same key order): relations match rows
|
|
4
|
+
* by comparing the two.
|
|
5
|
+
*/
|
|
1
6
|
export class ORMClaim {
|
|
2
7
|
async upsert({ orm, table, conflictOn, data, }) {
|
|
3
8
|
const refs = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ORMClaim.js","sourceRoot":"","sources":["../../src/claims/ORMClaim.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ORMClaim.js","sourceRoot":"","sources":["../../src/claims/ORMClaim.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,MAAM,OAAgB,QAAQ;IAqBrB,KAAK,CAAC,MAAM,CAAC,EAClB,GAAG,EACH,KAAK,EACL,UAAU,EACV,IAAI,GACoB;QACxB,MAAM,IAAI,GAAQ,EAAE,CAAA;QAEpB,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAC9B,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAE,CAAC,CAAC,CAC3C,CAAA;YAED,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;YAEzE,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;gBAEjE,SAAQ;YACV,CAAC;YAED,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;YAEpD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAChB,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CAKF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EntityConstructor } from '../typings/ORM.js';
|
|
2
|
+
export interface ManyToOneOptions {
|
|
3
|
+
nullable?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function ManyToOne(entity: () => EntityConstructor, options?: ManyToOneOptions): PropertyDecorator;
|
|
6
|
+
//# sourceMappingURL=ManyToOne.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManyToOne.d.ts","sourceRoot":"","sources":["../../src/decorators/ManyToOne.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,iBAAiB,EAC/B,OAAO,CAAC,EAAE,gBAAgB,GACzB,iBAAiB,CAenB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getEntityMetadata } from './metadata.js';
|
|
2
|
+
export function ManyToOne(entity, options) {
|
|
3
|
+
return (target, propertyKey) => {
|
|
4
|
+
const metadata = getEntityMetadata(target.constructor);
|
|
5
|
+
const name = propertyKey;
|
|
6
|
+
metadata.indexes.push({ properties: [name] });
|
|
7
|
+
metadata.relations.set(name, {
|
|
8
|
+
name,
|
|
9
|
+
kind: 'many-to-one',
|
|
10
|
+
entity,
|
|
11
|
+
nullable: options?.nullable,
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ManyToOne.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManyToOne.js","sourceRoot":"","sources":["../../src/decorators/ManyToOne.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAOjD,MAAM,UAAU,SAAS,CACvB,MAA+B,EAC/B,OAA0B;IAE1B,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAA4B,CAAC,CAAA;QAEvE,MAAM,IAAI,GAAG,WAAqB,CAAA;QAElC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAE7C,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE;YAC3B,IAAI;YACJ,IAAI,EAAE,aAAa;YACnB,MAAM;YACN,QAAQ,EAAE,OAAO,EAAE,QAAQ;SAC5B,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { EntityConstructor } from '../typings/ORM.js';
|
|
2
|
+
export interface OneToManyOptions {
|
|
3
|
+
mappedBy: string;
|
|
4
|
+
orderBy?: Record<string, 'asc' | 'desc'>;
|
|
5
|
+
}
|
|
6
|
+
export declare function OneToMany(entity: () => EntityConstructor, options: OneToManyOptions): PropertyDecorator;
|
|
7
|
+
//# sourceMappingURL=OneToMany.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OneToMany.d.ts","sourceRoot":"","sources":["../../src/decorators/OneToMany.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC,CAAA;CACzC;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,iBAAiB,EAC/B,OAAO,EAAE,gBAAgB,GACxB,iBAAiB,CAmBnB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getEntityMetadata } from './metadata.js';
|
|
2
|
+
export function OneToMany(entity, options) {
|
|
3
|
+
return (target, propertyKey) => {
|
|
4
|
+
if (!options?.mappedBy)
|
|
5
|
+
throw new Error(`@OneToMany "${String(propertyKey)}" requires a mappedBy property`);
|
|
6
|
+
const metadata = getEntityMetadata(target.constructor);
|
|
7
|
+
const name = propertyKey;
|
|
8
|
+
metadata.relations.set(name, {
|
|
9
|
+
name,
|
|
10
|
+
kind: 'one-to-many',
|
|
11
|
+
entity,
|
|
12
|
+
mappedBy: options.mappedBy,
|
|
13
|
+
orderBy: options.orderBy,
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=OneToMany.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OneToMany.js","sourceRoot":"","sources":["../../src/decorators/OneToMany.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAQjD,MAAM,UAAU,SAAS,CACvB,MAA+B,EAC/B,OAAyB;IAEzB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC7B,IAAI,CAAC,OAAO,EAAE,QAAQ;YACpB,MAAM,IAAI,KAAK,CACb,eAAe,MAAM,CAAC,WAAW,CAAC,gCAAgC,CACnE,CAAA;QAEH,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAA4B,CAAC,CAAA;QAEvE,MAAM,IAAI,GAAG,WAAqB,CAAA;QAElC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE;YAC3B,IAAI;YACJ,IAAI,EAAE,aAAa;YACnB,MAAM;YACN,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -3,8 +3,23 @@ import type { IndexMetadata } from './Index.js';
|
|
|
3
3
|
export interface EntityMetadata {
|
|
4
4
|
tableName?: string;
|
|
5
5
|
properties: Map<string, PropertyMetadata>;
|
|
6
|
+
relations: Map<string, RelationMetadata>;
|
|
6
7
|
indexes: Array<IndexMetadata>;
|
|
7
8
|
}
|
|
9
|
+
export interface ManyToOneMetadata {
|
|
10
|
+
name: string;
|
|
11
|
+
kind: 'many-to-one';
|
|
12
|
+
entity: () => new (...args: any[]) => any;
|
|
13
|
+
nullable?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface OneToManyMetadata {
|
|
16
|
+
name: string;
|
|
17
|
+
kind: 'one-to-many';
|
|
18
|
+
entity: () => new (...args: any[]) => any;
|
|
19
|
+
mappedBy: string;
|
|
20
|
+
orderBy?: Record<string, 'asc' | 'desc'>;
|
|
21
|
+
}
|
|
22
|
+
export type RelationMetadata = ManyToOneMetadata | OneToManyMetadata;
|
|
8
23
|
export interface PropertyMetadata {
|
|
9
24
|
name: string;
|
|
10
25
|
type?: string;
|
|
@@ -17,4 +32,6 @@ export declare function getEntityTableName(target: new (...args: any[]) => any):
|
|
|
17
32
|
export declare function getEntityProperties(target: new (...args: any[]) => any): Map<string, PropertyMetadata>;
|
|
18
33
|
export declare function registerEntity(target: new (...args: any[]) => any): void;
|
|
19
34
|
export declare function getEntityByTableName(tableName: string): new (...args: any[]) => any;
|
|
35
|
+
export declare function getEntityRelations(target: new (...args: any[]) => any): Map<string, RelationMetadata>;
|
|
36
|
+
export declare function getInverseRelation(owner: new (...args: any[]) => any, relation: OneToManyMetadata): ManyToOneMetadata;
|
|
20
37
|
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/decorators/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACzC,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAMD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,cAAc,CAShB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,MAAM,CAIR;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAE/B;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,IAAI,CAExE;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,GAChB,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAS7B"}
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/decorators/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACzC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACxC,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,aAAa,CAAA;IACnB,MAAM,EAAE,MAAM,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,aAAa,CAAA;IACnB,MAAM,EAAE,MAAM,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC,CAAA;CACzC;AAED,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,CAAA;AAEpE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAMD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,cAAc,CAShB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,MAAM,CAIR;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAE/B;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,IAAI,CAExE;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,GAChB,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAS7B;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAClC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAE/B;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAClC,QAAQ,EAAE,iBAAiB,GAC1B,iBAAiB,CAWnB"}
|
|
@@ -3,7 +3,7 @@ const entityRegistry = new Map();
|
|
|
3
3
|
export function getEntityMetadata(target) {
|
|
4
4
|
let metadata = entityMetadataMap.get(target.prototype);
|
|
5
5
|
if (!metadata) {
|
|
6
|
-
metadata = { properties: new Map(), indexes: [] };
|
|
6
|
+
metadata = { properties: new Map(), relations: new Map(), indexes: [] };
|
|
7
7
|
entityMetadataMap.set(target.prototype, metadata);
|
|
8
8
|
}
|
|
9
9
|
return metadata;
|
|
@@ -24,4 +24,14 @@ export function getEntityByTableName(tableName) {
|
|
|
24
24
|
throw new Error(`Could not find an entity for table "${tableName}": is it decorated with @Entity?`);
|
|
25
25
|
return entity;
|
|
26
26
|
}
|
|
27
|
+
export function getEntityRelations(target) {
|
|
28
|
+
return getEntityMetadata(target).relations;
|
|
29
|
+
}
|
|
30
|
+
export function getInverseRelation(owner, relation) {
|
|
31
|
+
const target = relation.entity();
|
|
32
|
+
const inverse = getEntityRelations(target).get(relation.mappedBy);
|
|
33
|
+
if (inverse?.kind !== 'many-to-one' || inverse.entity() !== owner)
|
|
34
|
+
throw new Error(`Relation "${owner.name}.${relation.name}" is mapped by "${target.name}.${relation.mappedBy}", which must be a @ManyToOne to ${owner.name}`);
|
|
35
|
+
return inverse;
|
|
36
|
+
}
|
|
27
37
|
//# sourceMappingURL=metadata.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/decorators/metadata.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/decorators/metadata.ts"],"names":[],"mappings":"AAoCA,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAA0B,CAAA;AAE/D,MAAM,cAAc,GAAG,IAAI,GAAG,EAAuC,CAAA;AAErE,MAAM,UAAU,iBAAiB,CAC/B,MAAmC;IAEnC,IAAI,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAEtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,EAAE,UAAU,EAAE,IAAI,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;QACvE,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IACnD,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,MAAmC;IAEnC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAE1C,OAAO,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI,CAAA;AAC1C,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,MAAmC;IAEnC,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,UAAU,CAAA;AAC7C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAmC;IAChE,cAAc,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,SAAiB;IAEjB,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IAE5C,IAAI,CAAC,MAAM;QACT,MAAM,IAAI,KAAK,CACb,uCAAuC,SAAS,kCAAkC,CACnF,CAAA;IAEH,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,MAAmC;IAEnC,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,SAAS,CAAA;AAC5C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,KAAkC,EAClC,QAA2B;IAE3B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAA;IAEhC,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAEjE,IAAI,OAAO,EAAE,IAAI,KAAK,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,KAAK,KAAK;QAC/D,MAAM,IAAI,KAAK,CACb,aAAa,KAAK,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,mBAAmB,MAAM,CAAC,IAAI,IAAI,QAAQ,CAAC,QAAQ,oCAAoC,KAAK,CAAC,IAAI,EAAE,CAC5I,CAAA;IAEH,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { EntityConstructor } from '../typings/ORM.js';
|
|
2
|
+
export declare namespace Insert {
|
|
3
|
+
type Row = Record<string, unknown>;
|
|
4
|
+
interface Parents {
|
|
5
|
+
relation: string;
|
|
6
|
+
plan: Plan;
|
|
7
|
+
rows: number[];
|
|
8
|
+
}
|
|
9
|
+
interface Children {
|
|
10
|
+
relation: string;
|
|
11
|
+
plan: Plan;
|
|
12
|
+
parents: number[];
|
|
13
|
+
}
|
|
14
|
+
interface Plan {
|
|
15
|
+
entity: EntityConstructor;
|
|
16
|
+
rows: Row[];
|
|
17
|
+
parents: Parents[];
|
|
18
|
+
children: Children[];
|
|
19
|
+
}
|
|
20
|
+
function plan(entity: EntityConstructor, data: Row[], filled?: string): Promise<Plan>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=Insert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Insert.d.ts","sourceRoot":"","sources":["../../src/helpers/Insert.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,mBAAmB,CAAA;AAEzE,yBAAiB,MAAM,CAAC;IACtB,KAAY,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAEzC,UAAiB,OAAO;QACtB,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,EAAE,IAAI,CAAA;QACV,IAAI,EAAE,MAAM,EAAE,CAAA;KACf;IAED,UAAiB,QAAQ;QACvB,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,EAAE,IAAI,CAAA;QACV,OAAO,EAAE,MAAM,EAAE,CAAA;KAClB;IAED,UAAiB,IAAI;QACnB,MAAM,EAAE,iBAAiB,CAAA;QACzB,IAAI,EAAE,GAAG,EAAE,CAAA;QACX,OAAO,EAAE,OAAO,EAAE,CAAA;QAClB,QAAQ,EAAE,QAAQ,EAAE,CAAA;KACrB;IAQD,SAAsB,IAAI,CACxB,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,GAAG,EAAE,EACX,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA0Ff;CACF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { isPlainObject } from './isPlainObject.js';
|
|
2
|
+
import { Serialize } from './Serialize.js';
|
|
3
|
+
import { applyDefaultProperties } from '../constraints/apply-default-properties.js';
|
|
4
|
+
import { assertConstraints } from '../constraints/assert-constraints.js';
|
|
5
|
+
import { getEntityMetadata, getEntityRelations, getInverseRelation, } from '../decorators/metadata.js';
|
|
6
|
+
import { ConstraintError } from '../errors/ConstraintError.js';
|
|
7
|
+
export var Insert;
|
|
8
|
+
(function (Insert) {
|
|
9
|
+
const group = (groups, key, create) => {
|
|
10
|
+
if (!groups.has(key))
|
|
11
|
+
groups.set(key, create());
|
|
12
|
+
return groups.get(key);
|
|
13
|
+
};
|
|
14
|
+
async function plan(entity, data, filled) {
|
|
15
|
+
const relations = getEntityRelations(entity);
|
|
16
|
+
const parents = new Map();
|
|
17
|
+
const children = new Map();
|
|
18
|
+
const rows = data.map((raw, index) => {
|
|
19
|
+
const row = { ...raw };
|
|
20
|
+
if (filled && row[filled] !== undefined)
|
|
21
|
+
throw new ConstraintError(`Property "${filled}" is set by the row it is nested in`);
|
|
22
|
+
const later = filled ? [filled] : [];
|
|
23
|
+
for (const relation of relations.values()) {
|
|
24
|
+
const { name } = relation;
|
|
25
|
+
const value = row[name];
|
|
26
|
+
if (relation.kind === 'many-to-one') {
|
|
27
|
+
if (!isPlainObject(value))
|
|
28
|
+
continue;
|
|
29
|
+
const parent = group(parents, name, () => ({ data: [], rows: [] }));
|
|
30
|
+
parent.data.push(value);
|
|
31
|
+
parent.rows.push(index);
|
|
32
|
+
later.push(name);
|
|
33
|
+
delete row[name];
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (value === undefined)
|
|
37
|
+
continue;
|
|
38
|
+
if (!Array.isArray(value) || !value.every(isPlainObject))
|
|
39
|
+
throw new ConstraintError(`Property "${name}" takes the data of new ${relation.entity().name} rows`);
|
|
40
|
+
const child = group(children, name, () => ({ data: [], parents: [] }));
|
|
41
|
+
for (const item of value) {
|
|
42
|
+
child.data.push(item);
|
|
43
|
+
child.parents.push(index);
|
|
44
|
+
}
|
|
45
|
+
delete row[name];
|
|
46
|
+
}
|
|
47
|
+
Serialize.assertRelations(entity, [row], { except: later });
|
|
48
|
+
return row;
|
|
49
|
+
});
|
|
50
|
+
const defaulted = applyDefaultProperties(rows, getEntityMetadata(entity));
|
|
51
|
+
await assertConstraints(entity, defaulted);
|
|
52
|
+
return {
|
|
53
|
+
entity,
|
|
54
|
+
rows: defaulted,
|
|
55
|
+
parents: await Promise.all([...parents].map(async ([relation, parent]) => ({
|
|
56
|
+
relation,
|
|
57
|
+
plan: await plan(relations.get(relation).entity(), parent.data),
|
|
58
|
+
rows: parent.rows,
|
|
59
|
+
}))),
|
|
60
|
+
children: await Promise.all([...children].map(async ([name, child]) => {
|
|
61
|
+
const relation = relations.get(name);
|
|
62
|
+
const inverse = getInverseRelation(entity, relation).name;
|
|
63
|
+
return {
|
|
64
|
+
relation: inverse,
|
|
65
|
+
plan: await plan(relation.entity(), child.data, inverse),
|
|
66
|
+
parents: child.parents,
|
|
67
|
+
};
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
Insert.plan = plan;
|
|
72
|
+
})(Insert || (Insert = {}));
|
|
73
|
+
//# sourceMappingURL=Insert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Insert.js","sourceRoot":"","sources":["../../src/helpers/Insert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EntityConstructor } from '../typings/ORM.js';
|
|
2
|
+
import type { RelationKey, Related } from '../typings/Relations.js';
|
|
3
|
+
type Depth = [never, 0, 1, 2, 3];
|
|
4
|
+
export type Populate<T, D extends number = 4> = [D] extends [never] ? never : {
|
|
5
|
+
[K in RelationKey<T>]: K | `${K}.${Populate<Related<T[K]>, Depth[D]>}`;
|
|
6
|
+
}[RelationKey<T>];
|
|
7
|
+
export declare namespace Populate {
|
|
8
|
+
type Tree = Map<string, Tree>;
|
|
9
|
+
function toTree(paths: readonly string[]): Tree;
|
|
10
|
+
function assert(entity: EntityConstructor, paths: readonly string[]): void;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=Populate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Populate.d.ts","sourceRoot":"","sources":["../../src/helpers/Populate.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAEnE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;AAEhC,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC/D,KAAK,GACL;KACG,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;CACvE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAErB,yBAAiB,QAAQ,CAAC;IACxB,KAAY,IAAI,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAEpC,SAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAcrD;IAED,SAAgB,MAAM,CACpB,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,IAAI,CAiBN;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getEntityRelations, } from '../decorators/metadata.js';
|
|
2
|
+
export var Populate;
|
|
3
|
+
(function (Populate) {
|
|
4
|
+
function toTree(paths) {
|
|
5
|
+
const tree = new Map();
|
|
6
|
+
for (const path of paths) {
|
|
7
|
+
let node = tree;
|
|
8
|
+
for (const segment of path.split('.')) {
|
|
9
|
+
if (!node.has(segment))
|
|
10
|
+
node.set(segment, new Map());
|
|
11
|
+
node = node.get(segment);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return tree;
|
|
15
|
+
}
|
|
16
|
+
Populate.toTree = toTree;
|
|
17
|
+
function assert(entity, paths) {
|
|
18
|
+
const visit = (target, tree, at) => {
|
|
19
|
+
const relations = getEntityRelations(target);
|
|
20
|
+
for (const [name, nested] of tree) {
|
|
21
|
+
const relation = relations.get(name);
|
|
22
|
+
if (!relation)
|
|
23
|
+
throw new Error(`Cannot populate "${at}${name}": "${target.name}" has no relation "${name}"`);
|
|
24
|
+
visit(relation.entity(), nested, `${at}${name}.`);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
visit(entity, toTree(paths), '');
|
|
28
|
+
}
|
|
29
|
+
Populate.assert = assert;
|
|
30
|
+
})(Populate || (Populate = {}));
|
|
31
|
+
//# sourceMappingURL=Populate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Populate.js","sourceRoot":"","sources":["../../src/helpers/Populate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAEnB,MAAM,2BAA2B,CAAA;AAYlC,MAAM,KAAW,QAAQ,CAwCxB;AAxCD,WAAiB,QAAQ;IAGvB,SAAgB,MAAM,CAAC,KAAwB;QAC7C,MAAM,IAAI,GAAS,IAAI,GAAG,EAAE,CAAA;QAE5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,GAAG,IAAI,CAAA;YAEf,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;oBAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,EAAE,CAAC,CAAA;gBAEpD,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAE,CAAA;YAC3B,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAde,eAAM,SAcrB,CAAA;IAED,SAAgB,MAAM,CACpB,MAAyB,EACzB,KAAwB;QAExB,MAAM,KAAK,GAAG,CAAC,MAAyB,EAAE,IAAU,EAAE,EAAU,EAAE,EAAE;YAClE,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;YAE5C,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBAClC,MAAM,QAAQ,GAAiC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBAElE,IAAI,CAAC,QAAQ;oBACX,MAAM,IAAI,KAAK,CACb,oBAAoB,EAAE,GAAG,IAAI,OAAO,MAAM,CAAC,IAAI,sBAAsB,IAAI,GAAG,CAC7E,CAAA;gBAEH,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,GAAG,CAAC,CAAA;YACnD,CAAC;QACH,CAAC,CAAA;QAED,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAA;IAClC,CAAC;IApBe,eAAM,SAoBrB,CAAA;AACH,CAAC,EAxCgB,QAAQ,KAAR,QAAQ,QAwCxB"}
|