typemold 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 (39) hide show
  1. package/LICENSE +43 -0
  2. package/README.md +235 -0
  3. package/dist/cjs/decorators.js +284 -0
  4. package/dist/cjs/index.js +74 -0
  5. package/dist/cjs/mapper.js +153 -0
  6. package/dist/cjs/nestjs/index.js +12 -0
  7. package/dist/cjs/nestjs/mapper.module.js +103 -0
  8. package/dist/cjs/nestjs/mapper.service.js +161 -0
  9. package/dist/cjs/registry.js +179 -0
  10. package/dist/cjs/types.js +17 -0
  11. package/dist/cjs/utils.js +136 -0
  12. package/dist/esm/decorators.js +274 -0
  13. package/dist/esm/index.js +51 -0
  14. package/dist/esm/mapper.js +149 -0
  15. package/dist/esm/nestjs/index.js +6 -0
  16. package/dist/esm/nestjs/mapper.module.js +100 -0
  17. package/dist/esm/nestjs/mapper.service.js +125 -0
  18. package/dist/esm/registry.js +175 -0
  19. package/dist/esm/types.js +14 -0
  20. package/dist/esm/utils.js +127 -0
  21. package/dist/types/decorators.d.ts +206 -0
  22. package/dist/types/decorators.d.ts.map +1 -0
  23. package/dist/types/index.d.ts +46 -0
  24. package/dist/types/index.d.ts.map +1 -0
  25. package/dist/types/mapper.d.ts +93 -0
  26. package/dist/types/mapper.d.ts.map +1 -0
  27. package/dist/types/nestjs/index.d.ts +7 -0
  28. package/dist/types/nestjs/index.d.ts.map +1 -0
  29. package/dist/types/nestjs/mapper.module.d.ts +89 -0
  30. package/dist/types/nestjs/mapper.module.d.ts.map +1 -0
  31. package/dist/types/nestjs/mapper.service.d.ts +80 -0
  32. package/dist/types/nestjs/mapper.service.d.ts.map +1 -0
  33. package/dist/types/registry.d.ts +60 -0
  34. package/dist/types/registry.d.ts.map +1 -0
  35. package/dist/types/types.d.ts +120 -0
  36. package/dist/types/types.d.ts.map +1 -0
  37. package/dist/types/utils.d.ts +30 -0
  38. package/dist/types/utils.d.ts.map +1 -0
  39. package/package.json +92 -0
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /**
3
+ * @sevirial/nest-mapper - Utility Functions
4
+ * Helper functions for the mapping engine
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.getNestedValue = getNestedValue;
8
+ exports.isPlainObject = isPlainObject;
9
+ exports.isClassInstance = isClassInstance;
10
+ exports.pickKeys = pickKeys;
11
+ exports.omitKeys = omitKeys;
12
+ exports.getAllPropertyKeys = getAllPropertyKeys;
13
+ exports.deepClone = deepClone;
14
+ /**
15
+ * Gets a nested value from an object using dot notation path.
16
+ * Optimized for performance with caching of path segments.
17
+ *
18
+ * @example
19
+ * getNestedValue({ profile: { avatar: 'url' } }, 'profile.avatar')
20
+ * // Returns: 'url'
21
+ */
22
+ const pathCache = new Map();
23
+ // Dangerous property names for prototype pollution
24
+ const BLOCKED_KEYS = new Set(["__proto__", "constructor", "prototype"]);
25
+ function getNestedValue(obj, path) {
26
+ if (obj == null)
27
+ return undefined;
28
+ // Simple path - check for prototype pollution
29
+ if (!path.includes(".")) {
30
+ if (BLOCKED_KEYS.has(path))
31
+ return undefined;
32
+ return obj[path];
33
+ }
34
+ let segments = pathCache.get(path);
35
+ if (!segments) {
36
+ segments = path.split(".");
37
+ pathCache.set(path, segments);
38
+ }
39
+ let current = obj;
40
+ for (let i = 0; i < segments.length; i++) {
41
+ // Block prototype pollution attempts
42
+ if (BLOCKED_KEYS.has(segments[i]))
43
+ return undefined;
44
+ if (current == null || typeof current !== "object")
45
+ return undefined;
46
+ current = current[segments[i]];
47
+ }
48
+ return current;
49
+ }
50
+ /**
51
+ * Checks if a value is a plain object (not an array, Date, etc.)
52
+ */
53
+ function isPlainObject(value) {
54
+ if (value === null || typeof value !== "object")
55
+ return false;
56
+ const proto = Object.getPrototypeOf(value);
57
+ return proto === Object.prototype || proto === null;
58
+ }
59
+ /**
60
+ * Checks if a value is a class instance (not a plain object)
61
+ */
62
+ function isClassInstance(value) {
63
+ if (value === null || typeof value !== "object")
64
+ return false;
65
+ const proto = Object.getPrototypeOf(value);
66
+ return proto !== Object.prototype && proto !== null;
67
+ }
68
+ /**
69
+ * Creates a shallow clone of an object with only specified keys
70
+ */
71
+ function pickKeys(obj, keys) {
72
+ const result = {};
73
+ for (const key of keys) {
74
+ if (key in obj) {
75
+ result[key] = obj[key];
76
+ }
77
+ }
78
+ return result;
79
+ }
80
+ /**
81
+ * Creates a shallow clone of an object without specified keys
82
+ */
83
+ function omitKeys(obj, keys) {
84
+ const keySet = new Set(keys);
85
+ const result = {};
86
+ for (const key in obj) {
87
+ if (Object.prototype.hasOwnProperty.call(obj, key) && !keySet.has(key)) {
88
+ result[key] = obj[key];
89
+ }
90
+ }
91
+ return result;
92
+ }
93
+ /**
94
+ * Gets all property keys including inherited ones
95
+ */
96
+ function getAllPropertyKeys(target) {
97
+ const keys = new Set();
98
+ let current = target;
99
+ while (current && current !== Object.prototype) {
100
+ for (const key of Object.getOwnPropertyNames(current)) {
101
+ if (key !== "constructor") {
102
+ keys.add(key);
103
+ }
104
+ }
105
+ current = Object.getPrototypeOf(current);
106
+ }
107
+ return Array.from(keys);
108
+ }
109
+ /**
110
+ * Deep clones an object (for handling circular references)
111
+ */
112
+ function deepClone(obj, visited = new WeakMap()) {
113
+ if (obj === null || typeof obj !== "object")
114
+ return obj;
115
+ const objAsObject = obj;
116
+ if (visited.has(objAsObject))
117
+ return visited.get(objAsObject);
118
+ if (Array.isArray(obj)) {
119
+ const arrClone = [];
120
+ visited.set(objAsObject, arrClone);
121
+ for (let i = 0; i < obj.length; i++) {
122
+ arrClone[i] = deepClone(obj[i], visited);
123
+ }
124
+ return arrClone;
125
+ }
126
+ if (obj instanceof Date)
127
+ return new Date(obj.getTime());
128
+ if (obj instanceof RegExp)
129
+ return new RegExp(obj.source, obj.flags);
130
+ const clone = Object.create(Object.getPrototypeOf(obj));
131
+ visited.set(objAsObject, clone);
132
+ for (const key of Object.keys(obj)) {
133
+ clone[key] = deepClone(obj[key], visited);
134
+ }
135
+ return clone;
136
+ }
@@ -0,0 +1,274 @@
1
+ /**
2
+ * @sevirial/nest-mapper - Decorators
3
+ * Property decorators for defining mapping configurations
4
+ */
5
+ import "reflect-metadata";
6
+ import { METADATA_KEYS, } from "./types";
7
+ /**
8
+ * Maps a property from a source path or using a transform function.
9
+ *
10
+ * @example
11
+ * // Direct property mapping
12
+ * class UserDto {
13
+ * @MapFrom('firstName')
14
+ * name: string;
15
+ * }
16
+ *
17
+ * @example
18
+ * // Nested path mapping
19
+ * class UserDto {
20
+ * @MapFrom('profile.avatar')
21
+ * avatarUrl: string;
22
+ * }
23
+ *
24
+ * @example
25
+ * // Transform function with typed source
26
+ * class UserDto {
27
+ * @MapFrom<User>((src) => src.age >= 18) // ← IntelliSense for src!
28
+ * isAdult: boolean;
29
+ * }
30
+ */
31
+ export function MapFrom(sourcePathOrTransform) {
32
+ return (target, propertyKey) => {
33
+ const key = String(propertyKey);
34
+ const existingMappings = Reflect.getMetadata(METADATA_KEYS.PROPERTY_MAPPINGS, target.constructor) || new Map();
35
+ const existingConfig = existingMappings.get(key) || createDefaultConfig(key);
36
+ if (typeof sourcePathOrTransform === "function") {
37
+ existingConfig.source = sourcePathOrTransform;
38
+ existingConfig.isTransform = true;
39
+ }
40
+ else {
41
+ existingConfig.source = sourcePathOrTransform;
42
+ existingConfig.isTransform = false;
43
+ }
44
+ existingMappings.set(key, existingConfig);
45
+ Reflect.defineMetadata(METADATA_KEYS.PROPERTY_MAPPINGS, existingMappings, target.constructor);
46
+ };
47
+ }
48
+ /**
49
+ * Creates a type-safe mapping configuration with full IntelliSense support.
50
+ * Use this builder pattern when you need autocomplete for source paths.
51
+ *
52
+ * @example
53
+ * interface User {
54
+ * username: string;
55
+ * profile: { avatar: string; bio: string };
56
+ * }
57
+ *
58
+ * // Option 1: Define mappings with full autocomplete
59
+ * const toUserDto = createMapping<User, UserDto>({
60
+ * avatar: 'profile.avatar', // ✨ Autocomplete for paths!
61
+ * bio: src => src.profile.bio, // ✨ Autocomplete for transforms!
62
+ * });
63
+ *
64
+ * // Usage
65
+ * const dto = toUserDto(userEntity);
66
+ *
67
+ * @example
68
+ * // Option 2: Use with Mapper
69
+ * const dto = Mapper.mapWith(user, toUserDto);
70
+ */
71
+ export function createMapping(mappings) {
72
+ return (source) => {
73
+ const result = {};
74
+ for (const [targetKey, sourcePathOrFn] of Object.entries(mappings)) {
75
+ if (typeof sourcePathOrFn === "function") {
76
+ result[targetKey] = sourcePathOrFn(source);
77
+ }
78
+ else {
79
+ result[targetKey] = getNestedValueTyped(source, sourcePathOrFn);
80
+ }
81
+ }
82
+ return result;
83
+ };
84
+ }
85
+ /**
86
+ * Helper to get nested value with type safety
87
+ */
88
+ function getNestedValueTyped(obj, path) {
89
+ if (obj == null)
90
+ return undefined;
91
+ const segments = path.split(".");
92
+ let current = obj;
93
+ for (const segment of segments) {
94
+ if (current == null || typeof current !== "object")
95
+ return undefined;
96
+ current = current[segment];
97
+ }
98
+ return current;
99
+ }
100
+ /**
101
+ * Automatically maps a property with the same name from source.
102
+ *
103
+ * @example
104
+ * class UserDto {
105
+ * @AutoMap()
106
+ * username: string; // Maps from source.username
107
+ * }
108
+ */
109
+ export function AutoMap() {
110
+ return (target, propertyKey) => {
111
+ const key = String(propertyKey);
112
+ const existingMappings = Reflect.getMetadata(METADATA_KEYS.PROPERTY_MAPPINGS, target.constructor) || new Map();
113
+ const existingConfig = existingMappings.get(key) || createDefaultConfig(key);
114
+ existingConfig.source = key; // Same name mapping
115
+ existingConfig.isTransform = false;
116
+ existingMappings.set(key, existingConfig);
117
+ Reflect.defineMetadata(METADATA_KEYS.PROPERTY_MAPPINGS, existingMappings, target.constructor);
118
+ Reflect.defineMetadata(METADATA_KEYS.AUTO_MAP, true, target.constructor, key);
119
+ };
120
+ }
121
+ /**
122
+ * Assigns a property to one or more field groups for runtime projection.
123
+ *
124
+ * @example
125
+ * // Basic usage with strings
126
+ * class UserDto {
127
+ * @FieldGroup('minimal', 'public')
128
+ * @AutoMap()
129
+ * username: string;
130
+ * }
131
+ *
132
+ * @example
133
+ * // Type-safe usage with const object (recommended for autocomplete!)
134
+ * const Groups = createFieldGroups('minimal', 'public', 'full');
135
+ *
136
+ * class UserDto {
137
+ * @FieldGroup(Groups.minimal, Groups.public) // ✨ Autocomplete!
138
+ * @AutoMap()
139
+ * username: string;
140
+ * }
141
+ */
142
+ export function FieldGroup(...groups) {
143
+ return (target, propertyKey) => {
144
+ const key = String(propertyKey);
145
+ const existingMappings = Reflect.getMetadata(METADATA_KEYS.PROPERTY_MAPPINGS, target.constructor) || new Map();
146
+ const existingConfig = existingMappings.get(key) || createDefaultConfig(key);
147
+ existingConfig.groups = [...new Set([...existingConfig.groups, ...groups])];
148
+ existingMappings.set(key, existingConfig);
149
+ Reflect.defineMetadata(METADATA_KEYS.PROPERTY_MAPPINGS, existingMappings, target.constructor);
150
+ // Also store in field groups map for quick lookup
151
+ const fieldGroups = Reflect.getMetadata(METADATA_KEYS.FIELD_GROUPS, target.constructor) || new Map();
152
+ for (const group of groups) {
153
+ const groupSet = fieldGroups.get(group) || new Set();
154
+ groupSet.add(key);
155
+ fieldGroups.set(group, groupSet);
156
+ }
157
+ Reflect.defineMetadata(METADATA_KEYS.FIELD_GROUPS, fieldGroups, target.constructor);
158
+ };
159
+ }
160
+ /**
161
+ * Creates a type-safe field groups object with autocomplete support.
162
+ * Use this to define your groups once and get IntelliSense everywhere!
163
+ *
164
+ * @example
165
+ * // Define groups once
166
+ * export const UserGroups = createFieldGroups('minimal', 'public', 'full');
167
+ *
168
+ * class UserDto {
169
+ * @FieldGroup(UserGroups.minimal, UserGroups.public) // ✨ Autocomplete!
170
+ * @AutoMap()
171
+ * username: string;
172
+ *
173
+ * @FieldGroup(UserGroups.full)
174
+ * @AutoMap()
175
+ * email: string;
176
+ * }
177
+ *
178
+ * // Usage with type-safety
179
+ * Mapper.map(user, UserDto, { group: UserGroups.minimal }); // ✨ Autocomplete!
180
+ */
181
+ export function createFieldGroups(...groups) {
182
+ const result = {};
183
+ for (const group of groups) {
184
+ result[group] = group;
185
+ }
186
+ return Object.freeze(result);
187
+ }
188
+ /**
189
+ * Built-in field groups with autocomplete - use these directly!
190
+ * No need to define your own groups for common use cases.
191
+ *
192
+ * @example
193
+ * class UserDto {
194
+ * @FieldGroup(Groups.MINIMAL, Groups.PUBLIC) // ✨ Autocomplete!
195
+ * @AutoMap()
196
+ * username: string;
197
+ *
198
+ * @FieldGroup(Groups.DETAILED)
199
+ * @AutoMap()
200
+ * email: string;
201
+ * }
202
+ *
203
+ * // Usage
204
+ * Mapper.map(user, UserDto, { group: Groups.MINIMAL }); // ✨ Autocomplete!
205
+ */
206
+ export const Groups = Object.freeze({
207
+ /** Minimal fields - just the essentials (e.g., id, name) */
208
+ MINIMAL: "minimal",
209
+ /** Summary fields - brief overview */
210
+ SUMMARY: "summary",
211
+ /** Public fields - safe to expose publicly */
212
+ PUBLIC: "public",
213
+ /** Private fields - internal use only */
214
+ PRIVATE: "private",
215
+ /** Detailed fields - comprehensive info */
216
+ DETAILED: "detailed",
217
+ /** Full fields - everything */
218
+ FULL: "full",
219
+ /** List view fields - for table/list displays */
220
+ LIST: "list",
221
+ /** Detail view fields - for detail pages */
222
+ DETAIL: "detail",
223
+ /** Admin fields - administrative data */
224
+ ADMIN: "admin",
225
+ /** API response fields */
226
+ API: "api",
227
+ });
228
+ /**
229
+ * Ignores a property during mapping.
230
+ *
231
+ * @example
232
+ * class UserDto {
233
+ * @Ignore()
234
+ * internalId: string; // Will not be mapped
235
+ * }
236
+ */
237
+ export function Ignore() {
238
+ return (target, propertyKey) => {
239
+ const key = String(propertyKey);
240
+ const existingMappings = Reflect.getMetadata(METADATA_KEYS.PROPERTY_MAPPINGS, target.constructor) || new Map();
241
+ const existingConfig = existingMappings.get(key) || createDefaultConfig(key);
242
+ existingConfig.ignore = true;
243
+ existingMappings.set(key, existingConfig);
244
+ Reflect.defineMetadata(METADATA_KEYS.PROPERTY_MAPPINGS, existingMappings, target.constructor);
245
+ Reflect.defineMetadata(METADATA_KEYS.IGNORE, true, target.constructor, key);
246
+ };
247
+ }
248
+ /**
249
+ * Specifies the type for nested object mapping.
250
+ *
251
+ * @example
252
+ * class UserDto {
253
+ * @NestedType(() => AddressDto)
254
+ * @MapFrom('address')
255
+ * address: AddressDto;
256
+ * }
257
+ */
258
+ export function NestedType(typeFactory) {
259
+ return (target, propertyKey) => {
260
+ Reflect.defineMetadata(METADATA_KEYS.NESTED_TYPE, typeFactory, target.constructor, String(propertyKey));
261
+ };
262
+ }
263
+ /**
264
+ * Creates a default property mapping config
265
+ */
266
+ function createDefaultConfig(targetKey) {
267
+ return {
268
+ targetKey,
269
+ source: targetKey,
270
+ isTransform: false,
271
+ groups: [],
272
+ ignore: false,
273
+ };
274
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * typemold
3
+ * A lightweight, high-performance object mapper for TypeScript and Node.js
4
+ *
5
+ * @author Chetan Joshi
6
+ * @license MIT
7
+ *
8
+ * @example
9
+ * // Basic mapping
10
+ * import { Mapper, MapFrom, AutoMap } from 'typemold';
11
+ *
12
+ * class UserDto {
13
+ * @AutoMap()
14
+ * username: string;
15
+ *
16
+ * @MapFrom('profile.avatar')
17
+ * avatar: string;
18
+ *
19
+ * @MapFrom((src) => src.age >= 18)
20
+ * isAdult: boolean;
21
+ * }
22
+ *
23
+ * const userDto = Mapper.map(userEntity, UserDto);
24
+ *
25
+ * @example
26
+ * // Runtime field projection
27
+ * const minimal = Mapper.map(user, UserDto, { pick: ['username', 'avatar'] });
28
+ * const safe = Mapper.map(user, UserDto, { omit: ['email', 'password'] });
29
+ * const public = Mapper.map(user, UserDto, { group: 'public' });
30
+ *
31
+ * @example
32
+ * // NestJS integration (optional)
33
+ * import { MapperModule, MapperService } from 'typemold';
34
+ *
35
+ * @Module({
36
+ * imports: [MapperModule.forRoot()],
37
+ * })
38
+ * export class AppModule {}
39
+ */
40
+ // Core Mapper
41
+ export { Mapper } from "./mapper";
42
+ // Decorators
43
+ export { MapFrom, createMapping, AutoMap, FieldGroup, createFieldGroups, Groups, Ignore, NestedType, } from "./decorators";
44
+ // Types
45
+ export { METADATA_KEYS, } from "./types";
46
+ // Registry (for advanced usage)
47
+ export { MappingRegistry, MapperFactory } from "./registry";
48
+ // Utilities
49
+ export { getNestedValue, pickKeys, omitKeys, isPlainObject, isClassInstance, } from "./utils";
50
+ // NestJS Integration
51
+ export { MapperModule, MapperService, MAPPER_OPTIONS, } from "./nestjs";
@@ -0,0 +1,149 @@
1
+ /**
2
+ * @sevirial/nest-mapper - Core Mapper
3
+ * Main mapper class with static methods for easy usage
4
+ */
5
+ import "reflect-metadata";
6
+ import { MapperFactory, MappingRegistry } from "./registry";
7
+ /**
8
+ * Main Mapper class - provides static methods for object mapping
9
+ *
10
+ * @example
11
+ * // Basic usage
12
+ * const userDto = Mapper.map(userEntity, UserDto);
13
+ *
14
+ * @example
15
+ * // With field projection
16
+ * const minimalUser = Mapper.map(userEntity, UserDto, { pick: ['username', 'avatar'] });
17
+ *
18
+ * @example
19
+ * // With field groups
20
+ * const publicUser = Mapper.map(userEntity, UserDto, { group: 'public' });
21
+ *
22
+ * @example
23
+ * // Array mapping
24
+ * const userDtos = Mapper.mapArray(users, UserDto);
25
+ */
26
+ export class Mapper {
27
+ /**
28
+ * Maps a source object to a target DTO class
29
+ *
30
+ * @param source - Source object to map from
31
+ * @param targetType - Target DTO class constructor
32
+ * @param options - Optional mapping options for field projection
33
+ * @returns Mapped target object
34
+ */
35
+ static map(source, targetType, options) {
36
+ if (source == null) {
37
+ return null;
38
+ }
39
+ const mapper = MapperFactory.createMapper(targetType, options);
40
+ const context = {
41
+ ...this.globalContext,
42
+ extras: options?.extras,
43
+ depth: 0,
44
+ visited: new WeakMap(),
45
+ };
46
+ return mapper(source, context);
47
+ }
48
+ /**
49
+ * Maps an array of source objects to target DTOs
50
+ *
51
+ * @param sources - Array of source objects
52
+ * @param targetType - Target DTO class constructor
53
+ * @param options - Optional mapping options for field projection
54
+ * @returns Array of mapped target objects
55
+ */
56
+ static mapArray(sources, targetType, options) {
57
+ if (!sources || !Array.isArray(sources)) {
58
+ return [];
59
+ }
60
+ const mapper = MapperFactory.createMapper(targetType, options);
61
+ const context = {
62
+ ...this.globalContext,
63
+ extras: options?.extras,
64
+ depth: 0,
65
+ visited: new WeakMap(),
66
+ };
67
+ const result = new Array(sources.length);
68
+ for (let i = 0; i < sources.length; i++) {
69
+ result[i] =
70
+ sources[i] != null
71
+ ? mapper(sources[i], context)
72
+ : null;
73
+ }
74
+ return result;
75
+ }
76
+ /**
77
+ * Maps source to target and returns only specified fields (shorthand)
78
+ *
79
+ * @example
80
+ * const result = Mapper.pick(user, UserDto, ['username', 'avatar']);
81
+ */
82
+ static pick(source, targetType, fields) {
83
+ return this.map(source, targetType, {
84
+ pick: fields,
85
+ });
86
+ }
87
+ /**
88
+ * Maps source to target excluding specified fields (shorthand)
89
+ *
90
+ * @example
91
+ * const result = Mapper.omit(user, UserDto, ['password', 'email']);
92
+ */
93
+ static omit(source, targetType, fields) {
94
+ return this.map(source, targetType, {
95
+ omit: fields,
96
+ });
97
+ }
98
+ /**
99
+ * Maps source using a predefined field group (shorthand)
100
+ *
101
+ * @example
102
+ * const result = Mapper.group(user, UserDto, 'minimal');
103
+ */
104
+ static group(source, targetType, groupName) {
105
+ return this.map(source, targetType, { group: groupName });
106
+ }
107
+ /**
108
+ * Creates a reusable mapper function for better performance in loops
109
+ *
110
+ * @example
111
+ * const mapToUserDto = Mapper.createMapper(UserDto);
112
+ * const users = entities.map(mapToUserDto);
113
+ */
114
+ static createMapper(targetType, options) {
115
+ const compiledMapper = MapperFactory.createMapper(targetType, options);
116
+ const context = {
117
+ ...this.globalContext,
118
+ extras: options?.extras,
119
+ };
120
+ return (source) => compiledMapper(source, context);
121
+ }
122
+ /**
123
+ * Registers a type converter for automatic type transformations
124
+ */
125
+ static registerConverter(converter) {
126
+ this.typeConverters.push(converter);
127
+ }
128
+ /**
129
+ * Sets global context that will be available to all transform functions
130
+ */
131
+ static setGlobalContext(context) {
132
+ this.globalContext = { ...this.globalContext, ...context };
133
+ }
134
+ /**
135
+ * Clears all cached mappers (useful for testing or hot-reload scenarios)
136
+ */
137
+ static clearCache() {
138
+ MappingRegistry.clearCache();
139
+ }
140
+ /**
141
+ * Gets the compiled mapper for inspection (useful for debugging)
142
+ */
143
+ static getCompiledMapper(targetType, options) {
144
+ const optionsKey = MappingRegistry.getOptionsKey(options);
145
+ return MappingRegistry.getCompiledMapper(targetType, optionsKey);
146
+ }
147
+ }
148
+ Mapper.typeConverters = [];
149
+ Mapper.globalContext = {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @sevirial/nest-mapper - NestJS Integration
3
+ * Re-exports for NestJS-specific functionality
4
+ */
5
+ export { MapperModule, } from "./mapper.module";
6
+ export { MapperService, MAPPER_OPTIONS, } from "./mapper.service";