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.
- package/build/{BaseEntity.d.ts → src/BaseEntity.d.ts} +2 -1
- package/build/{BaseEntity.js → src/BaseEntity.js} +13 -9
- package/build/src/BaseEntity.js.map +1 -0
- package/build/{EntityManager.d.ts → src/EntityManager.d.ts} +139 -110
- package/build/{EntityManager.js → src/EntityManager.js} +281 -262
- package/build/src/EntityManager.js.map +1 -0
- package/build/{QueryBuilder.d.ts → src/QueryBuilder.d.ts} +53 -3
- package/build/src/QueryBuilder.js +341 -0
- package/build/src/QueryBuilder.js.map +1 -0
- package/build/src/Todo.d.ts +25 -0
- package/build/src/Todo.js +52 -0
- package/build/src/Todo.js.map +1 -0
- package/build/src/changes.d.ts +34 -0
- package/build/src/changes.js +37 -0
- package/build/src/changes.js.map +1 -0
- package/build/src/config.d.ts +43 -0
- package/build/src/config.js +114 -0
- package/build/src/config.js.map +1 -0
- package/build/{createOrUpdatePartial.d.ts → src/createOrUpdatePartial.d.ts} +2 -1
- package/build/{createOrUpdatePartial.js → src/createOrUpdatePartial.js} +42 -10
- package/build/src/createOrUpdatePartial.js.map +1 -0
- package/build/src/dataloaders/findDataLoader.d.ts +5 -0
- package/build/src/dataloaders/findDataLoader.js +28 -0
- package/build/src/dataloaders/findDataLoader.js.map +1 -0
- package/build/src/dataloaders/loadDataLoader.d.ts +3 -0
- package/build/src/dataloaders/loadDataLoader.js +37 -0
- package/build/src/dataloaders/loadDataLoader.js.map +1 -0
- package/build/src/dataloaders/manyToManyDataLoader.d.ts +5 -0
- package/build/src/dataloaders/manyToManyDataLoader.js +78 -0
- package/build/src/dataloaders/manyToManyDataLoader.js.map +1 -0
- package/build/src/dataloaders/manyToManyFindDataLoader.d.ts +5 -0
- package/build/src/dataloaders/manyToManyFindDataLoader.js +33 -0
- package/build/src/dataloaders/manyToManyFindDataLoader.js.map +1 -0
- package/build/src/dataloaders/oneToManyDataLoader.d.ts +4 -0
- package/build/src/dataloaders/oneToManyDataLoader.js +40 -0
- package/build/src/dataloaders/oneToManyDataLoader.js.map +1 -0
- package/build/src/dataloaders/oneToManyFindDataLoader.d.ts +5 -0
- package/build/src/dataloaders/oneToManyFindDataLoader.js +32 -0
- package/build/src/dataloaders/oneToManyFindDataLoader.js.map +1 -0
- package/build/src/dataloaders/oneToOneDataLoader.d.ts +4 -0
- package/build/src/dataloaders/oneToOneDataLoader.js +40 -0
- package/build/src/dataloaders/oneToOneDataLoader.js.map +1 -0
- package/build/src/drivers/IdAssigner.d.ts +33 -0
- package/build/src/drivers/IdAssigner.js +106 -0
- package/build/src/drivers/IdAssigner.js.map +1 -0
- package/build/src/drivers/InMemoryDriver.d.ts +29 -0
- package/build/src/drivers/InMemoryDriver.js +306 -0
- package/build/src/drivers/InMemoryDriver.js.map +1 -0
- package/build/src/drivers/PostgresDriver.d.ts +40 -0
- package/build/src/drivers/PostgresDriver.js +376 -0
- package/build/src/drivers/PostgresDriver.js.map +1 -0
- package/build/src/drivers/driver.d.ts +23 -0
- package/build/src/drivers/driver.js +3 -0
- package/build/src/drivers/driver.js.map +1 -0
- package/build/src/drivers/index.d.ts +4 -0
- package/build/src/drivers/index.js +17 -0
- package/build/src/drivers/index.js.map +1 -0
- package/build/{getProperties.d.ts → src/getProperties.d.ts} +0 -0
- package/build/{getProperties.js → src/getProperties.js} +1 -1
- package/build/src/getProperties.js.map +1 -0
- package/build/src/index.d.ts +62 -0
- package/build/src/index.js +263 -0
- package/build/src/index.js.map +1 -0
- package/build/src/keys.d.ts +30 -0
- package/build/{keys.js → src/keys.js} +48 -16
- package/build/src/keys.js.map +1 -0
- package/build/{loadLens.d.ts → src/loadLens.d.ts} +2 -2
- package/build/{loadLens.js → src/loadLens.js} +1 -1
- package/build/src/loadLens.js.map +1 -0
- package/build/src/loaded.d.ts +49 -0
- package/build/src/loaded.js +9 -0
- package/build/src/loaded.js.map +1 -0
- package/build/{newTestInstance.d.ts → src/newTestInstance.d.ts} +37 -3
- package/build/src/newTestInstance.js +342 -0
- package/build/src/newTestInstance.js.map +1 -0
- package/build/{collections → src/relations}/AbstractRelationImpl.d.ts +6 -5
- package/build/{collections → src/relations}/AbstractRelationImpl.js +0 -0
- package/build/src/relations/AbstractRelationImpl.js.map +1 -0
- package/build/src/relations/Collection.d.ts +26 -0
- package/build/src/relations/Collection.js +19 -0
- package/build/src/relations/Collection.js.map +1 -0
- package/build/{collections → src/relations}/CustomCollection.d.ts +6 -2
- package/build/{collections → src/relations}/CustomCollection.js +17 -9
- package/build/src/relations/CustomCollection.js.map +1 -0
- package/build/{collections → src/relations}/CustomReference.d.ts +7 -2
- package/build/{collections → src/relations}/CustomReference.js +16 -9
- package/build/src/relations/CustomReference.js.map +1 -0
- package/build/src/relations/LargeCollection.d.ts +17 -0
- package/build/src/relations/LargeCollection.js +3 -0
- package/build/src/relations/LargeCollection.js.map +1 -0
- package/build/{collections → src/relations}/ManyToManyCollection.d.ts +9 -2
- package/build/src/relations/ManyToManyCollection.js +249 -0
- package/build/src/relations/ManyToManyCollection.js.map +1 -0
- package/build/src/relations/ManyToManyLargeCollection.d.ts +25 -0
- package/build/src/relations/ManyToManyLargeCollection.js +97 -0
- package/build/src/relations/ManyToManyLargeCollection.js.map +1 -0
- package/build/src/relations/ManyToOneReference.d.ts +77 -0
- package/build/{collections → src/relations}/ManyToOneReference.js +101 -48
- package/build/src/relations/ManyToOneReference.js.map +1 -0
- package/build/{collections → src/relations}/OneToManyCollection.d.ts +10 -2
- package/build/{collections → src/relations}/OneToManyCollection.js +54 -59
- package/build/src/relations/OneToManyCollection.js.map +1 -0
- package/build/src/relations/OneToManyLargeCollection.d.ts +25 -0
- package/build/src/relations/OneToManyLargeCollection.js +83 -0
- package/build/src/relations/OneToManyLargeCollection.js.map +1 -0
- package/build/src/relations/OneToOneReference.d.ts +82 -0
- package/build/src/relations/OneToOneReference.js +168 -0
- package/build/src/relations/OneToOneReference.js.map +1 -0
- package/build/src/relations/PolymorphicReference.d.ts +69 -0
- package/build/src/relations/PolymorphicReference.js +210 -0
- package/build/src/relations/PolymorphicReference.js.map +1 -0
- package/build/src/relations/Reference.d.ts +29 -0
- package/build/src/relations/Reference.js +23 -0
- package/build/src/relations/Reference.js.map +1 -0
- package/build/src/relations/Relation.d.ts +10 -0
- package/build/src/relations/Relation.js +13 -0
- package/build/src/relations/Relation.js.map +1 -0
- package/build/src/relations/hasAsyncProperty.d.ts +36 -0
- package/build/src/relations/hasAsyncProperty.js +55 -0
- package/build/src/relations/hasAsyncProperty.js.map +1 -0
- package/build/{collections → src/relations}/hasManyDerived.d.ts +2 -1
- package/build/{collections → src/relations}/hasManyDerived.js +1 -1
- package/build/src/relations/hasManyDerived.js.map +1 -0
- package/build/{collections → src/relations}/hasManyThrough.d.ts +0 -0
- package/build/{collections → src/relations}/hasManyThrough.js +2 -2
- package/build/src/relations/hasManyThrough.js.map +1 -0
- package/build/{collections → src/relations}/hasOneDerived.d.ts +3 -2
- package/build/{collections → src/relations}/hasOneDerived.js +1 -1
- package/build/src/relations/hasOneDerived.js.map +1 -0
- package/build/{collections → src/relations}/hasOneThrough.d.ts +0 -0
- package/build/{collections → src/relations}/hasOneThrough.js +2 -2
- package/build/src/relations/hasOneThrough.js.map +1 -0
- package/build/src/relations/index.d.ts +18 -0
- package/build/src/relations/index.js +53 -0
- package/build/src/relations/index.js.map +1 -0
- package/build/{reverseHint.d.ts → src/reverseHint.d.ts} +2 -1
- package/build/{reverseHint.js → src/reverseHint.js} +13 -9
- package/build/src/reverseHint.js.map +1 -0
- package/build/src/rules.d.ts +23 -0
- package/build/src/rules.js +23 -0
- package/build/src/rules.js.map +1 -0
- package/build/src/serde.d.ts +121 -0
- package/build/src/serde.js +190 -0
- package/build/src/serde.js.map +1 -0
- package/build/{utils.d.ts → src/utils.d.ts} +2 -0
- package/build/{utils.js → src/utils.js} +10 -1
- package/build/src/utils.js.map +1 -0
- package/build/tsconfig.tsbuildinfo +1 -0
- package/package.json +30 -15
- package/build/BaseEntity.js.map +0 -1
- package/build/EntityManager.js.map +0 -1
- package/build/EntityPersister.d.ts +0 -30
- package/build/EntityPersister.js +0 -197
- package/build/EntityPersister.js.map +0 -1
- package/build/QueryBuilder.js +0 -195
- package/build/QueryBuilder.js.map +0 -1
- package/build/changes.d.ts +0 -23
- package/build/changes.js +0 -14
- package/build/changes.js.map +0 -1
- package/build/collections/AbstractRelationImpl.js.map +0 -1
- package/build/collections/CustomCollection.js.map +0 -1
- package/build/collections/CustomReference.js.map +0 -1
- package/build/collections/ManyToManyCollection.js +0 -288
- package/build/collections/ManyToManyCollection.js.map +0 -1
- package/build/collections/ManyToOneReference.d.ts +0 -50
- package/build/collections/ManyToOneReference.js.map +0 -1
- package/build/collections/OneToManyCollection.js.map +0 -1
- package/build/collections/OneToOneReference.d.ts +0 -51
- package/build/collections/OneToOneReference.js +0 -132
- package/build/collections/OneToOneReference.js.map +0 -1
- package/build/collections/hasManyDerived.js.map +0 -1
- package/build/collections/hasManyThrough.js.map +0 -1
- package/build/collections/hasOneDerived.js.map +0 -1
- package/build/collections/hasOneThrough.js.map +0 -1
- package/build/collections/index.d.ts +0 -19
- package/build/collections/index.js +0 -49
- package/build/collections/index.js.map +0 -1
- package/build/createOrUpdatePartial.js.map +0 -1
- package/build/getProperties.js.map +0 -1
- package/build/index.d.ts +0 -140
- package/build/index.js +0 -278
- package/build/index.js.map +0 -1
- package/build/keys.d.ts +0 -21
- package/build/keys.js.map +0 -1
- package/build/loadLens.js.map +0 -1
- package/build/newTestInstance.js +0 -153
- package/build/newTestInstance.js.map +0 -1
- package/build/reverseHint.js.map +0 -1
- package/build/serde.d.ts +0 -47
- package/build/serde.js +0 -93
- package/build/serde.js.map +0 -1
- package/build/utils.js.map +0 -1
- package/package.json.bak +0 -27
- package/src/BaseEntity.ts +0 -104
- package/src/EntityManager.ts +0 -1263
- package/src/EntityPersister.ts +0 -240
- package/src/QueryBuilder.ts +0 -289
- package/src/changes.ts +0 -40
- package/src/collections/AbstractRelationImpl.ts +0 -28
- package/src/collections/CustomCollection.ts +0 -152
- package/src/collections/CustomReference.ts +0 -138
- package/src/collections/ManyToManyCollection.ts +0 -346
- package/src/collections/ManyToOneReference.ts +0 -215
- package/src/collections/OneToManyCollection.ts +0 -254
- package/src/collections/OneToOneReference.ts +0 -153
- package/src/collections/hasManyDerived.ts +0 -29
- package/src/collections/hasManyThrough.ts +0 -20
- package/src/collections/hasOneDerived.ts +0 -26
- package/src/collections/hasOneThrough.ts +0 -20
- package/src/collections/index.ts +0 -74
- package/src/createOrUpdatePartial.ts +0 -144
- package/src/getProperties.ts +0 -27
- package/src/index.ts +0 -400
- package/src/keys.ts +0 -75
- package/src/loadLens.ts +0 -126
- package/src/newTestInstance.ts +0 -205
- package/src/reverseHint.ts +0 -43
- package/src/serde.ts +0 -97
- package/src/utils.ts +0 -63
- package/tsconfig.json +0 -21
- 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
|
|
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 === "
|
|
29
|
-
if (!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
|
|
69
|
-
const allowRemove = !field.otherMetadata().fields
|
|
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,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
|