ts-ref-kit 1.1.26 → 1.2.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/README.md CHANGED
@@ -22,97 +22,98 @@ npm install ts-ref-kit
22
22
  ### Type Reflection Example
23
23
 
24
24
  ```typescript
25
- import { getClassDefinition, getInterfaceDefinition, getTypeAliasDefinition, getEnumDefinition } from 'ts-ref-kit';
25
+ import { getClassDefinition, getInterfaceDefinition, getTypeAliasDefinition, getEnumDefinition } from 'ts-ref-kit'
26
26
 
27
27
  // Get class definition
28
- const classDef = getClassDefinition('MyClass');
29
- console.log(classDef?.name); // Output: class name
30
- console.log(classDef?.properties); // Output: class properties list
31
- console.log(classDef?.methods); // Output: class methods list
28
+ const classDef = getClassDefinition('MyClass')
29
+ console.log(classDef?.name) // Output: class name
30
+ console.log(classDef?.properties) // Output: class properties list
31
+ console.log(classDef?.methods) // Output: class methods list
32
32
 
33
33
  // Get interface definition
34
- const interfaceDef = getInterfaceDefinition('MyInterface');
35
- console.log(interfaceDef?.name); // Output: interface name
36
- console.log(interfaceDef?.properties); // Output: interface properties list
37
- console.log(interfaceDef?.methods); // Output: interface methods list
34
+ const interfaceDef = getInterfaceDefinition('MyInterface')
35
+ console.log(interfaceDef?.name) // Output: interface name
36
+ console.log(interfaceDef?.properties) // Output: interface properties list
37
+ console.log(interfaceDef?.methods) // Output: interface methods list
38
38
 
39
39
  // Get type alias definition
40
- const typeAliasDef = getTypeAliasDefinition('MyTypeAlias');
41
- console.log(typeAliasDef?.name); // Output: type alias name
42
- console.log(typeAliasDef?.type); // Output: type definition
40
+ const typeAliasDef = getTypeAliasDefinition('MyTypeAlias')
41
+ console.log(typeAliasDef?.name) // Output: type alias name
42
+ console.log(typeAliasDef?.type) // Output: type definition
43
43
 
44
44
  // Get enum definition
45
- const enumDef = getEnumDefinition('MyEnum');
46
- console.log(enumDef?.name); // Output: enum name
47
- console.log(enumDef?.members); // Output: enum members
45
+ const enumDef = getEnumDefinition('MyEnum')
46
+ console.log(enumDef?.name) // Output: enum name
47
+ console.log(enumDef?.members) // Output: enum members
48
48
  ```
49
49
 
50
50
  ### Type Validation Example
51
51
 
52
52
  ```typescript
53
- import { isType, assertType } from 'ts-ref-kit';
53
+ import { isType, assertType } from 'ts-ref-kit'
54
54
 
55
55
  // Validate if value matches type
56
- const value = 'test';
57
- const isString = isType(value, 'string');
58
- console.log(isString); // Output: true
56
+ const value = 'test'
57
+ const isString = isType(value, 'string')
58
+ console.log(isString) // Output: true
59
59
 
60
60
  // Assert value matches type (throws error if not)
61
- assertType<string>(value, 'string');
61
+ assertType<string>(value, 'string')
62
62
 
63
- // Validate complex type
63
+ // Validate a reflected interface
64
64
  interface User {
65
- name: string;
66
- age: number;
65
+ name: string
66
+ age: number
67
67
  }
68
68
 
69
- const user = { name: 'John', age: 30 };
70
- const isUser = isType(user, '{ name: string, age: number }');
71
- console.log(isUser); // Output: true
69
+ const user = { name: 'John', age: 30 }
70
+ const isUser = isType(user, 'User')
71
+ console.log(isUser) // Output: true
72
72
  ```
73
73
 
74
74
  ### JSON Conversion Example
75
75
 
