UNPKG

3.49 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.ModuleTokenFactory = void 0;
4const common_1 = require("@nestjs/common");
5const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
6const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
7const crypto_1 = require("crypto");
8const fast_safe_stringify_1 = require("fast-safe-stringify");
9const perf_hooks_1 = require("perf_hooks");
10const CLASS_STR = 'class ';
11const CLASS_STR_LEN = CLASS_STR.length;
12class ModuleTokenFactory {
13 constructor() {
14 this.moduleTokenCache = new Map();
15 this.moduleIdsCache = new WeakMap();
16 this.logger = new common_1.Logger(ModuleTokenFactory.name, {
17 timestamp: true,
18 });
19 }
20 create(metatype, dynamicModuleMetadata) {
21 const moduleId = this.getModuleId(metatype);
22 if (!dynamicModuleMetadata) {
23 return this.getStaticModuleToken(moduleId, this.getModuleName(metatype));
24 }
25 const opaqueToken = {
26 id: moduleId,
27 module: this.getModuleName(metatype),
28 dynamic: dynamicModuleMetadata,
29 };
30 const start = perf_hooks_1.performance.now();
31 const opaqueTokenString = this.getStringifiedOpaqueToken(opaqueToken);
32 const timeSpentInMs = perf_hooks_1.performance.now() - start;
33 if (timeSpentInMs > 10) {
34 const formattedTimeSpent = timeSpentInMs.toFixed(2);
35 this.logger.warn(`The module "${opaqueToken.module}" is taking ${formattedTimeSpent}ms to serialize, this may be caused by larger objects statically assigned to the module. More details: https://github.com/nestjs/nest/issues/12738`);
36 }
37 return this.hashString(opaqueTokenString);
38 }
39 getStaticModuleToken(moduleId, moduleName) {
40 const key = `${moduleId}_${moduleName}`;
41 if (this.moduleTokenCache.has(key)) {
42 return this.moduleTokenCache.get(key);
43 }
44 const hash = this.hashString(key);
45 this.moduleTokenCache.set(key, hash);
46 return hash;
47 }
48 getStringifiedOpaqueToken(opaqueToken) {
49 // Uses safeStringify instead of JSON.stringify to support circular dynamic modules
50 // The replacer function is also required in order to obtain real class names
51 // instead of the unified "Function" key
52 return opaqueToken ? (0, fast_safe_stringify_1.default)(opaqueToken, this.replacer) : '';
53 }
54 getModuleId(metatype) {
55 let moduleId = this.moduleIdsCache.get(metatype);
56 if (moduleId) {
57 return moduleId;
58 }
59 moduleId = (0, random_string_generator_util_1.randomStringGenerator)();
60 this.moduleIdsCache.set(metatype, moduleId);
61 return moduleId;
62 }
63 getModuleName(metatype) {
64 return metatype.name;
65 }
66 hashString(value) {
67 return (0, crypto_1.createHash)('sha256').update(value).digest('hex');
68 }
69 replacer(key, value) {
70 if ((0, shared_utils_1.isFunction)(value)) {
71 const funcAsString = value.toString();
72 const isClass = funcAsString.slice(0, CLASS_STR_LEN) === CLASS_STR;
73 if (isClass) {
74 return value.name;
75 }
76 return funcAsString;
77 }
78 if ((0, shared_utils_1.isSymbol)(value)) {
79 return value.toString();
80 }
81 return value;
82 }
83}
84exports.ModuleTokenFactory = ModuleTokenFactory;