ts-ref-kit 1.1.27 → 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,34 +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
 
243
- When multiple built projects run in the same browser context, assign each one a
244
- separate reflect module and select it at runtime before using reflection APIs:
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.
245
264
 
246
265
  ```typescript
247
266
  // vite.config.ts
248
267
  reflectParserPlugin({
249
- entry: 'src/main.ts',
250
- sourcePaths: 'src',
251
- reflectModule: 'project-a'
268
+ entry: 'src/main.ts',
269
+ sourcePaths: 'src',
270
+ reflectModule: 'project-a'
252
271
  })
253
272
  ```
254
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
+
255
285
  ```typescript
256
- // src/main.ts
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
257
305
  import { setReflectModule } from 'ts-ref-kit'
258
306
 
259
307
  setReflectModule('project-a')
260
308
  ```
261
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
+
262
322
  ### Custom Build Configuration
263
323
 
264
324
  If you're using other build tools or a custom build process, you can directly use `reflectLoader`:
@@ -267,16 +327,17 @@ If you're using other build tools or a custom build process, you can directly us
267
327
  import { reflectLoader } from 'ts-ref-kit/parser'
268
328
 
269
329
  const loader = reflectLoader({
270
- sourcePaths: 'src',
271
- exclude: /node_modules/,
272
- outputLog: true
330
+ sourcePaths: 'src',
331
+ reflectModule: 'project-a',
332
+ exclude: /node_modules/,
333
+ outputLog: true
273
334
  })
274
335
 
275
336
  // Transform a single file
276
337
  const transformedCode = loader.transform(sourceCode, sourceFileName)
277
338
 
278
- // Generate all metadata
279
- const allMetas = loader.outputAllMetas()
339
+ // Generate metadata injection code for the entry module
340
+ const metadataCode = loader.outputAllMetas()
280
341
  ```
281
342
 
282
343
  ### Parser Options
@@ -286,7 +347,7 @@ const allMetas = loader.outputAllMetas()
286
347
  - `exclude`: File paths to exclude, can be a string, regular expression, or array of them
287
348
  - `forEnabledClassOnly`: Whether to only process classes that implement the `EnableReflect` interface
288
349
  - `outputLog`: Whether to output log information
289
- - `reflectModule`: Optional reflect module name for isolating metadata when multiple built projects share one browser context
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.
290
351
 
291
352
  ### Working Principle
292
353
 
@@ -297,67 +358,41 @@ const allMetas = loader.outputAllMetas()
297
358
 
298
359
  ### Node.js Environment Usage
299
360
 
300
- 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:
301
362
 
302
363
  ```javascript
303
- const { reflectLoader } = require('ts-ref-kit/parser');
304
- const fs = require('fs');
364
+ const { reflectLoader } = require('ts-ref-kit/parser')
365
+ const fs = require('fs')
305
366
 
306
- const sourceCode = fs.readFileSync('src/types.ts', 'utf8');
367
+ const sourceCode = fs.readFileSync('src/types.ts', 'utf8')
307
368
  const loader = reflectLoader({
308
- sourcePaths: 'src'
309
- });
310
-
311
- const transformedCode = loader.transform(sourceCode, 'src/types.ts');
312
- const metadata = loader.outputAllMetas();
313
-
314
- console.log(metadata);
315
- ```
316
-
317
- ### tsconfig.json Configuration
369
+ sourcePaths: 'src',
370
+ reflectModule: 'project-a'
371
+ })
318
372
 
319
- 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()
320
375
 
321
- ```json
322
- {
323
- "compilerOptions": {
324
- "experimentalDecorators": true,
325
- "emitDecoratorMetadata": true,
326
- "plugins": [
327
- {
328
- "transform": "ts-ref-kit/parser"
329
- }
330
- ]
331
- }
332
- }
376
+ console.log(metadataCode)
333
377
  ```
334
378
 
335
- ### Webpack Configuration
336
-
337
- 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:
338
382
 
339
383
  ```javascript
340
- const { ReflectParserPlugin } = require('ts-ref-kit/parser');
341
-
342
- module.exports = {
343
- module: {
344
- rules: [
345
- {
346
- test: /\.tsx?$/,
347
- use: [
348
- {
349
- loader: 'ts-loader',
350
- options: {
351
- getCustomTransformers: () => ({
352
- before: [ReflectParserPlugin()]
353
- })
354
- }
355
- }
356
- ]
357
- }
358
- ]
359
- }
360
- };
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')
361
396
  ```
362
397
 
363
398
  ## Development