joist-orm 0.1.538 → 1.0.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 (221) hide show
  1. package/build/{BaseEntity.d.ts → src/BaseEntity.d.ts} +2 -1
  2. package/build/{BaseEntity.js → src/BaseEntity.js} +13 -9
  3. package/build/src/BaseEntity.js.map +1 -0
  4. package/build/{EntityManager.d.ts → src/EntityManager.d.ts} +139 -110
  5. package/build/{EntityManager.js → src/EntityManager.js} +281 -262
  6. package/build/src/EntityManager.js.map +1 -0
  7. package/build/{QueryBuilder.d.ts → src/QueryBuilder.d.ts} +53 -3
  8. package/build/src/QueryBuilder.js +341 -0
  9. package/build/src/QueryBuilder.js.map +1 -0
  10. package/build/src/Todo.d.ts +25 -0
  11. package/build/src/Todo.js +52 -0
  12. package/build/src/Todo.js.map +1 -0
  13. package/build/src/changes.d.ts +34 -0
  14. package/build/src/changes.js +37 -0
  15. package/build/src/changes.js.map +1 -0
  16. package/build/src/config.d.ts +43 -0
  17. package/build/src/config.js +114 -0
  18. package/build/src/config.js.map +1 -0
  19. package/build/{createOrUpdatePartial.d.ts → src/createOrUpdatePartial.d.ts} +2 -1
  20. package/build/{createOrUpdatePartial.js → src/createOrUpdatePartial.js} +42 -10
  21. package/build/src/createOrUpdatePartial.js.map +1 -0
  22. package/build/src/dataloaders/findDataLoader.d.ts +5 -0
  23. package/build/src/dataloaders/findDataLoader.js +28 -0
  24. package/build/src/dataloaders/findDataLoader.js.map +1 -0
  25. package/build/src/dataloaders/loadDataLoader.d.ts +3 -0
  26. package/build/src/dataloaders/loadDataLoader.js +37 -0
  27. package/build/src/dataloaders/loadDataLoader.js.map +1 -0
  28. package/build/src/dataloaders/manyToManyDataLoader.d.ts +5 -0
  29. package/build/src/dataloaders/manyToManyDataLoader.js +78 -0
  30. package/build/src/dataloaders/manyToManyDataLoader.js.map +1 -0
  31. package/build/src/dataloaders/manyToManyFindDataLoader.d.ts +5 -0
  32. package/build/src/dataloaders/manyToManyFindDataLoader.js +33 -0
  33. package/build/src/dataloaders/manyToManyFindDataLoader.js.map +1 -0
  34. package/build/src/dataloaders/oneToManyDataLoader.d.ts +4 -0
  35. package/build/src/dataloaders/oneToManyDataLoader.js +40 -0
  36. package/build/src/dataloaders/oneToManyDataLoader.js.map +1 -0
  37. package/build/src/dataloaders/oneToManyFindDataLoader.d.ts +5 -0
  38. package/build/src/dataloaders/oneToManyFindDataLoader.js +32 -0
  39. package/build/src/dataloaders/oneToManyFindDataLoader.js.map +1 -0
  40. package/build/src/dataloaders/oneToOneDataLoader.d.ts +4 -0
  41. package/build/src/dataloaders/oneToOneDataLoader.js +40 -0
  42. package/build/src/dataloaders/oneToOneDataLoader.js.map +1 -0
  43. package/build/src/drivers/IdAssigner.d.ts +33 -0
  44. package/build/src/drivers/IdAssigner.js +106 -0
  45. package/build/src/drivers/IdAssigner.js.map +1 -0
  46. package/build/src/drivers/InMemoryDriver.d.ts +29 -0
  47. package/build/src/drivers/InMemoryDriver.js +306 -0
  48. package/build/src/drivers/InMemoryDriver.js.map +1 -0
  49. package/build/src/drivers/PostgresDriver.d.ts +40 -0
  50. package/build/src/drivers/PostgresDriver.js +376 -0
  51. package/build/src/drivers/PostgresDriver.js.map +1 -0
  52. package/build/src/drivers/driver.d.ts +23 -0
  53. package/build/src/drivers/driver.js +3 -0
  54. package/build/src/drivers/driver.js.map +1 -0
  55. package/build/src/drivers/index.d.ts +4 -0
  56. package/build/src/drivers/index.js +17 -0
  57. package/build/src/drivers/index.js.map +1 -0
  58. package/build/{getProperties.d.ts → src/getProperties.d.ts} +0 -0
  59. package/build/{getProperties.js → src/getProperties.js} +1 -1
  60. package/build/src/getProperties.js.map +1 -0
  61. package/build/src/index.d.ts +62 -0
  62. package/build/src/index.js +263 -0
  63. package/build/src/index.js.map +1 -0
  64. package/build/src/keys.d.ts +30 -0
  65. package/build/{keys.js → src/keys.js} +48 -16
  66. package/build/src/keys.js.map +1 -0
  67. package/build/{loadLens.d.ts → src/loadLens.d.ts} +2 -2
  68. package/build/{loadLens.js → src/loadLens.js} +1 -1
  69. package/build/src/loadLens.js.map +1 -0
  70. package/build/src/loaded.d.ts +49 -0
  71. package/build/src/loaded.js +9 -0
  72. package/build/src/loaded.js.map +1 -0
  73. package/build/{newTestInstance.d.ts → src/newTestInstance.d.ts} +37 -3
  74. package/build/src/newTestInstance.js +342 -0
  75. package/build/src/newTestInstance.js.map +1 -0
  76. package/build/{collections → src/relations}/AbstractRelationImpl.d.ts +6 -5
  77. package/build/{collections → src/relations}/AbstractRelationImpl.js +0 -0
  78. package/build/src/relations/AbstractRelationImpl.js.map +1 -0
  79. package/build/src/relations/Collection.d.ts +26 -0
  80. package/build/src/relations/Collection.js +19 -0
  81. package/build/src/relations/Collection.js.map +1 -0
  82. package/build/{collections → src/relations}/CustomCollection.d.ts +6 -2
  83. package/build/{collections → src/relations}/CustomCollection.js +17 -9
  84. package/build/src/relations/CustomCollection.js.map +1 -0
  85. package/build/{collections → src/relations}/CustomReference.d.ts +7 -2
  86. package/build/{collections → src/relations}/CustomReference.js +16 -9
  87. package/build/src/relations/CustomReference.js.map +1 -0
  88. package/build/src/relations/LargeCollection.d.ts +17 -0
  89. package/build/src/relations/LargeCollection.js +3 -0
  90. package/build/src/relations/LargeCollection.js.map +1 -0
  91. package/build/{collections → src/relations}/ManyToManyCollection.d.ts +9 -2
  92. package/build/src/relations/ManyToManyCollection.js +249 -0
  93. package/build/src/relations/ManyToManyCollection.js.map +1 -0
  94. package/build/src/relations/ManyToManyLargeCollection.d.ts +25 -0
  95. package/build/src/relations/ManyToManyLargeCollection.js +97 -0
  96. package/build/src/relations/ManyToManyLargeCollection.js.map +1 -0
  97. package/build/src/relations/ManyToOneReference.d.ts +77 -0
  98. package/build/{collections → src/relations}/ManyToOneReference.js +101 -48
  99. package/build/src/relations/ManyToOneReference.js.map +1 -0
  100. package/build/{collections → src/relations}/OneToManyCollection.d.ts +10 -2
  101. package/build/{collections → src/relations}/OneToManyCollection.js +54 -59
  102. package/build/src/relations/OneToManyCollection.js.map +1 -0
  103. package/build/src/relations/OneToManyLargeCollection.d.ts +25 -0
  104. package/build/src/relations/OneToManyLargeCollection.js +83 -0
  105. package/build/src/relations/OneToManyLargeCollection.js.map +1 -0
  106. package/build/src/relations/OneToOneReference.d.ts +82 -0
  107. package/build/src/relations/OneToOneReference.js +168 -0
  108. package/build/src/relations/OneToOneReference.js.map +1 -0
  109. package/build/src/relations/PolymorphicReference.d.ts +69 -0
  110. package/build/src/relations/PolymorphicReference.js +210 -0
  111. package/build/src/relations/PolymorphicReference.js.map +1 -0
  112. package/build/src/relations/Reference.d.ts +29 -0
  113. package/build/src/relations/Reference.js +23 -0
  114. package/build/src/relations/Reference.js.map +1 -0
  115. package/build/src/relations/Relation.d.ts +10 -0
  116. package/build/src/relations/Relation.js +13 -0
  117. package/build/src/relations/Relation.js.map +1 -0
  118. package/build/src/relations/hasAsyncProperty.d.ts +36 -0
  119. package/build/src/relations/hasAsyncProperty.js +55 -0
  120. package/build/src/relations/hasAsyncProperty.js.map +1 -0
  121. package/build/{collections → src/relations}/hasManyDerived.d.ts +2 -1
  122. package/build/{collections → src/relations}/hasManyDerived.js +1 -1
  123. package/build/src/relations/hasManyDerived.js.map +1 -0
  124. package/build/{collections → src/relations}/hasManyThrough.d.ts +0 -0
  125. package/build/{collections → src/relations}/hasManyThrough.js +2 -2
  126. package/build/src/relations/hasManyThrough.js.map +1 -0
  127. package/build/{collections → src/relations}/hasOneDerived.d.ts +3 -2
  128. package/build/{collections → src/relations}/hasOneDerived.js +1 -1
  129. package/build/src/relations/hasOneDerived.js.map +1 -0
  130. package/build/{collections → src/relations}/hasOneThrough.d.ts +0 -0
  131. package/build/{collections → src/relations}/hasOneThrough.js +2 -2
  132. package/build/src/relations/hasOneThrough.js.map +1 -0
  133. package/build/src/relations/index.d.ts +18 -0
  134. package/build/src/relations/index.js +53 -0
  135. package/build/src/relations/index.js.map +1 -0
  136. package/build/{reverseHint.d.ts → src/reverseHint.d.ts} +2 -1
  137. package/build/{reverseHint.js → src/reverseHint.js} +13 -9
  138. package/build/src/reverseHint.js.map +1 -0
  139. package/build/src/rules.d.ts +23 -0
  140. package/build/src/rules.js +23 -0
  141. package/build/src/rules.js.map +1 -0
  142. package/build/src/serde.d.ts +121 -0
  143. package/build/src/serde.js +190 -0
  144. package/build/src/serde.js.map +1 -0
  145. package/build/{utils.d.ts → src/utils.d.ts} +2 -0
  146. package/build/{utils.js → src/utils.js} +10 -1
  147. package/build/src/utils.js.map +1 -0
  148. package/build/tsconfig.tsbuildinfo +1 -0
  149. package/package.json +30 -15
  150. package/build/BaseEntity.js.map +0 -1
  151. package/build/EntityManager.js.map +0 -1
  152. package/build/EntityPersister.d.ts +0 -30
  153. package/build/EntityPersister.js +0 -197
  154. package/build/EntityPersister.js.map +0 -1
  155. package/build/QueryBuilder.js +0 -195
  156. package/build/QueryBuilder.js.map +0 -1
  157. package/build/changes.d.ts +0 -23
  158. package/build/changes.js +0 -14
  159. package/build/changes.js.map +0 -1
  160. package/build/collections/AbstractRelationImpl.js.map +0 -1
  161. package/build/collections/CustomCollection.js.map +0 -1
  162. package/build/collections/CustomReference.js.map +0 -1
  163. package/build/collections/ManyToManyCollection.js +0 -288
  164. package/build/collections/ManyToManyCollection.js.map +0 -1
  165. package/build/collections/ManyToOneReference.d.ts +0 -50
  166. package/build/collections/ManyToOneReference.js.map +0 -1
  167. package/build/collections/OneToManyCollection.js.map +0 -1
  168. package/build/collections/OneToOneReference.d.ts +0 -51
  169. package/build/collections/OneToOneReference.js +0 -132
  170. package/build/collections/OneToOneReference.js.map +0 -1
  171. package/build/collections/hasManyDerived.js.map +0 -1
  172. package/build/collections/hasManyThrough.js.map +0 -1
  173. package/build/collections/hasOneDerived.js.map +0 -1
  174. package/build/collections/hasOneThrough.js.map +0 -1
  175. package/build/collections/index.d.ts +0 -19
  176. package/build/collections/index.js +0 -49
  177. package/build/collections/index.js.map +0 -1
  178. package/build/createOrUpdatePartial.js.map +0 -1
  179. package/build/getProperties.js.map +0 -1
  180. package/build/index.d.ts +0 -140
  181. package/build/index.js +0 -278
  182. package/build/index.js.map +0 -1
  183. package/build/keys.d.ts +0 -21
  184. package/build/keys.js.map +0 -1
  185. package/build/loadLens.js.map +0 -1
  186. package/build/newTestInstance.js +0 -153
  187. package/build/newTestInstance.js.map +0 -1
  188. package/build/reverseHint.js.map +0 -1
  189. package/build/serde.d.ts +0 -47
  190. package/build/serde.js +0 -93
  191. package/build/serde.js.map +0 -1
  192. package/build/utils.js.map +0 -1
  193. package/package.json.bak +0 -27
  194. package/src/BaseEntity.ts +0 -104
  195. package/src/EntityManager.ts +0 -1263
  196. package/src/EntityPersister.ts +0 -240
  197. package/src/QueryBuilder.ts +0 -289
  198. package/src/changes.ts +0 -40
  199. package/src/collections/AbstractRelationImpl.ts +0 -28
  200. package/src/collections/CustomCollection.ts +0 -152
  201. package/src/collections/CustomReference.ts +0 -138
  202. package/src/collections/ManyToManyCollection.ts +0 -346
  203. package/src/collections/ManyToOneReference.ts +0 -215
  204. package/src/collections/OneToManyCollection.ts +0 -254
  205. package/src/collections/OneToOneReference.ts +0 -153
  206. package/src/collections/hasManyDerived.ts +0 -29
  207. package/src/collections/hasManyThrough.ts +0 -20
  208. package/src/collections/hasOneDerived.ts +0 -26
  209. package/src/collections/hasOneThrough.ts +0 -20
  210. package/src/collections/index.ts +0 -74
  211. package/src/createOrUpdatePartial.ts +0 -144
  212. package/src/getProperties.ts +0 -27
  213. package/src/index.ts +0 -400
  214. package/src/keys.ts +0 -75
  215. package/src/loadLens.ts +0 -126
  216. package/src/newTestInstance.ts +0 -205
  217. package/src/reverseHint.ts +0 -43
  218. package/src/serde.ts +0 -97
  219. package/src/utils.ts +0 -63
  220. package/tsconfig.json +0 -21
  221. package/tsconfig.tsbuildinfo +0 -2646
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.newChangesProxy = void 0;
4
+ const EntityManager_1 = require("./EntityManager");
5
+ function newChangesProxy(entity) {
6
+ return new Proxy(entity, {
7
+ get(target, p) {
8
+ if (p === "fields") {
9
+ return (entity.isNewEntity ? Object.keys(entity.__orm.data) : Object.keys(entity.__orm.originalData));
10
+ }
11
+ else if (typeof p === "symbol") {
12
+ throw new Error(`Unsupported call to ${String(p)}`);
13
+ }
14
+ const originalValue = entity.__orm.originalData[p];
15
+ const hasChanged = (entity.isNewEntity && p in entity.__orm.data) || p in entity.__orm.originalData;
16
+ const hasUpdated = !entity.isNewEntity && p in entity.__orm.originalData;
17
+ return {
18
+ hasChanged,
19
+ hasUpdated,
20
+ originalValue,
21
+ get originalEntity() {
22
+ if ((0, EntityManager_1.isEntity)(originalValue)) {
23
+ return Promise.resolve(originalValue);
24
+ }
25
+ else if ((0, EntityManager_1.isId)(originalValue)) {
26
+ return entity.em.load(entity[p].otherMeta.cstr, originalValue);
27
+ }
28
+ else {
29
+ return Promise.resolve();
30
+ }
31
+ },
32
+ };
33
+ },
34
+ });
35
+ }
36
+ exports.newChangesProxy = newChangesProxy;
37
+ //# sourceMappingURL=changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/changes.ts"],"names":[],"mappings":";;;AAAA,mDAAuE;AAyCvE,SAAgB,eAAe,CAAmB,MAAS;IACzD,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE;QACvB,GAAG,CAAC,MAAM,EAAE,CAAc;YACxB,IAAI,CAAC,KAAK,QAAQ,EAAE;gBAClB,OAAO,CACL,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CACtE,CAAC;aAC1B;iBAAM,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE;gBAChC,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;aACrD;YAED,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACnD,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC;YACpG,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC;YACzE,OAAO;gBACL,UAAU;gBACV,UAAU;gBACV,aAAa;gBACb,IAAI,cAAc;oBAChB,IAAI,IAAA,wBAAQ,EAAC,aAAa,CAAC,EAAE;wBAC3B,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;qBACvC;yBAAM,IAAI,IAAA,oBAAI,EAAC,aAAa,CAAC,EAAE;wBAC9B,OAAO,MAAM,CAAC,EAAE,CAAC,IAAI,CAAE,MAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;qBACzE;yBAAM;wBACL,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;qBAC1B;gBACH,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAQ,CAAC;AACZ,CAAC;AA9BD,0CA8BC"}
@@ -0,0 +1,43 @@
1
+ import { Entity } from "./EntityManager";
2
+ import { Loaded, LoadHint, RelationsIn } from "./index";
3
+ import { MaybePromise, ValidationRule } from "./rules";
4
+ export declare type EntityHook = "beforeFlush" | "beforeCreate" | "beforeUpdate" | "beforeDelete" | "afterValidation" | "afterCommit";
5
+ declare type HookFn<T extends Entity, C> = (entity: T, ctx: C) => MaybePromise<void>;
6
+ /** The public API to configure an Entity's hooks & validation rules. */
7
+ export declare class ConfigApi<T extends Entity, C> {
8
+ __data: ConfigData<T, C>;
9
+ addRule<H extends LoadHint<T>>(populate: H, rule: ValidationRule<Loaded<T, H>>): void;
10
+ addRule(rule: ValidationRule<T>): void;
11
+ cascadeDelete(relationship: keyof RelationsIn<T> & LoadHint<T>): void;
12
+ /** Registers `fn` as the lambda to provide the async value for `key`. */
13
+ setAsyncDerivedField<P extends keyof T, H extends LoadHint<T>>(key: P, populate: H, fn: (entity: Loaded<T, H>) => T[P]): void;
14
+ private addHook;
15
+ beforeDelete<H extends LoadHint<T>>(populate: H, fn: HookFn<Loaded<T, H>, C>): void;
16
+ beforeDelete(fn: HookFn<T, C>): void;
17
+ beforeFlush<H extends LoadHint<T>>(populate: H, fn: HookFn<Loaded<T, H>, C>): void;
18
+ beforeFlush(fn: HookFn<T, C>): void;
19
+ beforeCreate<H extends LoadHint<T>>(populate: H, fn: HookFn<Loaded<T, H>, C>): void;
20
+ beforeCreate(fn: HookFn<T, C>): void;
21
+ beforeUpdate<H extends LoadHint<T>>(populate: H, fn: HookFn<Loaded<T, H>, C>): void;
22
+ beforeUpdate(fn: HookFn<T, C>): void;
23
+ afterValidation<H extends LoadHint<T>>(populate: H, fn: HookFn<Loaded<T, H>, C>): void;
24
+ afterValidation(fn: HookFn<T, C>): void;
25
+ afterCommit(fn: HookFn<T, C>): void;
26
+ /**
27
+ * A noop method that exists solely to keep the `config.placeholder()` line in the initial entity file,
28
+ * until the user is ready to use it. */
29
+ placeholder(): void;
30
+ }
31
+ /** The internal state of an entity's configuration data, i.e. validation rules/hooks. */
32
+ export declare class ConfigData<T extends Entity, C> {
33
+ /** The validation rules for this entity type. */
34
+ rules: ValidationRule<T>[];
35
+ /** The async derived fields for this entity type. */
36
+ asyncDerivedFields: Partial<Record<keyof T, [LoadHint<T>, (entity: T) => any]>>;
37
+ /** The hooks for this instance. */
38
+ hooks: Record<EntityHook, HookFn<T, C>[]>;
39
+ reactiveRules: string[][];
40
+ reactiveDerivedValues: string[][];
41
+ cascadeDeleteFields: Array<keyof RelationsIn<T>>;
42
+ }
43
+ export {};
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfigData = exports.ConfigApi = void 0;
4
+ /** The public API to configure an Entity's hooks & validation rules. */
5
+ class ConfigApi {
6
+ constructor() {
7
+ this.__data = new ConfigData();
8
+ }
9
+ addRule(ruleOrHint, maybeRule) {
10
+ if (typeof ruleOrHint === "function") {
11
+ this.__data.rules.push(ruleOrHint);
12
+ }
13
+ else {
14
+ const fn = async (entity) => {
15
+ const loaded = await entity.em.populate(entity, ruleOrHint);
16
+ return maybeRule(loaded);
17
+ };
18
+ // Squirrel our hint away where configureMetadata can find it
19
+ fn.hint = ruleOrHint;
20
+ // Keep the name for easy debugging/tracing later
21
+ fn.ruleName = getCallerName();
22
+ this.__data.rules.push(fn);
23
+ }
24
+ }
25
+ cascadeDelete(relationship) {
26
+ this.__data.cascadeDeleteFields.push(relationship);
27
+ this.beforeDelete(relationship, (entity) => {
28
+ const relation = entity[relationship];
29
+ relation.maybeCascadeDelete();
30
+ });
31
+ }
32
+ /** Registers `fn` as the lambda to provide the async value for `key`. */
33
+ setAsyncDerivedField(key, populate, fn) {
34
+ this.__data.asyncDerivedFields[key] = [populate, fn];
35
+ }
36
+ addHook(hook, ruleOrHint, maybeFn) {
37
+ if (typeof ruleOrHint === "function") {
38
+ this.__data.hooks[hook].push(ruleOrHint);
39
+ }
40
+ else {
41
+ const fn = async (entity, ctx) => {
42
+ // TODO Use this for reactive beforeFlush
43
+ const loaded = await entity.em.populate(entity, ruleOrHint);
44
+ return maybeFn(loaded, ctx);
45
+ };
46
+ // Squirrel our hint away where configureMetadata can find it
47
+ fn.hint = ruleOrHint;
48
+ this.__data.hooks[hook].push(fn);
49
+ }
50
+ }
51
+ beforeDelete(ruleOrHint, maybeFn) {
52
+ this.addHook("beforeDelete", ruleOrHint, maybeFn);
53
+ }
54
+ beforeFlush(ruleOrHint, maybeFn) {
55
+ this.addHook("beforeFlush", ruleOrHint, maybeFn);
56
+ }
57
+ beforeCreate(ruleOrHint, maybeFn) {
58
+ this.addHook("beforeCreate", ruleOrHint, maybeFn);
59
+ }
60
+ beforeUpdate(ruleOrHint, maybeFn) {
61
+ this.addHook("beforeUpdate", ruleOrHint, maybeFn);
62
+ }
63
+ afterValidation(ruleOrHint, maybeFn) {
64
+ this.addHook("afterValidation", ruleOrHint, maybeFn);
65
+ }
66
+ afterCommit(fn) {
67
+ this.addHook("afterCommit", fn);
68
+ }
69
+ /**
70
+ * A noop method that exists solely to keep the `config.placeholder()` line in the initial entity file,
71
+ * until the user is ready to use it. */
72
+ placeholder() { }
73
+ }
74
+ exports.ConfigApi = ConfigApi;
75
+ /** The internal state of an entity's configuration data, i.e. validation rules/hooks. */
76
+ class ConfigData {
77
+ constructor() {
78
+ /** The validation rules for this entity type. */
79
+ this.rules = [];
80
+ /** The async derived fields for this entity type. */
81
+ this.asyncDerivedFields = {};
82
+ /** The hooks for this instance. */
83
+ this.hooks = {
84
+ beforeDelete: [],
85
+ beforeFlush: [],
86
+ beforeCreate: [],
87
+ beforeUpdate: [],
88
+ afterCommit: [],
89
+ afterValidation: [],
90
+ };
91
+ // Load-hint-ish structures that point back to instances that depend on us for validation rules.
92
+ this.reactiveRules = [];
93
+ // Load-hint-ish structures that point back to instances that depend on us for derived values.
94
+ this.reactiveDerivedValues = [];
95
+ this.cascadeDeleteFields = [];
96
+ }
97
+ }
98
+ exports.ConfigData = ConfigData;
99
+ function getCallerName() {
100
+ const err = getErrorObject();
101
+ // E.g. at Object.<anonymous> (/home/stephen/homebound/graphql-service/src/entities/Activity.ts:86:8)
102
+ const line = err.stack.split("\n")[4];
103
+ const parts = line.split("/");
104
+ return parts[parts.length - 1].replace(")", "");
105
+ }
106
+ function getErrorObject() {
107
+ try {
108
+ throw Error("");
109
+ }
110
+ catch (err) {
111
+ return err;
112
+ }
113
+ }
114
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { NullOrDefinedOr } from "./utils";
2
1
  import { Entity, EntityConstructor, EntityManager, IdOf, OptIdsOf, OptsOf } from "./EntityManager";
