@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.
Files changed (83) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +37 -2
  3. package/dist/activities/ORMLoadActivity.d.ts +16 -0
  4. package/dist/activities/ORMLoadActivity.d.ts.map +1 -0
  5. package/dist/activities/ORMLoadActivity.js +90 -0
  6. package/dist/activities/ORMLoadActivity.js.map +1 -0
  7. package/dist/activities/ORMLoadRelationActivity.d.ts +13 -0
  8. package/dist/activities/ORMLoadRelationActivity.d.ts.map +1 -0
  9. package/dist/activities/ORMLoadRelationActivity.js +23 -0
  10. package/dist/activities/ORMLoadRelationActivity.js.map +1 -0
  11. package/dist/claims/ORMClaim.d.ts +7 -1
  12. package/dist/claims/ORMClaim.d.ts.map +1 -1
  13. package/dist/claims/ORMClaim.js +5 -0
  14. package/dist/claims/ORMClaim.js.map +1 -1
  15. package/dist/decorators/ManyToOne.d.ts +6 -0
  16. package/dist/decorators/ManyToOne.d.ts.map +1 -0
  17. package/dist/decorators/ManyToOne.js +15 -0
  18. package/dist/decorators/ManyToOne.js.map +1 -0
  19. package/dist/decorators/OneToMany.d.ts +7 -0
  20. package/dist/decorators/OneToMany.d.ts.map +1 -0
  21. package/dist/decorators/OneToMany.js +17 -0
  22. package/dist/decorators/OneToMany.js.map +1 -0
  23. package/dist/decorators/metadata.d.ts +17 -0
  24. package/dist/decorators/metadata.d.ts.map +1 -1
  25. package/dist/decorators/metadata.js +11 -1
  26. package/dist/decorators/metadata.js.map +1 -1
  27. package/dist/helpers/Insert.d.ts +22 -0
  28. package/dist/helpers/Insert.d.ts.map +1 -0
  29. package/dist/helpers/Insert.js +73 -0
  30. package/dist/helpers/Insert.js.map +1 -0
  31. package/dist/helpers/Populate.d.ts +13 -0
  32. package/dist/helpers/Populate.d.ts.map +1 -0
  33. package/dist/helpers/Populate.js +31 -0
  34. package/dist/helpers/Populate.js.map +1 -0
  35. package/dist/helpers/Serialize.d.ts +11 -0
  36. package/dist/helpers/Serialize.d.ts.map +1 -0
  37. package/dist/helpers/Serialize.js +60 -0
  38. package/dist/helpers/Serialize.js.map +1 -0
  39. package/dist/helpers/hydrateEntity.d.ts +4 -0
  40. package/dist/helpers/hydrateEntity.d.ts.map +1 -0
  41. package/dist/helpers/hydrateEntity.js +30 -0
  42. package/dist/helpers/hydrateEntity.js.map +1 -0
  43. package/dist/helpers/isPlainObject.d.ts +2 -0
  44. package/dist/helpers/isPlainObject.d.ts.map +1 -0
  45. package/dist/helpers/isPlainObject.js +7 -0
  46. package/dist/helpers/isPlainObject.js.map +1 -0
  47. package/dist/helpers/refs.d.ts +5 -0
  48. package/dist/helpers/refs.d.ts.map +1 -0
  49. package/dist/helpers/refs.js +3 -0
  50. package/dist/helpers/refs.js.map +1 -0
  51. package/dist/helpers/toRefKey.d.ts +3 -0
  52. package/dist/helpers/toRefKey.d.ts.map +1 -0
  53. package/dist/helpers/toRefKey.js +4 -0
  54. package/dist/helpers/toRefKey.js.map +1 -0
  55. package/dist/models/MapCollection.d.ts +46 -0
  56. package/dist/models/MapCollection.d.ts.map +1 -0
  57. package/dist/models/MapCollection.js +126 -0
  58. package/dist/models/MapCollection.js.map +1 -0
  59. package/dist/models/ORM.d.ts +16 -3
  60. package/dist/models/ORM.d.ts.map +1 -1
  61. package/dist/models/ORM.js +43 -13
  62. package/dist/models/ORM.js.map +1 -1
  63. package/dist/models/Ref.d.ts +8 -1
  64. package/dist/models/Ref.d.ts.map +1 -1
  65. package/dist/models/Ref.js +17 -14
  66. package/dist/models/Ref.js.map +1 -1
  67. package/dist/models/RefCollection.d.ts +10 -1
  68. package/dist/models/RefCollection.d.ts.map +1 -1
  69. package/dist/models/RefCollection.js +62 -2
  70. package/dist/models/RefCollection.js.map +1 -1
  71. package/dist/orm.d.ts +6 -0
  72. package/dist/orm.d.ts.map +1 -1
  73. package/dist/orm.js +6 -0
  74. package/dist/orm.js.map +1 -1
  75. package/dist/typings/FindWhere.d.ts +2 -1
  76. package/dist/typings/FindWhere.d.ts.map +1 -1
  77. package/dist/typings/ORM.d.ts +42 -4
  78. package/dist/typings/ORM.d.ts.map +1 -1
  79. package/dist/typings/Relations.d.ts +27 -0
  80. package/dist/typings/Relations.d.ts.map +1 -0
  81. package/dist/typings/Relations.js +2 -0
  82. package/dist/typings/Relations.js.map +1 -0
  83. 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.map(ref => ref.getSnapshot())
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":"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"}
@@ -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"}
@@ -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":"AAYA,MAAM,OAAgB,QAAQ;IAiBrB,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"}
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":"AAkBA,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,OAAO,EAAE,EAAE,EAAE,CAAA;QACjD,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"}
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"}