@vendure/core 3.7.1-master-202607110305 → 3.7.1-master-202607140305
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.
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ID } from '@vendure/common/lib/shared-types';
|
|
2
|
+
import { RequestContextCacheService } from '../../cache/request-context-cache.service';
|
|
2
3
|
import { RelationCustomFieldConfig } from '../../config/custom-field/custom-field-types';
|
|
3
4
|
import { TransactionalConnection } from '../../connection/transactional-connection';
|
|
4
5
|
import { VendureEntity } from '../../entity/base/base.entity';
|
|
@@ -13,16 +14,35 @@ export interface ResolveRelationConfig {
|
|
|
13
14
|
}
|
|
14
15
|
export declare class CustomFieldRelationResolverService {
|
|
15
16
|
private connection;
|
|
17
|
+
private requestCache;
|
|
16
18
|
private productPriceApplicator;
|
|
17
19
|
private translator;
|
|
18
|
-
constructor(connection: TransactionalConnection, productPriceApplicator: ProductPriceApplicator, translator: TranslatorService);
|
|
20
|
+
constructor(connection: TransactionalConnection, requestCache: RequestContextCacheService, productPriceApplicator: ProductPriceApplicator, translator: TranslatorService);
|
|
19
21
|
/**
|
|
20
22
|
* @description
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
23
|
+
* Resolves a relation-type custom field. Lookups for the same entity/field combination
|
|
24
|
+
* within a single request are batched via a DataLoader into one query for the mapping
|
|
25
|
+
* and one for the related entities, eliminating the N+1 pattern that otherwise occurs
|
|
26
|
+
* when resolving list queries.
|
|
24
27
|
*/
|
|
25
|
-
resolveRelation(config: ResolveRelationConfig): Promise<VendureEntity | VendureEntity[]>;
|
|
28
|
+
resolveRelation(config: ResolveRelationConfig): Promise<VendureEntity | VendureEntity[] | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Returns the DataLoader for a given entity/field combination, creating it if needed.
|
|
31
|
+
*
|
|
32
|
+
* The loader is cached via RequestContextCacheService, which keys on the RequestContext
|
|
33
|
+
* instance itself (a WeakMap), so:
|
|
34
|
+
* - loaders never leak beyond the request they were created for and are garbage-collected
|
|
35
|
+
* once the request completes;
|
|
36
|
+
* - a transactional RequestContext (a distinct instance from its parent) gets its own,
|
|
37
|
+
* unbatched loader, so writes made earlier in the same transaction are never masked by a
|
|
38
|
+
* stale batched read.
|
|
39
|
+
*
|
|
40
|
+
* The loader also memoizes per id for the lifetime of `ctx`. This is safe here because
|
|
41
|
+
* relation custom fields are only ever read via this path within a request, so there is no
|
|
42
|
+
* same-request write that could go stale.
|
|
43
|
+
*/
|
|
44
|
+
private getLoader;
|
|
45
|
+
private batchLoad;
|
|
26
46
|
translateEntity(ctx: RequestContext, result: VendureEntity | VendureEntity[] | null, fieldDef: RelationCustomFieldConfig): Promise<any>;
|
|
27
47
|
private isTranslatable;
|
|
28
48
|
private applyVariantPrices;
|
|
@@ -8,43 +8,112 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.CustomFieldRelationResolverService = void 0;
|
|
13
16
|
const common_1 = require("@nestjs/common");
|
|
17
|
+
const dataloader_1 = __importDefault(require("dataloader"));
|
|
14
18
|
const FindOptionsUtils_1 = require("typeorm/find-options/FindOptionsUtils");
|
|
19
|
+
const request_context_cache_service_1 = require("../../cache/request-context-cache.service");
|
|
15
20
|
const transactional_connection_1 = require("../../connection/transactional-connection");
|
|
16
21
|
const product_variant_entity_1 = require("../../entity/product-variant/product-variant.entity");
|
|
17
22
|
const product_price_applicator_1 = require("../../service/helpers/product-price-applicator/product-price-applicator");
|
|
18
23
|
const translator_service_1 = require("../../service/helpers/translator/translator.service");
|
|
19
24
|
let CustomFieldRelationResolverService = class CustomFieldRelationResolverService {
|
|
20
|
-
constructor(connection, productPriceApplicator, translator) {
|
|
25
|
+
constructor(connection, requestCache, productPriceApplicator, translator) {
|
|
21
26
|
this.connection = connection;
|
|
27
|
+
this.requestCache = requestCache;
|
|
22
28
|
this.productPriceApplicator = productPriceApplicator;
|
|
23
29
|
this.translator = translator;
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
26
32
|
* @description
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
33
|
+
* Resolves a relation-type custom field. Lookups for the same entity/field combination
|
|
34
|
+
* within a single request are batched via a DataLoader into one query for the mapping
|
|
35
|
+
* and one for the related entities, eliminating the N+1 pattern that otherwise occurs
|
|
36
|
+
* when resolving list queries.
|
|
30
37
|
*/
|
|
31
38
|
async resolveRelation(config) {
|
|
39
|
+
var _a;
|
|
32
40
|
const { ctx, entityId, entityName, fieldDef } = config;
|
|
33
|
-
const
|
|
41
|
+
const loader = this.getLoader(ctx, entityName, fieldDef);
|
|
42
|
+
const batchResult = await loader.load(entityId);
|
|
43
|
+
const finalResult = fieldDef.list ? batchResult : ((_a = batchResult[0]) !== null && _a !== void 0 ? _a : null);
|
|
44
|
+
return this.translateEntity(ctx, finalResult, fieldDef);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Returns the DataLoader for a given entity/field combination, creating it if needed.
|
|
48
|
+
*
|
|
49
|
+
* The loader is cached via RequestContextCacheService, which keys on the RequestContext
|
|
50
|
+
* instance itself (a WeakMap), so:
|
|
51
|
+
* - loaders never leak beyond the request they were created for and are garbage-collected
|
|
52
|
+
* once the request completes;
|
|
53
|
+
* - a transactional RequestContext (a distinct instance from its parent) gets its own,
|
|
54
|
+
* unbatched loader, so writes made earlier in the same transaction are never masked by a
|
|
55
|
+
* stale batched read.
|
|
56
|
+
*
|
|
57
|
+
* The loader also memoizes per id for the lifetime of `ctx`. This is safe here because
|
|
58
|
+
* relation custom fields are only ever read via this path within a request, so there is no
|
|
59
|
+
* same-request write that could go stale.
|
|
60
|
+
*/
|
|
61
|
+
getLoader(ctx, entityName, fieldDef) {
|
|
62
|
+
const cacheKey = `CustomFieldRelationLoader:${entityName}:${fieldDef.name}`;
|
|
63
|
+
return this.requestCache.get(ctx, cacheKey, () => new dataloader_1.default(ids => this.batchLoad(ctx, entityName, fieldDef, ids)));
|
|
64
|
+
}
|
|
65
|
+
async batchLoad(ctx, entityName, fieldDef, ids) {
|
|
66
|
+
// Fetch the parent -> relation id mapping for all batched parent ids in a single query
|
|
67
|
+
const mappingQb = this.connection
|
|
34
68
|
.getRepository(ctx, entityName)
|
|
35
69
|
.createQueryBuilder('entity')
|
|
36
70
|
.leftJoin(`entity.customFields.${fieldDef.name}`, 'relationEntity')
|
|
37
|
-
.select('
|
|
38
|
-
.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
71
|
+
.select('entity.id', 'entity_id')
|
|
72
|
+
.addSelect('relationEntity.id', 'relation_id')
|
|
73
|
+
.where('entity.id IN (:...ids)', { ids });
|
|
74
|
+
const rawMappings = await mappingQb.getRawMany();
|
|
75
|
+
// Normalize ids to strings before using them as Map keys. getRawMany() returns
|
|
76
|
+
// driver-native raw values (which may be numbers, e.g. on postgres integer PKs),
|
|
77
|
+
// while `ids` (from DataLoader) and hydrated entity `.id` values are not guaranteed
|
|
78
|
+
// to be of the same type. Without normalizing, lookups below can silently miss.
|
|
79
|
+
const mappingMap = new Map();
|
|
80
|
+
for (const row of rawMappings) {
|
|
81
|
+
const relationId = row.relation_id;
|
|
82
|
+
if (relationId == null) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const parentKey = String(row.entity_id);
|
|
86
|
+
const existing = mappingMap.get(parentKey);
|
|
87
|
+
if (existing) {
|
|
88
|
+
existing.push(relationId);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
mappingMap.set(parentKey, [relationId]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const allRelationIds = Array.from(new Set(rawMappings.map(row => row.relation_id).filter((id) => id != null)));
|
|
95
|
+
let relations = [];
|
|
96
|
+
if (allRelationIds.length > 0) {
|
|
97
|
+
const relationQb = this.connection
|
|
98
|
+
.getRepository(ctx, fieldDef.entity)
|
|
99
|
+
.createQueryBuilder('relation')
|
|
100
|
+
.where('relation.id IN (:...allRelationIds)', { allRelationIds });
|
|
101
|
+
FindOptionsUtils_1.FindOptionsUtils.joinEagerRelations(relationQb, relationQb.alias, relationQb.expressionMap.mainAlias.metadata);
|
|
102
|
+
relations = await relationQb.getMany();
|
|
103
|
+
}
|
|
104
|
+
const relationMap = new Map();
|
|
105
|
+
for (const rel of relations) {
|
|
106
|
+
relationMap.set(String(rel.id), rel);
|
|
107
|
+
}
|
|
108
|
+
// Map grouped relation ids back to each original id, in the same order DataLoader
|
|
109
|
+
// requested them, so results line up with their corresponding parent entity.
|
|
110
|
+
return ids.map(id => {
|
|
111
|
+
var _a;
|
|
112
|
+
const targetIds = (_a = mappingMap.get(String(id))) !== null && _a !== void 0 ? _a : [];
|
|
113
|
+
return targetIds
|
|
114
|
+
.map(targetId => relationMap.get(String(targetId)))
|
|
115
|
+
.filter((r) => r != null);
|
|
116
|
+
});
|
|
48
117
|
}
|
|
49
118
|
async translateEntity(ctx, result, fieldDef) {
|
|
50
119
|
if (result == null)
|
|
@@ -82,6 +151,7 @@ exports.CustomFieldRelationResolverService = CustomFieldRelationResolverService;
|
|
|
82
151
|
exports.CustomFieldRelationResolverService = CustomFieldRelationResolverService = __decorate([
|
|
83
152
|
(0, common_1.Injectable)(),
|
|
84
153
|
__metadata("design:paramtypes", [transactional_connection_1.TransactionalConnection,
|
|
154
|
+
request_context_cache_service_1.RequestContextCacheService,
|
|
85
155
|
product_price_applicator_1.ProductPriceApplicator,
|
|
86
156
|
translator_service_1.TranslatorService])
|
|
87
157
|
], CustomFieldRelationResolverService);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-field-relation-resolver.service.js","sourceRoot":"","sources":["../../../src/api/common/custom-field-relation-resolver.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"custom-field-relation-resolver.service.js","sourceRoot":"","sources":["../../../src/api/common/custom-field-relation-resolver.service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vendure/core",
|
|
3
|
-
"version": "3.7.1-master-
|
|
3
|
+
"version": "3.7.1-master-202607140305",
|
|
4
4
|
"description": "A modern, headless ecommerce framework",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -49,13 +49,14 @@
|
|
|
49
49
|
"@nestjs/platform-express": "^11.0.12",
|
|
50
50
|
"@nestjs/typeorm": "^11.0.0",
|
|
51
51
|
"@types/express": "^5.0.1",
|
|
52
|
-
"@vendure/common": "^3.7.1-master-
|
|
52
|
+
"@vendure/common": "^3.7.1-master-202607140305",
|
|
53
53
|
"bcrypt": "^6.0.0",
|
|
54
54
|
"cookie-session": "^2.1.0",
|
|
55
55
|
"cron-time-generator": "^2.0.3",
|
|
56
56
|
"croner": "^10.0.1",
|
|
57
57
|
"cronstrue": "^3.14.0",
|
|
58
58
|
"csv-parse": "^6.2.1",
|
|
59
|
+
"dataloader": "^2.2.3",
|
|
59
60
|
"express": "^5.1.0",
|
|
60
61
|
"file-type": "^19.0.0",
|
|
61
62
|
"fs-extra": "^11.2.0",
|