76
76
  ```typescript
77
- import { JSONTransfer } from 'ts-ref-kit';
77
+ import { JSONTransfer } from 'ts-ref-kit'
78
78
 
79
79
  class User {
80
- name: string;
81
- age: number;
82
- constructor() {
83
- this.name = '';
84
- this.age = 0;
85
- }
80
+ name: string
81
+ age: number
82
+
83
+ constructor() {
84
+ this.name = ''
85
+ this.age = 0
86
+ }
86
87
  }
87
88
 
88
- const jsonString = '{"name":"John","age":30}';
89
- const jsonTransfer = new JSONTransfer();
89
+ const jsonString = '{"name":"John","age":30}'
90
+ const jsonTransfer = new JSONTransfer()
90
91
 
91
92
  // Convert JSON string to class instance
92
- const user = jsonTransfer.parse<User>(jsonString, User);
93
- console.log(user instanceof User); // Output: true
94
- console.log(user.name); // Output: John
95
- console.log(user.age); // Output: 30
93
+ const user = jsonTransfer.parse<User>(jsonString, 'User')
94
+ console.log(user instanceof User) // Output: true
95
+ console.log(user.name) // Output: John
96
+ console.log(user.age) // Output: 30
96
97
  ```
97
98
 
98
99
  ### Enum Operations Example
99
100
 
100
101
  ```typescript
101
- import { getEnumNames, getEnumValues } from 'ts-ref-kit';
102
+ import { getEnumNames, getEnumValues } from 'ts-ref-kit'
102
103
 
103
104
  enum Color {
104
- Red,
105
- Green,
106
- Blue
105
+ Red,
106
+ Green,
107
+ Blue
107
108
  }
108
109
 
109
110
  // Get enum names list
110
- const colorNames = getEnumNames('Color');
111
- console.log(colorNames); // Output: ['Red', 'Green', 'Blue']
111
+ const colorNames = getEnumNames('Color')
112
+ console.log(colorNames) // Output: ['Red', 'Green', 'Blue']
112
113
 
113
114
  // Get enum values list
114
- const colorValues = getEnumValues({ Color });
115
- console.log(colorValues); // Output: [0, 1, 2]
115
+ const colorValues = getEnumValues({ Color })
116
+ console.log(colorValues) // Output: [0, 1, 2]
116
117
  ```
117
118
 
118
119
  ## API Documentation
@@ -128,50 +129,64 @@ console.log(colorValues); // Output: [0, 1, 2]
128
129
  ### Type Reflection API
129
130
 
130
131
  #### Class Related
132
+
131
133
  - `getClassDefinition(arg: Constructor | object | string): ClassDefinition | undefined`
132
134
  - `getClassByName(className: string): Constructor | undefined`
133
135
 
134
136
  #### Interface Related
137
+
135
138
  - `getInterfaceDefinition(name: string): InterfaceDefinition | undefined`
136
139
 
137
140
  #### Type Alias Related
141
+
138
142
  - `getTypeAliasDefinition(name: string, genericArgs?: TypeDefinition[]): TypeAliasDefinition | undefined`
139
143
 
140
144
  #### Enum Related
145
+
141
146
  - `getEnumDefinition(name: string): EnumDefinition | undefined`
142
147
  - `getEnumNames(enumName: string): string[]`
143
148
  - `getEnumValues(args: { [enumName: string]: Record<string, string | number> }): (string | number)[]`
144
149
 
145
- #### Generic Type
146
- - `getTypeDefinition(typeName: string, genericArgs?: TypeDefinition[]): TypeDefinition`
150
+ #### Type Utilities
151
+
152
+ - `getTypeDef(type: Type | TypeDefinition): TypeDefinition`
153
+ - `TypeDefinition.isPrimitiveType(type: TypeDefinition): boolean`
154
+ - `TypeDefinition.isArrayType(type: TypeDefinition): boolean`
155
+ - `TypeDefinition.isLiteralType(type: TypeDefinition): boolean`
156
+ - `TypeDefinition.isTypeLiteralType(type: TypeDefinition): boolean`
157
+ - `TypeDefinition.isUnionType(type: TypeDefinition): boolean`
158
+ - `TypeDefinition.isIntersectionType(type: TypeDefinition): boolean`
159
+ - `TypeDefinition.isTupleType(type: TypeDefinition): boolean`
160
+ - `TypeDefinition.isClassDefinition(type: TypeDefinition): boolean`
161
+ - `TypeDefinition.hasGenerics(type: TypeDefinition): boolean`
147
162
 
