@travetto/transformer 7.0.0-rc.0 → 7.0.0-rc.2

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.
@@ -16,6 +16,14 @@ const UNDEFINED = Symbol();
16
16
 
17
17
  const MAPPED_TYPE_SET = new Set(['Omit', 'Pick', 'Required', 'Partial']);
18
18
  const isMappedType = (type: string | undefined): type is MappedType['operation'] => MAPPED_TYPE_SET.has(type!);
19
+ const getMappedFields = (type: ts.Type): string[] | undefined => {
20
+ if (type.isStringLiteral()) {
21
+ return [type.value];
22
+ } else if (type.isUnion() && type.types.every(subType => subType.isStringLiteral())) {
23
+ return type.types.map(subType => subType.value);
24
+ }
25
+ };
26
+
19
27
  /**
20
28
  * List of global types that can be parameterized
21
29
  */
@@ -74,7 +82,7 @@ export function TypeCategorize(resolver: TransformResolver, type: ts.Type): { ca
74
82
  try {
75
83
  const source = DeclarationUtil.getPrimaryDeclarationNode(type).getSourceFile();
76
84
  const sourceFile = source.fileName;
77
- if (sourceFile && ManifestModuleUtil.TYPINGS_EXT_RE.test(sourceFile) && !resolver.isKnownFile(sourceFile)) {
85
+ if (sourceFile && ManifestModuleUtil.TYPINGS_EXT_REGEX.test(sourceFile) && !resolver.isKnownFile(sourceFile)) {
78
86
  return { category: 'foreign', type };
79
87
  }
80
88
  } catch { }
@@ -93,7 +101,7 @@ export function TypeCategorize(resolver: TransformResolver, type: ts.Type): { ca
93
101
  const sourceFile = source.fileName;
94
102
  if (sourceFile?.includes('typescript/lib')) {
95
103
  return { category: 'literal', type };
96
- } else if (sourceFile && ManifestModuleUtil.TYPINGS_EXT_RE.test(sourceFile) && !resolver.isKnownFile(sourceFile)) {
104
+ } else if (sourceFile && ManifestModuleUtil.TYPINGS_EXT_REGEX.test(sourceFile) && !resolver.isKnownFile(sourceFile)) {
97
105
  return { category: 'foreign', type: resolvedType };
98
106
  } else if (!resolvedType.isClass()) { // Not a real type
99
107
  return { category: 'shape', type: resolvedType };
@@ -105,7 +113,7 @@ export function TypeCategorize(resolver: TransformResolver, type: ts.Type): { ca
105
113
  } else if (type.isLiteral()) {
106
114
  return { category: 'shape', type };
107
115
  } else if (objectFlags & ts.ObjectFlags.Mapped) { // Mapped types
108
- if (type.getProperties().some(x => x.declarations || x.valueDeclaration)) {
116
+ if (type.getProperties().some(property => property.declarations || property.valueDeclaration)) {
109
117
  return { category: 'mapped', type };
110
118
  }
111
119
  }
@@ -117,7 +125,7 @@ export function TypeCategorize(resolver: TransformResolver, type: ts.Type): { ca
117
125
  */
118
126
  export const TypeBuilder: {
119
127
  [K in Category]: {
120
- build(resolver: TransformResolver, type: ts.Type, alias?: ts.Symbol): AnyType | undefined;
128
+ build(resolver: TransformResolver, type: ts.Type, context: { alias?: ts.Symbol, node?: ts.Node }): AnyType | undefined;
121
129
  finalize?(type: Type<K>): AnyType;
122
130
  }
123
131
  } = {
@@ -152,7 +160,7 @@ export const TypeBuilder: {
152
160
  }
153
161
  }
154
162
  if (values.length > 0) {
155
- return ({ key: 'template', template: { op: 'and', values }, ctor: String });
163
+ return ({ key: 'template', template: { operation: 'and', values }, ctor: String });
156
164
  }
157
165
  }
158
166
  }
@@ -215,11 +223,11 @@ export const TypeBuilder: {
215
223
  let undefinable = false;
216
224
  let nullable = false;
217
225
  const remainder = uType.types.filter(ut => {
218
- const u = (ut.getFlags() & (ts.TypeFlags.Undefined)) > 0;
219
- const n = (ut.getFlags() & (ts.TypeFlags.Null)) > 0;
220
- undefinable ||= u;
221
- nullable ||= n;
222
- return !(u || n);
226
+ const isUndefined = (ut.getFlags() & (ts.TypeFlags.Undefined)) > 0;
227
+ const isNull = (ut.getFlags() & (ts.TypeFlags.Null)) > 0;
228
+ undefinable ||= isUndefined;
229
+ nullable ||= isNull;
230
+ return !(isUndefined || isNull);
223
231
  });
224
232
  const name = CoreUtil.getSymbol(uType)?.getName();
225
233
  return { key: 'composition', name, undefinable, nullable, tsSubTypes: remainder, subTypes: [], operation: uType.isUnion() ? 'or' : 'and' };
@@ -239,77 +247,76 @@ export const TypeBuilder: {
239
247
  ctor: String,
240
248
  nullable: type.nullable,
241
249
  undefinable: type.undefinable,
242
- template: { op: 'or', values: subTypes.map(x => transformCast<TemplateType>(x).template!) }
250
+ template: { operation: 'or', values: subTypes.map(subType => transformCast<TemplateType>(subType).template!) }
243
251
  };
244
252
  } else if (subTypes.length === 1) {
245
253
  return { undefinable, nullable, ...first };
246
- } else if (first.key === 'literal' && subTypes.every(el => el.name === first.name)) { // We have a common
254
+ } else if (first.key === 'literal' && subTypes.every(item => item.name === first.name)) { // We have a common
247
255
  type.commonType = first;
248
- } else if (type.operation === 'and' && first.key === 'shape' && subTypes.every(el => el.key === 'shape')) { // All shapes
249
- return { importName: first.importName, name: first.name, key: 'shape', fieldTypes: subTypes.reduce((acc, x) => ({ ...acc, ...x.fieldTypes }), {}) };
256
+ } else if (type.operation === 'and' && first.key === 'shape' && subTypes.every(item => item.key === 'shape')) { // All shapes
257
+ return {
258
+ importName: first.importName,
259
+ name: first.name,
260
+ key: 'shape',
261
+ fieldTypes: subTypes.reduce((map, subType) => ({ ...map, ...subType.fieldTypes }), {})
262
+ };
250
263
  }
251
264
  return type;
252
265
  }
253
266
  },
254
267
  mapped: {
255
- build: (resolver, type, alias) => {
268
+ build: (resolver, type, context) => {
256
269
  let mainType: ts.Type | undefined;
257
270
  let fields: string[] | undefined;
258
271
  let operation: string | undefined;
272
+ let name: string | undefined;
259
273
 
260
- const decls = DeclarationUtil.getDeclarations(type).filter(x => ts.isTypeAliasDeclaration(x));
261
- if (decls.length > 0) {
262
- const ref = decls[0].type;
263
- if (ts.isTypeReferenceNode(ref) && ref.typeArguments && ref.typeArguments.length > 0) {
264
- const [first, second] = ref.typeArguments;
265
- mainType = resolver.getType(first);
266
- operation = ref.typeName.getText();
267
- if (second) {
268
- const resolved = resolver.getType(second);
269
- if (resolved.isStringLiteral()) {
270
- fields = [resolved.value];
271
- } else if (resolved.isUnion() && resolved.types.every(t => t.isStringLiteral())) {
272
- fields = resolved.types.map(t => t.value);
273
- }
274
- }
275
- }
276
- } else {
277
- mainType = type.aliasTypeArguments?.[0]!;
278
- operation = type.aliasSymbol?.escapedName.toString();
279
- fields = type.getApparentProperties().map(p => p.getName());
274
+ const declarations = DeclarationUtil.getDeclarations(type).filter(declaration => ts.isTypeAliasDeclaration(declaration));
275
+ const ref = declarations[0]?.type;
276
+
277
+ if (ref && ts.isTypeReferenceNode(ref) && ref.typeArguments && ref.typeArguments.length > 0) {
278
+ const [first, second] = ref.typeArguments;
279
+ mainType = resolver.getType(first);
280
+ operation = ref.typeName.getText();
281
+ name = resolver.getTypeAsString(type)!;
282
+ fields = !second ? [] : getMappedFields(resolver.getType(second));
283
+ } else if (type.aliasTypeArguments && type.aliasSymbol) {
284
+ mainType = type.aliasTypeArguments[0];
285
+ operation = type.aliasSymbol.escapedName.toString();
286
+ fields = (type.aliasTypeArguments.length > 1) ? getMappedFields(type.aliasTypeArguments[1]) : [];
287
+ name = `${resolver.getTypeAsString(mainType)!}_${operation}_${fields?.join('_')}`;
280
288
  }
281
289
 
282
290
  if (!isMappedType(operation) || fields === undefined || !mainType || !mainType.isClass()) {
283
- return TypeBuilder.shape.build(resolver, type, alias);
291
+ return TypeBuilder.shape.build(resolver, type, context);
284
292
  }
285
293
 
286
294
  const importName = resolver.getTypeImportName(mainType) ?? '<unknown>';
287
295
  const mappedClassName = resolver.getTypeAsString(mainType)!;
288
- const name = resolver.getTypeAsString(type)!;
289
296
 
290
297
  return { key: 'mapped', name, original: mainType, operation, importName, mappedClassName, fields };
291
298
  }
292
299
  },
293
300
  shape: {
294
- build: (resolver, type, alias?) => {
301
+ build: (resolver, type, context) => {
295
302
  const tsFieldTypes: Record<string, ts.Type> = {};
296
- const name = CoreUtil.getSymbol(alias ?? type)?.getName();
303
+ const name = CoreUtil.getSymbol(context?.alias ?? type)?.getName();
297
304
  const importName = resolver.getTypeImportName(type) ?? '<unknown>';
298
305
  const tsTypeArguments = resolver.getAllTypeArguments(type);
299
- const props = resolver.getPropertiesOfType(type);
300
- if (props.length === 0) {
306
+ const properties = resolver.getPropertiesOfType(type);
307
+ if (properties.length === 0) {
301
308
  return { key: 'literal', name: 'Object', ctor: Object, importName };
302
309
  }
303
310
 
304
- for (const member of props) {
305
- const dec = DeclarationUtil.getPrimaryDeclarationNode(member);
306
- if (DeclarationUtil.isPublic(dec)) { // If public
307
- const memberType = resolver.getType(dec);
311
+ for (const member of properties) {
312
+ const decorator = DeclarationUtil.getPrimaryDeclarationNode(member);
313
+ if (DeclarationUtil.isPublic(decorator)) { // If public
314
+ const memberType = resolver.getType(decorator);
308
315
  if (
309
316
  !member.getName().includes('@') && // if not a symbol
310
317
  !memberType.getCallSignatures().length // if not a function
311
318
  ) {
312
- if ((ts.isPropertySignature(dec) || ts.isPropertyDeclaration(dec)) && !!dec.questionToken) {
319
+ if ((ts.isPropertySignature(decorator) || ts.isPropertyDeclaration(decorator)) && !!decorator.questionToken) {
313
320
  Object.defineProperty(memberType, UNDEFINED, { value: true });
314
321
  }
315
322
  tsFieldTypes[member.getName()] = memberType;
@@ -331,7 +338,7 @@ export const TypeBuilder: {
331
338
  // Resolving relative to source file
332
339
  if (!importName || importName.startsWith('.')) {
333
340
  const rawSourceFile: string = DeclarationUtil.getDeclarations(type)
334
- ?.find(x => ts.getAllJSDocTags(x, (t): t is ts.JSDocTag => t.tagName.getText() === 'concrete').length)
341
+ ?.find(declaration => ts.getAllJSDocTags(declaration, (node): node is ts.JSDocTag => node.tagName.getText() === 'concrete').length)
335
342
  ?.getSourceFile().fileName ?? '';
336
343
 
337
344
  if (!importName || importName === '.') {
@@ -344,8 +351,9 @@ export const TypeBuilder: {
344
351
 
345
352
  // Convert name to $Concrete suffix if not provided
346
353
  if (!name) {
347
- const [decl] = DeclarationUtil.getDeclarations(type).filter(x => ts.isInterfaceDeclaration(x) || ts.isTypeAliasDeclaration(x));
348
- name = `${decl.name.text}$Concrete`;
354
+ const [primaryDeclaration] = DeclarationUtil.getDeclarations(type)
355
+ .filter(declaration => ts.isInterfaceDeclaration(declaration) || ts.isTypeAliasDeclaration(declaration));
356
+ name = `${primaryDeclaration.name.text}$Concrete`;
349
357
  }
350
358
 
351
359
  return { key: 'managed', name, importName };
@@ -4,12 +4,12 @@ export class CoerceUtil {
4
4
  /**
5
5
  * Is a value a plain JS object, created using {}
6
6
  */
7
- static #isPlainObject(obj: unknown): obj is Record<string, unknown> {
8
- return typeof obj === 'object' // separate from primitives
9
- && obj !== undefined
10
- && obj !== null // is obvious
11
- && obj.constructor === Object // separate instances (Array, DOM, ...)
12
- && Object.prototype.toString.call(obj) === '[object Object]'; // separate build-in like Math
7
+ static #isPlainObject(value: unknown): value is Record<string, unknown> {
8
+ return typeof value === 'object' // separate from primitives
9
+ && value !== undefined
10
+ && value !== null // is obvious
11
+ && value.constructor === Object // separate instances (Array, DOM, ...)
12
+ && Object.prototype.toString.call(value) === '[object Object]'; // separate build-in like Math
13
13
  }
14
14
 
15
15
  /**
@@ -73,10 +73,10 @@ export class SimpleResolver implements TransformResolver {
73
73
 
74
74
  /**
75
75
  * Get type from element
76
- * @param el
76
+ * @param value
77
77
  */
78
- getType(el: ts.Type | ts.Node): ts.Type {
79
- return 'getSourceFile' in el ? this.#tsChecker.getTypeAtLocation(el) : el;
78
+ getType(value: ts.Type | ts.Node): ts.Type {
79
+ return 'getSourceFile' in value ? this.#tsChecker.getTypeAtLocation(value) : value;
80
80
  }
81
81
 
82
82
  /**
@@ -106,7 +106,8 @@ export class SimpleResolver implements TransformResolver {
106
106
  * Get list of properties
107
107
  */
108
108
  getPropertiesOfType(type: ts.Type): ts.Symbol[] {
109
- return this.#tsChecker.getPropertiesOfType(type).filter(x => x.getName() !== '__proto__' && x.getName() !== 'prototype');
109
+ return this.#tsChecker.getPropertiesOfType(type)
110
+ .filter(property => property.getName() !== '__proto__' && property.getName() !== 'prototype');
110
111
  }
111
112
 
112
113
  /**
@@ -123,7 +124,7 @@ export class SimpleResolver implements TransformResolver {
123
124
  const { category, type } = TypeCategorize(this, resType);
124
125
  const { build, finalize } = TypeBuilder[category];
125
126
 
126
- let result = build(this, type, alias);
127
+ let result = build(this, type, { alias, node: node && 'kind' in node ? node : undefined });
127
128
 
128
129
  // Convert via cache if needed
129
130
  result = visited.getOrSet(type, result);
@@ -161,11 +162,11 @@ export class SimpleResolver implements TransformResolver {
161
162
 
162
163
  try {
163
164
  return resolve(this.getType(node));
164
- } catch (err) {
165
- if (!(err instanceof Error)) {
166
- throw err;
165
+ } catch (error) {
166
+ if (!(error instanceof Error)) {
167
+ throw error;
167
168
  }
168
- console.error(`Unable to resolve type in ${importName}`, err.stack);
169
+ console.error(`Unable to resolve type in ${importName}`, error.stack);
169
170
  return { key: 'literal', ctor: Object, name: 'object' };
170
171
  }
171
172
  }
package/src/state.ts CHANGED
@@ -15,25 +15,27 @@ import { CoreUtil } from './util/core.ts';
15
15
  import { LiteralUtil } from './util/literal.ts';
16
16
  import { SystemUtil } from './util/system.ts';
17
17
 
18
- function hasOriginal(n: ts.Node): n is ts.Node & { original: ts.Node } {
19
- return !!n && !n.parent && 'original' in n && !!n.original;
18
+ function hasOriginal(node: ts.Node): node is ts.Node & { original: ts.Node } {
19
+ return !!node && !node.parent && 'original' in node && !!node.original;
20
20
  }
21
21
 
22
- function hasEscapedName(n: ts.Node): n is ts.Node & { name: { escapedText: string } } {
23
- return !!n && 'name' in n && typeof n.name === 'object' && !!n.name && 'escapedText' in n.name && !!n.name.escapedText;
22
+ function hasEscapedName(node: ts.Node): node is ts.Node & { name: { escapedText: string } } {
23
+ return !!node && 'name' in node && typeof node.name === 'object' && !!node.name && 'escapedText' in node.name && !!node.name.escapedText;
24
24
  }
25
25
 
26
- function isRedefinableDeclaration(x: ts.Node): x is ts.InterfaceDeclaration | ts.ClassDeclaration | ts.FunctionDeclaration {
27
- return ts.isFunctionDeclaration(x) || ts.isClassDeclaration(x) || ts.isInterfaceDeclaration(x);
26
+ function isRedefinableDeclaration(node: ts.Node): node is ts.InterfaceDeclaration | ts.ClassDeclaration | ts.FunctionDeclaration {
27
+ return ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node);
28
28
  }
29
29
 
30
+ const FOREIGN_TYPE_REGISTRY_FILE = '@travetto/runtime/src/function';
31
+
30
32
  /**
31
33
  * Transformer runtime state
32
34
  */
33
35
  export class TransformerState implements State {
34
36
  #resolver: SimpleResolver;
35
37
  #imports: ImportManager;
36
- #modIdent: ts.Identifier;
38
+ #moduleIdentifier: ts.Identifier;
37
39
  #manifestIndex: ManifestIndex;
38
40
  #syntheticIdentifiers = new Map<string, ts.Identifier>();
39
41
  #decorators = new Map<string, ts.PropertyAccessExpression>();
@@ -91,8 +93,8 @@ export class TransformerState implements State {
91
93
  const resolved = this.resolveType(node);
92
94
  if (resolved.key !== 'managed') {
93
95
  const file = node.getSourceFile().fileName;
94
- const src = this.#resolver.getFileImportName(file);
95
- throw new Error(`Unable to import non-external type: ${node.getText()} ${resolved.key}: ${src}`);
96
+ const source = this.#resolver.getFileImportName(file);
97
+ throw new Error(`Unable to import non-external type: ${node.getText()} ${resolved.key}: ${source}`);
96
98
  }
97
99
  return resolved;
98
100
  }
@@ -134,9 +136,9 @@ export class TransformerState implements State {
134
136
  */
135
137
  readDocTagList(node: ts.Declaration, name: string): string[] {
136
138
  return this.readDocTag(node, name)
137
- .flatMap(x => x.split(/\s*,\s*/g))
138
- .map(x => x.replace(/`/g, ''))
139
- .filter(x => !!x);
139
+ .flatMap(tag => tag.split(/\s*,\s*/g))
140
+ .map(tag => tag.replace(/`/g, ''))
141
+ .filter(tag => !!tag);
140
142
  }
141
143
 
142
144
  /**
@@ -145,8 +147,8 @@ export class TransformerState implements State {
145
147
  importDecorator(pth: string, name: string): ts.PropertyAccessExpression | undefined {
146
148
  if (!this.#decorators.has(`${pth}:${name}`)) {
147
149
  const ref = this.#imports.importFile(pth);
148
- const ident = this.factory.createIdentifier(name);
149
- this.#decorators.set(name, this.factory.createPropertyAccessExpression(ref.ident, ident));
150
+ const identifier = this.factory.createIdentifier(name);
151
+ this.#decorators.set(name, this.factory.createPropertyAccessExpression(ref.identifier, identifier));
150
152
  }
151
153
  return this.#decorators.get(name);
152
154
  }
@@ -162,22 +164,22 @@ export class TransformerState implements State {
162
164
  /**
163
165
  * Read a decorator's metadata
164
166
  */
165
- getDecoratorMeta(dec: ts.Decorator): DecoratorMeta | undefined {
166
- const ident = DecoratorUtil.getDecoratorIdent(dec);
167
- const type = this.#resolver.getType(ident);
168
- const decl = DeclarationUtil.getOptionalPrimaryDeclarationNode(type);
169
- const src = decl?.getSourceFile().fileName;
170
- const mod = src ? this.#resolver.getFileImportName(src, true) : undefined;
167
+ getDecoratorMeta(decorator: ts.Decorator): DecoratorMeta | undefined {
168
+ const identifier = DecoratorUtil.getDecoratorIdentifier(decorator);
169
+ const type = this.#resolver.getType(identifier);
170
+ const declaration = DeclarationUtil.getOptionalPrimaryDeclarationNode(type);
171
+ const source = declaration?.getSourceFile().fileName;
172
+ const mod = source ? this.#resolver.getFileImportName(source, true) : undefined;
171
173
  const file = this.#manifestIndex.getFromImport(mod ?? '')?.outputFile;
172
174
  const targets = DocUtil.readAugments(type);
173
175
  const example = DocUtil.readExample(type);
174
176
  const module = file ? mod : undefined;
175
- const name = ident ?
176
- ident.escapedText?.toString()! :
177
+ const name = identifier ?
178
+ identifier.escapedText?.toString()! :
177
179
  undefined;
178
180
 
179
- if (ident && name) {
180
- return { dec, ident, file, module, targets, name, options: example };
181
+ if (identifier && name) {
182
+ return { decorator, identifier, file, module, targets, name, options: example };
181
183
  }
182
184
  }
183
185
 
@@ -186,8 +188,8 @@ export class TransformerState implements State {
186
188
  */
187
189
  getDecoratorList(node: ts.Node): DecoratorMeta[] {
188
190
  return ts.canHaveDecorators(node) ? (ts.getDecorators(node) ?? [])
189
- .map(dec => this.getDecoratorMeta(dec))
190
- .filter(x => !!x) : [];
191
+ .map(decorator => this.getDecoratorMeta(decorator))
192
+ .filter(meta => !!meta) : [];
191
193
  }
192
194
 
193
195
  /**
@@ -199,26 +201,26 @@ export class TransformerState implements State {
199
201
 
200
202
  /**
201
203
  * Register statement for inclusion in final output
202
- * @param stmt
204
+ * @param added
203
205
  * @param before
204
206
  */
205
207
  addStatements(added: ts.Statement[], before?: ts.Node | number): void {
206
- const stmts = this.source.statements.slice(0);
207
- let idx = stmts.length + 1000;
208
+ const statements = this.source.statements.slice(0);
209
+ let idx = statements.length + 1000;
208
210
 
209
211
  if (before && typeof before !== 'number') {
210
- let n = before;
211
- if (hasOriginal(n)) {
212
- n = n.original;
212
+ let node = before;
213
+ if (hasOriginal(node)) {
214
+ node = node.original;
213
215
  }
214
- while (n && !ts.isSourceFile(n.parent) && n !== n.parent) {
215
- n = n.parent;
216
+ while (node && !ts.isSourceFile(node.parent) && node !== node.parent) {
217
+ node = node.parent;
216
218
  }
217
- if (!ts.isStatement(n)) {
219
+ if (!ts.isStatement(node)) {
218
220
  throw new Error('Unable to find statement at top level');
219
221
  }
220
- if (n && ts.isSourceFile(n.parent) && stmts.indexOf(n) >= 0) {
221
- idx = stmts.indexOf(n) - 1;
222
+ if (node && ts.isSourceFile(node.parent) && statements.indexOf(node) >= 0) {
223
+ idx = statements.indexOf(node) - 1;
222
224
  }
223
225
  } else if (before !== undefined) {
224
226
  idx = before;
@@ -239,21 +241,21 @@ export class TransformerState implements State {
239
241
  /**
240
242
  * From literal
241
243
  */
242
- fromLiteral<T extends ts.Expression>(val: T): T;
243
- fromLiteral(val: undefined): ts.Identifier;
244
- fromLiteral(val: null): ts.NullLiteral;
245
- fromLiteral(val: object): ts.ObjectLiteralExpression;
246
- fromLiteral(val: unknown[]): ts.ArrayLiteralExpression;
247
- fromLiteral(val: string | boolean | number): ts.LiteralExpression;
248
- fromLiteral(val: unknown): ts.Node {
249
- return LiteralUtil.fromLiteral(this.factory, val!);
244
+ fromLiteral<T extends ts.Expression>(value: T): T;
245
+ fromLiteral(value: undefined): ts.Identifier;
246
+ fromLiteral(value: null): ts.NullLiteral;
247
+ fromLiteral(value: object): ts.ObjectLiteralExpression;
248
+ fromLiteral(value: unknown[]): ts.ArrayLiteralExpression;
249
+ fromLiteral(value: string | boolean | number): ts.LiteralExpression;
250
+ fromLiteral(value: unknown): ts.Node {
251
+ return LiteralUtil.fromLiteral(this.factory, value!);
250
252
  }
251
253
 
252
254
  /**
253
255
  * Extend
254
256
  */
255
- extendObjectLiteral(src: object | ts.Expression, ...rest: (object | ts.Expression)[]): ts.ObjectLiteralExpression {
256
- return LiteralUtil.extendObjectLiteral(this.factory, src, ...rest);
257
+ extendObjectLiteral(source: object | ts.Expression, ...rest: (object | ts.Expression)[]): ts.ObjectLiteralExpression {
258
+ return LiteralUtil.extendObjectLiteral(this.factory, source, ...rest);
257
259
  }
258
260
 
259
261
  /**
@@ -266,8 +268,8 @@ export class TransformerState implements State {
266
268
  /**
267
269
  * Create a static field for a class
268
270
  */
269
- createStaticField(name: string, val: ts.Expression): ts.PropertyDeclaration {
270
- return CoreUtil.createStaticField(this.factory, name, val);
271
+ createStaticField(name: string, value: ts.Expression): ts.PropertyDeclaration {
272
+ return CoreUtil.createStaticField(this.factory, name, value);
271
273
  }
272
274
 
273
275
  /**
@@ -282,17 +284,17 @@ export class TransformerState implements State {
282
284
  * Get filename identifier, regardless of module system
283
285
  */
284
286
  getModuleIdentifier(): ts.Expression {
285
- if (this.#modIdent === undefined) {
286
- this.#modIdent = this.factory.createUniqueName('mod');
287
+ if (this.#moduleIdentifier === undefined) {
288
+ this.#moduleIdentifier = this.factory.createUniqueName('mod');
287
289
  const entry = this.#resolver.getFileImport(this.source.fileName);
288
- const decl = this.factory.createVariableDeclaration(this.#modIdent, undefined, undefined,
290
+ const declaration = this.factory.createVariableDeclaration(this.#moduleIdentifier, undefined, undefined,
289
291
  this.fromLiteral([entry?.module, entry?.relativeFile ?? ''])
290
292
  );
291
293
  this.addStatements([
292
- this.factory.createVariableStatement([], this.factory.createVariableDeclarationList([decl]))
294
+ this.factory.createVariableStatement([], this.factory.createVariableDeclarationList([declaration]))
293
295
  ], -1);
294
296
  }
295
- return this.#modIdent;
297
+ return this.#moduleIdentifier;
296
298
  }
297
299
 
298
300
  /**
@@ -307,7 +309,7 @@ export class TransformerState implements State {
307
309
  mod = typeof mod === 'string' ? mod : mod[ModuleNameSymbol]!;
308
310
  const target = `${mod}:${name}`;
309
311
  const list = this.getDecoratorList(node);
310
- return list.find(x => x.targets?.includes(target) && (!module || x.name === name && x.module === module))?.dec;
312
+ return list.find(meta => meta.targets?.includes(target) && (!module || meta.name === name && meta.module === module))?.decorator;
311
313
  }
312
314
 
313
315
  /**
@@ -377,14 +379,14 @@ export class TransformerState implements State {
377
379
  findMethodByName(cls: ts.ClassLikeDeclaration | ts.Type, method: string): ts.MethodDeclaration | undefined {
378
380
  if ('getSourceFile' in cls) {
379
381
  return cls.members.find(
380
- (m): m is ts.MethodDeclaration => ts.isMethodDeclaration(m) && ts.isIdentifier(m.name) && m.name.escapedText === method
382
+ (value): value is ts.MethodDeclaration => ts.isMethodDeclaration(value) && ts.isIdentifier(value.name) && value.name.escapedText === method
381
383
  );
382
384
  } else {
383
- const props = this.#resolver.getPropertiesOfType(cls);
384
- for (const prop of props) {
385
- const decl = prop.declarations?.[0];
386
- if (decl && prop.escapedName === method && ts.isMethodDeclaration(decl)) {
387
- return decl;
385
+ const properties = this.#resolver.getPropertiesOfType(cls);
386
+ for (const property of properties) {
387
+ const declaration = property.declarations?.[0];
388
+ if (declaration && property.escapedName === method && ts.isMethodDeclaration(declaration)) {
389
+ return declaration;
388
390
  }
389
391
  }
390
392
  }
@@ -401,15 +403,13 @@ export class TransformerState implements State {
401
403
  /**
402
404
  * Produce a foreign target type
403
405
  */
404
- getForeignTarget(ret: ForeignType): ts.Expression {
405
- return this.factory.createClassExpression([], undefined, undefined, undefined, [
406
- this.factory.createPropertyDeclaration(
407
- [this.factory.createModifier(ts.SyntaxKind.StaticKeyword)],
408
- 'Ⲑid',
409
- undefined,
410
- undefined,
411
- this.fromLiteral(`${ret.source.split('node_modules/')[1]}+${ret.name}`)
412
- )
406
+ getForeignTarget(type: ForeignType): ts.Expression {
407
+ const file = this.importFile(FOREIGN_TYPE_REGISTRY_FILE);
408
+ return this.factory.createCallExpression(this.createAccess(
409
+ file.identifier,
410
+ this.factory.createIdentifier('foreignType'),
411
+ ), [], [
412
+ this.fromLiteral(`${type.source.split('node_modules/')[1]}+${type.name}`)
413
413
  ]);
414
414
  }
415
415
 
@@ -425,8 +425,8 @@ export class TransformerState implements State {
425
425
  return this.getForeignTarget(type);
426
426
  } else {
427
427
  const file = node.getSourceFile().fileName;
428
- const src = this.getFileImportName(file);
429
- throw new Error(`Unable to import non-external type: ${node.getText()} ${type.key}: ${src}`);
428
+ const source = this.getFileImportName(file);
429
+ throw new Error(`Unable to import non-external type: ${node.getText()} ${type.key}: ${source}`);
430
430
  }
431
431
  }
432
432
 
@@ -435,7 +435,7 @@ export class TransformerState implements State {
435
435
  */
436
436
  getApparentTypeOfField(value: ts.Type, field: string): AnyType | undefined {
437
437
  const checker = this.#resolver.getChecker();
438
- const props = checker.getApparentType(value).getApparentProperties().find(x => x.escapedName === field);
439
- return props ? this.resolveType(checker.getTypeOfSymbol(props)) : undefined;
438
+ const properties = checker.getApparentType(value).getApparentProperties().find(property => property.escapedName === field);
439
+ return properties ? this.resolveType(checker.getTypeOfSymbol(properties)) : undefined;
440
440
  }
441
441
  }
@@ -22,13 +22,13 @@ export interface DeclDocumentation {
22
22
  */
23
23
  export type Import = {
24
24
  path: string;
25
- ident: ts.Identifier;
26
- stmt?: ts.ImportDeclaration;
25
+ identifier: ts.Identifier;
26
+ statement?: ts.ImportDeclaration;
27
27
  };
28
28
 
29
29
  /** Template Literal Types */
30
30
  export type TemplateLiteralPart = string | NumberConstructor | StringConstructor | BooleanConstructor;
31
- export type TemplateLiteral = { op: 'and' | 'or', values: (TemplateLiteralPart | TemplateLiteral)[] };
31
+ export type TemplateLiteral = { operation: 'and' | 'or', values: (TemplateLiteralPart | TemplateLiteral)[] };
32
32
 
33
33
  export function transformCast<T>(input: unknown): T {
34
34
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -4,8 +4,8 @@ import ts from 'typescript';
4
4
  * Decorator metadata
5
5
  */
6
6
  export type DecoratorMeta = {
7
- dec: ts.Decorator;
8
- ident: ts.Identifier;
7
+ decorator: ts.Decorator;
8
+ identifier: ts.Identifier;
9
9
  module?: string;
10
10
  file?: string;
11
11
  targets?: string[];
@@ -18,7 +18,7 @@ export type State = {
18
18
  importName: string;
19
19
  added: Map<number, ts.Statement[]>;
20
20
  getDecoratorList(node: ts.Node): DecoratorMeta[];
21
- finalize(src: ts.SourceFile): ts.SourceFile;
21
+ finalize(source: ts.SourceFile): ts.SourceFile;
22
22
  };
23
23
 
24
24
  export type TransformPhase = 'before' | 'after';