3
2
  import { PartialOrNull } from "./index";
3
+ import { NullOrDefinedOr } from "./utils";
4
4
  /**
5
5
  * The type for `EntityManager.createOrUpdateUnsafe` that allows "upsert"-ish behavior.
6
6
  *
@@ -16,6 +16,7 @@ declare type AllowRelationsToBeIdsOrEntitiesOrPartials<T> = {
16
16
  [P in keyof T]: T[P] extends NullOrDefinedOr<infer U> ? U extends Array<infer V> ? V extends Entity ? Array<V | (DeepPartialOrNull<V> & {
17
17
  delete?: boolean | null;
18
18
  remove?: boolean | null;
19
+ op?: "remove" | "delete" | "include" | "incremental";
19
20
  }) | IdOf<V>> | null : T[P] : U extends Entity ? U | DeepPartialOrNull<U> | IdOf<U> | null : T[P] : T[P];
20
21
  };
21
22
  /**
@@ -2,21 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createOrUpdatePartial = void 0;
4
4
  const EntityManager_1 = require("./EntityManager");
5
+ const index_1 = require("./index");
5
6
  /**
6
7
  * A utility function to create-or-update entities coming from a partial-update style API.
7
8
  */
8
9
  async function createOrUpdatePartial(em, constructor, opts) {
9
10
  const { id, ...others } = opts;
10
- const meta = EntityManager_1.getMetadata(constructor);
11
+ const meta = (0, EntityManager_1.getMetadata)(constructor);
11
12
  const isNew = id === null || id === undefined;
13
+ const collectionsToLoad = [];
12
14
  // The values in others might be themselves partials, so walk through and resolve them to entities.
13
15
  const p = Object.entries(others).map(async ([key, value]) => {
14
16
  // Watch for the `bookId` / `bookIds` aliases
15
- const field = meta.fields.find((f) => f.fieldName === key) || meta.fields.find((f) => f.fieldIdName === key);
17
+ const field = meta.fields[key] || Object.values(meta.fields).find((f) => f.fieldIdName === key);
16
18
  if (!field) {
17
19
  // Allow delete/remove flags that we assume the API layer (i.e. GraphQL) will have specifically
18
20
  // allowed, i.e. this isn't the Rails form bug where users can POST in any random field they want.
19
- const flagField = key === "delete" || key === "remove";
21
+ const flagField = key === "delete" || key === "remove" || key === "op";
20
22
  if (flagField) {
21
23
  // Pass these along for setOpts to look for
22
24
  return [key, value];
@@ -25,11 +27,24 @@ async function createOrUpdatePartial(em, constructor, opts) {
25
27
  }
26
28
  // Don't use key b/c it might be the bookId alias
27
29
  const name = field.fieldName;
28
- if (field.kind === "m2o" && !EntityManager_1.isEntity(value)) {
29
- if (!value || EntityManager_1.isEntity(value)) {
30
+ if (field.kind === "poly" && !(0, EntityManager_1.isEntity)(value)) {
31
+ if (!value) {
30
32
  return [name, value];
31
33
  }
32
- else if (EntityManager_1.isKey(value)) {
34
+ else if ((0, EntityManager_1.isKey)(value)) {
35
+ // This is a polymorphic reference
36
+ const entity = await em.load((0, index_1.getConstructorFromTaggedId)(value), value);
37
+ return [name, entity];
38
+ }
39
+ else {
40
+ throw new Error(`Cannot use partial value for polymorphic field `);
41
+ }
42
+ }
43
+ else if (field.kind === "m2o" && !(0, EntityManager_1.isEntity)(value)) {
44
+ if (!value || (0, EntityManager_1.isEntity)(value)) {
45
+ return [name, value];
46
+ }
47
+ else if ((0, EntityManager_1.isKey)(value)) {
33
48
  // This is a many-to-one reference
34
49
  const entity = await em.load(field.otherMetadata().cstr, value);
35
50
  return [name, entity];
@@ -65,32 +80,43 @@ async function createOrUpdatePartial(em, constructor, opts) {
65
80
  // Look for one-to-many/many-to-many partials
66
81
  // We allow `delete` and `remove` commands but only if they don't collide with existing fields
67
82
  // Also we trust the API layer, i.e. GraphQL, to not let these fields leak unless explicitly allowed.
68
- const allowDelete = !field.otherMetadata().fields.some((f) => f.fieldName === "delete");
69
- const allowRemove = !field.otherMetadata().fields.some((f) => f.fieldName === "remove");
83
+ const allowDelete = !field.otherMetadata().fields["delete"];
84
+ const allowRemove = !field.otherMetadata().fields["remove"];
85
+ const allowOp = !field.otherMetadata().fields["op"];
86
+ collectionsToLoad.push(field.fieldName);
70
87
  const entities = !value
71
88
  ? []
72
89
  : value.map(async (value) => {
73
- if (!value || EntityManager_1.isEntity(value)) {
90
+ if (!value || (0, EntityManager_1.isEntity)(value)) {
74
91
  return value;
75
92
  }
76
- else if (EntityManager_1.isKey(value)) {
93
+ else if ((0, EntityManager_1.isKey)(value)) {
77
94
  return await em.load(field.otherMetadata().cstr, value);
78
95
  }
79
96
  else {
80
97
  // Look for `delete: true/false` and `remove: true/false` markers
81
98
  const deleteMarker = allowDelete && value["delete"];
82
99
  const removeMarker = allowRemove && value["remove"];
100
+ const opMarker = allowOp && value["op"];
101
+ // If this is the incremental marker, just leave it in as-is so that setOpts can see it
102
+ if (opMarker === "incremental") {
103
+ return value;
104
+ }
83
105
  // Remove the markers, regardless of true/false, before recursing into createOrUpdatePartial to avoid unknown fields
84
106
  if (deleteMarker !== undefined)
85
107
  delete value.delete;
86
108
  if (removeMarker !== undefined)
87
109
  delete value.remove;
110
+ if (opMarker !== undefined)
111
+ delete value.op;
88
112
  const entity = await createOrUpdatePartial(em, field.otherMetadata().cstr, value);
89
113
  // Put the markers back for setOpts to find
90
114
  if (deleteMarker === true)
91
115
  entity.delete = true;
92
116
  if (removeMarker === true)
93
117
  entity.remove = true;
118
+ if (opMarker)
119
+ entity.op = opMarker;
94
120
  return entity;
95
121
  }
96
122
  });
@@ -106,6 +132,12 @@ async function createOrUpdatePartial(em, constructor, opts) {
106
132
  }
107
133
  else {
108
134
  const entity = await em.load(constructor, id);
135
+ // For o2m and m2m .set to work, they need to be loaded so that they know what to remove.
136
+ // Note that we also have the `delete: true` pattern for flagging not only "remove" but "delete",
137
+ // for a parent's mutation to control the lifecycle of a child entity (i.e. line items).
138
+ // Musing: Maybe this should happen implicitly, like if a LineItem.parent is set to null, that
139
+ // LineItem knows to just `em.delete` itself? Instead of relying on hints from GraphQL mutations.
140
+ await Promise.all(collectionsToLoad.map((fieldName) => entity[fieldName].load()));
109
141
  entity.setPartial(_opts);
110
142
  return entity;
111
143
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createOrUpdatePartial.js","sourceRoot":"","sources":["../../src/createOrUpdatePartial.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import DataLoader from "dataloader";
2
+ import { Entity, EntityConstructor, EntityManager } from "../EntityManager";
3
+ import { FilterAndSettings } from "../QueryBuilder";
4
+ export declare function findDataLoader<T extends Entity>(em: EntityManager, type: EntityConstructor<T>): DataLoader<FilterAndSettings<T>, unknown[]>;
5
+ export declare function whereFilterHash(where: FilterAndSettings<any>): string;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.whereFilterHash = exports.findDataLoader = void 0;
7
+ const dataloader_1 = __importDefault(require("dataloader"));
8
+ const object_hash_1 = __importDefault(require("object-hash"));
9
+ const EntityManager_1 = require("../EntityManager");
10
+ const utils_1 = require("../utils");
11
+ function findDataLoader(em, type) {
12
+ return (0, utils_1.getOrSet)(em.findLoaders, type.name, () => {
13
+ return new dataloader_1.default((queries) => {
14
+ return em.driver.find(em, type, queries);
15
+ }, {
16
+ // Our filter/order tuple is a complex object, so object-hash it to ensure caching works
17
+ cacheKeyFn: whereFilterHash,
18
+ });
19
+ });
20
+ }
21
+ exports.findDataLoader = findDataLoader;
22
+ // If a where clause includes an entity, object-hash cannot hash it, so just use the id.
23
+ const replacer = (v) => ((0, EntityManager_1.isEntity)(v) ? v.id : v);
24
+ function whereFilterHash(where) {
25
+ return (0, object_hash_1.default)(where, { replacer });
26
+ }
27
+ exports.whereFilterHash = whereFilterHash;
28
+ //# sourceMappingURL=findDataLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findDataLoader.js","sourceRoot":"","sources":["../../../src/dataloaders/findDataLoader.ts"],"names":[],"mappings":";;;;;;AAAA,4DAAoC;AACpC,8DAA+B;AAC/B,oDAAsF;AAEtF,oCAAoC;AAEpC,SAAgB,cAAc,CAC5B,EAAiB,EACjB,IAA0B;IAE1B,OAAO,IAAA,gBAAQ,EAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE;QAC9C,OAAO,IAAI,oBAAU,CACnB,CAAC,OAAO,EAAE,EAAE;YACV,OAAO,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC,EACD;YACE,wFAAwF;YACxF,UAAU,EAAE,eAAe;SAC5B,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAfD,wCAeC;AAED,wFAAwF;AACxF,MAAM,QAAQ,GAAG,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAA,wBAAQ,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtD,SAAgB,eAAe,CAAC,KAA6B;IAC3D,OAAO,IAAA,qBAAI,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;AACnC,CAAC;AAFD,0CAEC"}
@@ -0,0 +1,3 @@
1
+ import DataLoader from "dataloader";
2
+ import { Entity, EntityManager, EntityMetadata } from "../EntityManager";
3
+ export declare function loadDataLoader<T extends Entity>(em: EntityManager, meta: EntityMetadata<T>): DataLoader<string, T | undefined>;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadDataLoader = void 0;
7
+ const dataloader_1 = __importDefault(require("dataloader"));
8
+ const keys_1 = require("../keys");
9
+ const utils_1 = require("../utils");
10
+ function loadDataLoader(em, meta) {
11
+ return (0, utils_1.getOrSet)(em.loadLoaders, meta.type, () => {
12
+ return new dataloader_1.default(async (_keys) => {
13
+ (0, keys_1.assertIdsAreTagged)(_keys);
14
+ const keys = (0, keys_1.deTagIds)(meta, _keys);
15
+ const rows = await em.driver.load(em, meta, keys);
16
+ // Pass overwriteExisting (which is the default anyway) because it might be EntityManager.refresh calling us.
17
+ const entities = rows.map((row) => em.hydrate(meta.cstr, row, { overwriteExisting: true }));
18
+ const entitiesById = (0, utils_1.indexBy)(entities, (e) => e.id);
19
+ // Return the results back in the same order as the keys
20
+ return _keys.map((k) => {
21
+ const entity = entitiesById.get(k);
22
+ // We generally expect all of our entities to be found, but they may not for API calls like
23
+ // `findOneOrFail` or for `EntityManager.refresh` when the entity has been deleted out from
24
+ // under us.
25
+ if (entity === undefined) {
26
+ const existingEntity = em.findExistingInstance(k);
27
+ if (existingEntity) {
28
+ existingEntity.__orm.deleted = "deleted";
29
+ }
30
+ }
31
+ return entity;
32
+ });
33
+ });
34
+ });
35
+ }
36
+ exports.loadDataLoader = loadDataLoader;
37
+ //# sourceMappingURL=loadDataLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadDataLoader.js","sourceRoot":"","sources":["../../../src/dataloaders/loadDataLoader.ts"],"names":[],"mappings":";;;;;;AAAA,4DAAoC;AAEpC,kCAAuD;AACvD,oCAA6C;AAE7C,SAAgB,cAAc,CAC5B,EAAiB,EACjB,IAAuB;IAEvB,OAAO,IAAA,gBAAQ,EAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE;QAC9C,OAAO,IAAI,oBAAU,CAAwB,KAAK,EAAE,KAAK,EAAE,EAAE;YAC3D,IAAA,yBAAkB,EAAC,KAAK,CAAC,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAA,eAAQ,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAEnC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAElD,6GAA6G;YAC7G,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5F,MAAM,YAAY,GAAG,IAAA,eAAO,EAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAG,CAAC,CAAC;YAErD,wDAAwD;YACxD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACrB,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACnC,2FAA2F;gBAC3F,2FAA2F;gBAC3F,YAAY;gBACZ,IAAI,MAAM,KAAK,SAAS,EAAE;oBACxB,MAAM,cAAc,GAAG,EAAE,CAAC,oBAAoB,CAAI,CAAC,CAAC,CAAC;oBACrD,IAAI,cAAc,EAAE;wBAClB,cAAc,CAAC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;qBAC1C;iBACF;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AA/BD,wCA+BC"}
@@ -0,0 +1,5 @@
1
+ import DataLoader from "dataloader";
2
+ import { Entity, EntityManager } from "../EntityManager";
3
+ import { ManyToManyCollection } from "../index";
4
+ /** Batches m2m.load calls. */
5
+ export declare function manyToManyDataLoader<T extends Entity, U extends Entity>(em: EntityManager, collection: ManyToManyCollection<T, U>): DataLoader<any, any, any>;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.manyToManyDataLoader = void 0;
7
+ const dataloader_1 = __importDefault(require("dataloader"));
8
+ const index_1 = require("../index");
9
+ const utils_1 = require("../utils");
10
+ /** Batches m2m.load calls. */
11
+ function manyToManyDataLoader(em, collection) {
12
+ // Note that we cache the dataloader on the joinTableName, and not
13
+ // which side of the relation the `collection` is coming from, so
14
+ // the `load` impl will have to handle keys that come from either
15
+ // side of the relation.
16
+ return (0, utils_1.getOrSet)(em.loadLoaders, collection.joinTableName, () => new dataloader_1.default((keys) => load(collection, keys)));
17
+ }
18
+ exports.manyToManyDataLoader = manyToManyDataLoader;
19
+ /**
20
+ * Loads join rows (batched).
21
+ *
22
+ * I.e. we can load the `books_to_tags` join rows for multiple `Book`s at a time, or even
23
+ * load `books_to_tags` for several `Book`s and several `Tag`s in a single SQL query.
24
+ */
25
+ async function load(collection, keys) {
26
+ const { joinTableName } = collection;
27
+ const { em } = collection.entity;
28
+ // Make a map that will be both `tag_id=t:2 -> [...]` and `book_id=b:3 -> [...]`
29
+ const rowsByKey = {};
30
+ // Keep a reference to our row to track updates/deletes
31
+ const emJoinRows = (0, utils_1.getOrSet)(em.__data.joinRows, joinTableName, []);
32
+ const rows = await em.driver.loadManyToMany(em, collection, keys);
33
+ // The order of column1/column2 doesn't really matter, i.e. if the opposite-side collection is later used
34
+ const column1 = collection.columnName;
35
+ const meta1 = collection.entity.__orm.metadata;
36
+ const column2 = collection.otherColumnName;
37
+ const meta2 = collection.otherMeta;
38
+ // For each join table row, we use `EntityManager.load` to get both entities loaded.
39
+ // This will be another 1 or 2 queries (depending on whether we're loading just
40
+ // `book.getTags` (1 query to load new tags) or both `book.getTags` and `tag.getBooks
41
+ // (1 query to load the new tags and 1 query to look the new books)).
42
+ //
43
+ // Eventually we could have this query join into the entity tables themselves, i.e.
44
+ // `books` and `tags`, and use those results to hydrate the newly-found entities.
45
+ await Promise.all(rows.map(async (dbRow) => {
46
+ // We may have already loaded this join row in a prior load of the opposite side of this m2m.
47
+ let emRow = emJoinRows.find((jr) => {
48
+ return (jr[column1].id === (0, index_1.keyToString)(meta1, dbRow[column1]) &&
49
+ jr[column2].id === (0, index_1.keyToString)(meta2, dbRow[column2]));
50
+ });
51
+ if (!emRow) {
52
+ // For this join table row, load the entities of both foreign keys. Because we are `EntityManager.load`,
53
+ // this is N+1 safe (and will check the Unit of Work for already-loaded entities), but per ^ comment
54
+ // we chould pull these from the row itself if we did a fancier join.
55
+ const p1 = em.load(meta1.cstr, (0, index_1.keyToString)(meta1, dbRow[column1]));
56
+ const p2 = em.load(meta2.cstr, (0, index_1.keyToString)(meta2, dbRow[column2]));
57
+ const [e1, e2] = await Promise.all([p1, p2]);
58
+ emRow = { id: dbRow.id, m2m: collection, [column1]: e1, [column2]: e2, created_at: dbRow.created_at };
59
+ emJoinRows.push(emRow);
60
+ }
61
+ else {
62
+ // If a placeholder row was created while a ManyToManyCollection was unloaded, and we find it during
63
+ // a subsequent load/query, update its id to be what is in the database.
64
+ emRow.id = dbRow.id;
65
+ }
66
+ // Put this row into the map for both join table columns, i.e. `book_id=2` and `tag_id=3`
67
+ (0, utils_1.getOrSet)(rowsByKey, `${column1}=${emRow[column1].id}`, []).push(emRow);
68
+ (0, utils_1.getOrSet)(rowsByKey, `${column2}=${emRow[column2].id}`, []).push(emRow);
69
+ }));
70
+ // Map the requested keys, i.e. book_id=2 back to "the tags for book 2".
71
+ return keys.map((key) => {
72
+ const [column] = key.split("=");
73
+ const joinRows = rowsByKey[key] || [];
74
+ const otherColumn = column === collection.columnName ? collection.otherColumnName : collection.columnName;
75
+ return joinRows.map((joinRow) => joinRow[otherColumn]);
76
+ });
77
+ }
78
+ //# sourceMappingURL=manyToManyDataLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manyToManyDataLoader.js","sourceRoot":"","sources":["../../../src/dataloaders/manyToManyDataLoader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import DataLoader from "dataloader";
2
+ import { Entity, EntityManager } from "../EntityManager";
3
+ import { ManyToManyCollection, ManyToManyLargeCollection } from "../index";
4
+ /** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */
5
+ export declare function manyToManyFindDataLoader<T extends Entity, U extends Entity>(em: EntityManager, collection: ManyToManyCollection<T, U> | ManyToManyLargeCollection<T, U>): DataLoader<string, boolean>;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.manyToManyFindDataLoader = void 0;
7
+ const dataloader_1 = __importDefault(require("dataloader"));
8
+ const index_1 = require("../index");
9
+ const utils_1 = require("../utils");
10
+ /** Batches m2m.find/include calls (i.e. that don't fully load the m2m relation). */
11
+ function manyToManyFindDataLoader(em, collection) {
12
+ return (0, utils_1.getOrSet)(em.loadLoaders, `find-${collection.joinTableName}`, () => new dataloader_1.default((keys) => load(collection, keys)));
13
+ }
14
+ exports.manyToManyFindDataLoader = manyToManyFindDataLoader;
15
+ async function load(collection, keys) {
16
+ const { joinTableName } = collection;
17
+ const { em } = collection.entity;
18
+ const rows = await em.driver.findManyToMany(em, collection, keys);
19
+ const column1 = collection.columnName;
20
+ const column2 = collection.otherColumnName;
21
+ const meta1 = collection.meta;
22
+ const meta2 = collection.otherMeta;
23
+ // Because keys might come from either side of the m2m relationship, build
24
+ // a list of both `foo_id=2,bar_id=3` and `bar_id=3,foo_id=2` to make the
25
+ // final return value just a map of `Set.has`.
26
+ const found = new Set(rows.flatMap((dbRow) => {
27
+ const a = `${column1}=${(0, index_1.tagId)(meta1, dbRow[column1])}`;
28
+ const b = `${column2}=${(0, index_1.tagId)(meta2, dbRow[column2])}`;
29
+ return [`${a},${b}`, `${b},${a}`];
30
+ }));
31
+ return keys.map((key) => found.has(key));
32
+ }
33
+ //# sourceMappingURL=manyToManyFindDataLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manyToManyFindDataLoader.js","sourceRoot":"","sources":["../../../src/dataloaders/manyToManyFindDataLoader.ts"],"names":[],"mappings":";;;;;;AAAA,4DAAoC;AAEpC,oCAAkF;AAClF,oCAAoC;AAEpC,oFAAoF;AACpF,SAAgB,wBAAwB,CACtC,EAAiB,EACjB,UAAwE;IAExE,OAAO,IAAA,gBAAQ,EACb,EAAE,CAAC,WAAW,EACd,QAAQ,UAAU,CAAC,aAAa,EAAE,EAClC,GAAG,EAAE,CAAC,IAAI,oBAAU,CAAkB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CACxE,CAAC;AACJ,CAAC;AATD,4DASC;AAED,KAAK,UAAU,IAAI,CACjB,UAAwE,EACxE,IAA2B;IAE3B,MAAM,EAAE,aAAa,EAAE,GAAG,UAAU,CAAC;IACrC,MAAM,EAAE,EAAE,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC;IAEjC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IAElE,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC;IACtC,MAAM,OAAO,GAAG,UAAU,CAAC,eAAe,CAAC;IAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC;IAC9B,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC;IAEnC,0EAA0E;IAC1E,yEAAyE;IACzE,8CAA8C;IAC9C,MAAM,KAAK,GAAG,IAAI,GAAG,CACnB,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACrB,MAAM,CAAC,GAAG,GAAG,OAAO,IAAI,IAAA,aAAK,EAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAW,CAAC,EAAE,CAAC;QACjE,MAAM,CAAC,GAAG,GAAG,OAAO,IAAI,IAAA,aAAK,EAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAW,CAAC,EAAE,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import DataLoader from "dataloader";
2
+ import { Entity, EntityManager } from "../EntityManager";
3
+ import { OneToManyCollection } from "../index";
4
+ export declare function oneToManyDataLoader<T extends Entity, U extends Entity>(em: EntityManager, collection: OneToManyCollection<T, U>): DataLoader<string, U[]>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.oneToManyDataLoader = void 0;
7
+ const dataloader_1 = __importDefault(require("dataloader"));
8
+ const index_1 = require("../index");
9
+ const utils_1 = require("../utils");
10
+ function oneToManyDataLoader(em, collection) {
11
+ // The metadata for the entity that contains the collection
12
+ const { meta, fieldName } = collection;
13
+ const loaderName = `${meta.tableName}.${fieldName}`;
14
+ return (0, utils_1.getOrSet)(em.loadLoaders, loaderName, () => {
15
+ return new dataloader_1.default(async (_keys) => {
16
+ const { otherMeta } = collection;
17
+ (0, index_1.assertIdsAreTagged)(_keys);
18
+ const keys = (0, index_1.deTagIds)(meta, _keys);
19
+ const { em } = collection.entity;
20
+ const rows = await em.driver.loadOneToMany(em, collection, keys);
21
+ const entities = rows.map((row) => em.hydrate(otherMeta.cstr, row, { overwriteExisting: false }));
22
+ // .filter((e) => !e.isDeletedEntity);
23
+ const rowsById = (0, utils_1.groupBy)(entities, (entity) => {
24
+ // TODO If this came from the UoW, it may not be an id? I.e. pre-insert.
25
+ const ownerId = (0, index_1.maybeResolveReferenceToId)(entity.__orm.data[collection.otherFieldName]);
26
+ // We almost always expect ownerId to be found, b/c normally we just hydrated this entity
27
+ // directly from a SQL row with owner_id=X, however we might be loading this collection
28
+ // (i.e. find all children where owner_id=X) when the SQL thinks a child is still pointing
29
+ // at the parent (i.e. owner_id=X in the db), but our already-loaded child has had its
30
+ // `child.owner` field either changed to some other owner, or set to undefined. In either,
31
+ // that child should no longer be parent of this owner's collection, so just return a
32
+ // dummy value.
33
+ return ownerId ?? "dummyNoLongerOwned";
34
+ });
35
+ return _keys.map((k) => rowsById.get(k) || []);
36
+ });
37
+ });
38
+ }
39
+ exports.oneToManyDataLoader = oneToManyDataLoader;
40
+ //# sourceMappingURL=oneToManyDataLoader.js.map