148
163
  ### Type Validation API
149
164
 
150
165
  - `isType(value: unknown, type: Type | TypeDefinition, depth: number = 5): boolean`
151
166
  - `assertType<T>(data: unknown, type: Type, depth: number = 5): T`
152
- - `validateValue(value: unknown, typeDef: TypeDefinition, depth: number = 5): ValidateResult`
167
+ - `validateValue(value: unknown, typeDef: TypeDefinition, depth: number = 1): ValidateResult`
153
168
 
154
169
  ### JSON Conversion API
155
170
 
156
171
  - `JSONTransfer` class
157
- - `parse<T = unknown>(jsonString: JSONString<T>, type?: Type): T`
172
+ - `parse<T = unknown>(jsonString: JSONString<T>, type?: Type): T`
158
173
 
159
174
  ### Configuration Options
160
175
 
161
176
  ```typescript
162
- import { ReflectConfig } from 'ts-ref-kit';
163
-
164
- ReflectConfig {
165
- // Validation error handler
166
- validationErrorHandler: function (e: ValidationError): void {
167
- console.error(e.message);
168
- console.error(e.failureResult?.errorStackFlow);
169
- },
170
- // Whether to enable validation
171
- validation: true,
172
- // Whether to enable debug mode
173
- debug: false
177
+ import { ReflectConfig } from 'ts-ref-kit'
178
+
179
+ // Validation error handler
180
+ ReflectConfig.validationErrorHandler = e => {
181
+ console.error(e.message)
182
+ console.error(e.failureResult?.errorStackFlow)
174
183
  }
184
+
185
+ // Whether to enable validation
186
+ ReflectConfig.validation = true
187
+
188
+ // Whether to enable debug mode
189
+ ReflectConfig.debug = false
175
190
  ```
176
191
 
177
192
  ## Advanced Usage
@@ -179,43 +194,45 @@ ReflectConfig {
179
194
  ### Generic Type Handling
180
195
 
181
196
  ```typescript
182
- import { getTypeDefinition } from 'ts-ref-kit';
197
+ import { getTypeDef } from 'ts-ref-kit'
183
198
 
184
- // Get generic type definition
185
- const arrayOfStringType = getTypeDefinition('Array<string>');
186
- console.log(arrayOfStringType.arrayElementType?.name); // Output: string
199
+ // Get a generic type definition
200
+ const mapType = getTypeDef('Map<string, number>')
201
+ console.log(mapType.name) // Output: Map
202
+ console.log(mapType.generics?.[0].name) // Output: string
203
+ console.log(mapType.generics?.[1].name) // Output: number
187
204
 
188
- // Use type literals
189
- const mapType = getTypeDefinition('Map<string, number>');
205
+ // Get a reflected type by name
206
+ const userType = getTypeDef('User')
207
+ console.log(userType.classDefinition?.name || userType.interfaceName || userType.typeAliasName)
190
208
  ```
191
209
 
192
210
  ### Type Relationship Queries
193
211
 
194
212
  ```typescript
195
- import { getClassDefinition, getInterfaceDefinition } from 'ts-ref-kit';
213
+ import { getClassDefinition } from 'ts-ref-kit'
196
214
 
197
215
  // Query if a class is a subclass of another class
198
- const classDef = getClassDefinition('MyClass');
199
- const isSubClass = classDef?.isSubClassOf('BaseClass');
216
+ const classDef = getClassDefinition('MyClass')
217
+ const isSubClass = classDef?.isSubClassOf('BaseClass')
200
218
 
201
219
  // Query if a class is a superclass of another class
202
- const isSuperClass = classDef?.isSuperClassOf('DerivedClass');
220
+ const isSuperClass = classDef?.isSuperClassOf('DerivedClass')
203
221
  ```
204
222
 
205
223
  ### Special Type Registration
206
224
 
207
225
  ```typescript
208
- import { registerSpecialType } from 'ts-ref-kit';
226
+ import { registerSpecialType } from 'ts-ref-kit'
209
227
 
210
228
  // Register custom special type
211
- registerSpecialType('MySpecialType', (typeArgs) => {
212
- return {
229
+ registerSpecialType({
213
230
  name: 'MySpecialType',
214
- type: {
215
- // Type definition
231
+ genericParams: ['T'],
232
+ getType(typeArg) {
233
+ return typeArg
216
234
  }
217
- };
218
- });
235
+ })
219
236
  ```
220
237
 
221
238
  ## Parser Configuration
@@ -231,15 +248,77 @@ import { defineConfig } from 'vite'
231
248
  import { reflectParserPlugin } from 'ts-ref-kit/parser'
232
249
 
233
250
  export default defineConfig({
234
- plugins: [
235
- reflectParserPlugin({
236
- entry: 'src/main.ts',
237
- sourcePaths: 'src'
238
- })
239
- ]
251
+ plugins: [
252
+ reflectParserPlugin({
253
+ entry: 'src/main.ts',
254
+ sourcePaths: 'src'
255
+ })
256
+ ]
240
257
  })
241
258
  ```
242
259
 
260
+ When multiple independently built projects run in the same browser or Node.js
261
+ context, assign each project a separate reflect module. `default` is only safe
262
+ for a single project/build output; if multiple outputs all write metadata to
263
+ `default`, the last one loaded may overwrite the others.
264
+
265
+ ```typescript
266
+ // vite.config.ts
267
+ reflectParserPlugin({
268
+ entry: 'src/main.ts',
269
+ sourcePaths: 'src',
270
+ reflectModule: 'project-a'
271
+ })
272
+ ```
273
+
274
+ #### Shared runtime usage
275
+
276
+ ```typescript
277
+ // src/reflect.ts
278
+ import { getReflectModule } from 'ts-ref-kit'
279
+
280
+ export const reflect = getReflectModule('project-a')
281
+ export const ReflectClass = reflect.ReflectClass
282
+ export const ReflectValidate = reflect.ReflectValidate
283
+ ```
284
+
285
+ ```typescript
286
+ import { reflect } from './reflect'
287
+
288
+ reflect.getClassDefinition('User')
289
+ reflect.isType(user, 'User')
290
+ ```
291
+
292
+ Use this style when several packages share the same `ts-ref-kit` runtime, for
293
+ example when libraries depend on the application's installed copy. In this
294
+ scenario, avoid `setReflectModule` for isolation: it changes the shared default
295
+ module name and can affect other packages using the same runtime.
296
+
297
+ #### Bundled runtime compatibility
298
+
299
+ If a package bundles its own copy of `ts-ref-kit`, its default module state is
300
+ local to that bundled copy. Existing code that uses top-level APIs can be kept by
301
+ setting the module once at package startup:
302
+
303
+ ```typescript
304
+ // package entry
305
+ import { setReflectModule } from 'ts-ref-kit'
306
+
307
+ setReflectModule('project-a')
308
+ ```
309
+
310
+ After that, top-level APIs in that bundled package use `project-a`:
311
+
312
+ ```typescript
313
+ import { getClassDefinition, isType } from 'ts-ref-kit'
314
+
315
+ getClassDefinition('User')
316
+ isType(user, 'User')
317
+ ```
318
+
319
+ This compatibility style is intended for bundled/inline runtimes. For shared
320
+ runtimes, prefer the explicit `getReflectModule(name)` API shown above.
321
+
243
322
  ### Custom Build Configuration
244
323
 
245
324
  If you're using other build tools or a custom build process, you can directly use `reflectLoader`:
@@ -248,16 +327,17 @@ If you're using other build tools or a custom build process, you can directly us
248
327
  import { reflectLoader } from 'ts-ref-kit/parser'
249
328
 
250
329
  const loader = reflectLoader({
251
- sourcePaths: 'src',
252
- exclude: /node_modules/,
253
- outputLog: true
330
+ sourcePaths: 'src',
331
+ reflectModule: 'project-a',
332
+ exclude: /node_modules/,
333
+ outputLog: true
254
334
  })
255
335
 
256
336
  // Transform a single file
257
337
  const transformedCode = loader.transform(sourceCode, sourceFileName)
258
338
 
259
- // Generate all metadata
260
- const allMetas = loader.outputAllMetas()
339
+ // Generate metadata injection code for the entry module
340
+ const metadataCode = loader.outputAllMetas()
261
341
  ```
262
342
 
263
343
  ### Parser Options
@@ -267,6 +347,7 @@ const allMetas = loader.outputAllMetas()
267
347
  - `exclude`: File paths to exclude, can be a string, regular expression, or array of them
268
348
  - `forEnabledClassOnly`: Whether to only process classes that implement the `EnableReflect` interface
269
349
  - `outputLog`: Whether to output log information
350
+ - `reflectModule`: Optional reflect module name for isolating metadata. Use a unique value for each independently built project/package that can run in the same browser or Node.js context.
270
351
 
271
352
  ### Working Principle
272
353
 
@@ -277,67 +358,41 @@ const allMetas = loader.outputAllMetas()
277
358
 
278
359
  ### Node.js Environment Usage
279
360
 
280
- In Node.js environments, you can directly use the parser to analyze TypeScript files:
361
+ In Node.js environments, you can directly use the parser to analyze TypeScript files and generate injection code:
281
362
 
282
363
  ```javascript
283
- const { reflectLoader } = require('ts-ref-kit/parser');
284
- const fs = require('fs');
364
+ const { reflectLoader } = require('ts-ref-kit/parser')
365
+ const fs = require('fs')
285
366
 
286
- const sourceCode = fs.readFileSync('src/types.ts', 'utf8');
367
+ const sourceCode = fs.readFileSync('src/types.ts', 'utf8')
287
368
  const loader = reflectLoader({
288
- sourcePaths: 'src'
289
- });
290
-
291
- const transformedCode = loader.transform(sourceCode, 'src/types.ts');
292
- const metadata = loader.outputAllMetas();
293
-
294
- console.log(metadata);
295
- ```
296
-
297
- ### tsconfig.json Configuration
369
+ sourcePaths: 'src',
370
+ reflectModule: 'project-a'
371
+ })
298
372
 
299
- To enable decorator metadata generation, add the following configuration to your `tsconfig.json`:
373
+ const transformedCode = loader.transform(sourceCode, 'src/types.ts')
374
+ const metadataCode = loader.outputAllMetas()
300
375
 
301
- ```json
302
- {
303
- "compilerOptions": {
304
- "experimentalDecorators": true,
305
- "emitDecoratorMetadata": true,
306
- "plugins": [
307
- {
308
- "transform": "ts-ref-kit/parser"
309
- }
310
- ]
311
- }
312
- }
376
+ console.log(metadataCode)
313
377
  ```
314
378
 
315
- ### Webpack Configuration
316
-
317
- In Webpack projects, you can configure through custom transformers:
379
+ You can also initialize reflection directly in Node.js with `setupReflectTypes`.
380
+ The `reflectModule` option is optional and defaults to `default`, but it should
381
+ match the runtime module name when you isolate multiple projects:
318
382
 
319
383
  ```javascript
320
- const { ReflectParserPlugin } = require('ts-ref-kit/parser');
321
-
322
- module.exports = {
323
- module: {
324
- rules: [
325
- {
326
- test: /\.tsx?$/,
327
- use: [
328
- {
329
- loader: 'ts-loader',
330
- options: {
331
- getCustomTransformers: () => ({
332
- before: [ReflectParserPlugin()]
333
- })
334
- }
335
- }
336
- ]
337
- }
338
- ]
339
- }
340
- };
384
+ const { setupReflectTypes } = require('ts-ref-kit/parser')
385
+ const { getReflectModule } = require('ts-ref-kit')
386
+
387
+ await setupReflectTypes({
388
+ filePaths: ['src'],
389
+ sourceFolder: process.cwd(),
390
+ distFolder: process.cwd(),
391
+ reflectModule: 'project-a'
392
+ })
393
+
394
+ const reflect = getReflectModule('project-a')
395
+ const classDef = reflect.getClassDefinition('User')
341
396
  ```
342
397
 
343
398
  ## Development
@@ -362,4 +417,4 @@ npm run lint
362
417
 
363
418
  ## License
364
419
 
365
- MIT
420
+ MIT