@travetto/transformer 2.1.3 → 2.2.1

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
@@ -16,7 +16,7 @@ Because working with the [Typescript](https://typescriptlang.org) API can be del
16
16
 
17
17
  ## Custom Transformer
18
18
 
19
- Below is an example of a transformer that uppercases all `class`, `method` and `param` declarations. This will break any code that depends upon it as we are redefining all the identifiers at compile time.
19
+ Below is an example of a transformer that upper cases all `class`, `method` and `param` declarations. This will break any code that depends upon it as we are redefining all the identifiers at compile time.
20
20
 
21
21
  **Code: Sample Transformer - Upper case all declarations**
22
22
  ```typescript
@@ -29,7 +29,7 @@ export class MakeUpper {
29
29
  static [TransformerId] = '@trv:transformer-test';
30
30
 
31
31
  @OnProperty()
32
- static handleProperty(state: TransformerState, node: ts.PropertyDeclaration) {
32
+ static handleProperty(state: TransformerState, node: ts.PropertyDeclaration): ts.PropertyDeclaration {
33
33
  if (!state.source.fileName.includes('doc/src')) {
34
34
  return node;
35
35
  }
@@ -45,7 +45,7 @@ export class MakeUpper {
45
45
  }
46
46
 
47
47
  @OnClass()
48
- static handleClass(state: TransformerState, node: ts.ClassDeclaration) {
48
+ static handleClass(state: TransformerState, node: ts.ClassDeclaration): ts.ClassDeclaration {
49
49
  if (!state.source.fileName.includes('doc/src')) {
50
50
  return node;
51
51
  }
@@ -61,7 +61,7 @@ export class MakeUpper {
61
61
  }
62
62
 
63
63
  @OnMethod()
64
- static handleMethod(state: TransformerState, node: ts.MethodDeclaration) {
64
+ static handleMethod(state: TransformerState, node: ts.MethodDeclaration): ts.MethodDeclaration {
65
65
  if (!state.source.fileName.includes('doc/src')) {
66
66
  return node;
67
67
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@travetto/transformer",
3
3
  "displayName": "Transformation",
4
- "version": "2.1.3",
4
+ "version": "2.2.1",
5
5
  "description": "Functionality for AST transformations, with transformer registration, and general utils",
6
6
  "keywords": [
7
7
  "typescript",
@@ -25,7 +25,7 @@
25
25
  "directory": "module/transformer"
26
26
  },
27
27
  "dependencies": {
28
- "@travetto/base": "^2.1.3"
28
+ "@travetto/base": "^2.2.1"
29
29
  },
30
30
  "publishConfig": {
31
31
  "access": "public"
package/src/importer.ts CHANGED
@@ -26,7 +26,7 @@ export class ImportManager {
26
26
  /**
27
27
  * Produces a unique ID for a given file, importing if needed
28
28
  */
29
- getId(file: string) {
29
+ getId(file: string): string {
30
30
  if (!this.#ids.has(file)) {
31
31
  const key = basename(file).replace(/[.][^.]*$/, '').replace(/[^A-Za-z0-9]+/g, '_');
32
32
  this.#ids.set(file, `ᚕ_${key}_${this.#idx[key] = (this.#idx[key] || 0) + 1}`);
@@ -37,7 +37,7 @@ export class ImportManager {
37
37
  /**
38
38
  * Import a file if needed, and record it's identifier
39
39
  */
40
- importFile(file: string, base?: string) {
40
+ importFile(file: string, base?: string): Import {
41
41
  file = ModuleUtil.normalizePath(file);
42
42
 
43
43
  // Allow for node classes to be imported directly
@@ -65,9 +65,9 @@ export class ImportManager {
65
65
  }
66
66
 
67
67
  const ident = this.factory.createIdentifier(id);
68
- const imprt = { path: file, ident };
69
- this.#imports.set(ident.escapedText.toString(), imprt);
70
- this.#newImports.set(file, imprt);
68
+ const newImport = { path: file, ident };
69
+ this.#imports.set(ident.escapedText.toString(), newImport);
70
+ this.#newImports.set(file, newImport);
71
71
  }
72
72
  return this.#newImports.get(file)!;
73
73
  }
@@ -75,7 +75,7 @@ export class ImportManager {
75
75
  /**
76
76
  * Import given an external type
77
77
  */
78
- importFromResolved(...types: AnyType[]) {
78
+ importFromResolved(...types: AnyType[]): void {
79
79
  for (const type of types) {
80
80
  if (type.key === 'external' && type.source && type.source !== this.source.fileName) {
81
81
  this.importFile(type.source, this.source.fileName);
@@ -93,19 +93,19 @@ export class ImportManager {
93
93
  /**
94
94
  * Add imports to a source file
95
95
  */
96
- finalizeNewImports(file: ts.SourceFile) {
96
+ finalizeNewImports(file: ts.SourceFile): ts.SourceFile | undefined {
97
97
  if (!this.#newImports.size) {
98
98
  return;
99
99
  }
100
100
 
101
101
  try {
102
102
  const importStmts = [...this.#newImports.values()].map(({ path, ident }) => {
103
- const imptStmt = this.factory.createImportDeclaration(
103
+ const importStmt = this.factory.createImportDeclaration(
104
104
  undefined, undefined,
105
105
  this.factory.createImportClause(false, undefined, this.factory.createNamespaceImport(ident)),
106
106
  this.factory.createStringLiteral(path)
107
107
  );
108
- return imptStmt;
108
+ return importStmt;
109
109
  });
110
110
 
111
111
  return CoreUtil.updateSource(this.factory, file, [
@@ -113,6 +113,9 @@ export class ImportManager {
113
113
  ...file.statements.filter((x: ts.Statement & { remove?: boolean }) => !x.remove) // Exclude culled imports
114
114
  ]);
115
115
  } catch (err) { // Missing import
116
+ if (!(err instanceof Error)) {
117
+ throw err;
118
+ }
116
119
  const out = new Error(`${err.message} in ${file.fileName.replace(PathUtil.cwd, '.')}`);
117
120
  out.stack = err.stack;
118
121
  throw out;
@@ -122,14 +125,14 @@ export class ImportManager {
122
125
  /**
123
126
  * Reset the imports into the source file
124
127
  */
125
- finalize(ret: ts.SourceFile) {
128
+ finalize(ret: ts.SourceFile): ts.SourceFile {
126
129
  return this.finalizeNewImports(ret) ?? ret;
127
130
  }
128
131
 
129
132
  /**
130
133
  * Get the identifier and import if needed
131
134
  */
132
- getOrImport(factory: ts.NodeFactory, type: ExternalType) {
135
+ getOrImport(factory: ts.NodeFactory, type: ExternalType): ts.Identifier | ts.PropertyAccessExpression {
133
136
  if (type.source === this.source.fileName) {
134
137
  return factory.createIdentifier(type.name!);
135
138
  } else {
package/src/register.ts CHANGED
@@ -9,12 +9,12 @@ type TransformerWithHandlers = Transformer & { [HandlersProp]?: NodeTransformer[
9
9
  * Get all transformers
10
10
  * @param obj Object to search for transformers
11
11
  */
12
- export function getAllTransformers(obj: Record<string, { [HandlersProp]?: NodeTransformer[] }>) {
12
+ export function getAllTransformers(obj: Record<string, { [HandlersProp]?: NodeTransformer[] }>): NodeTransformer[] {
13
13
  return Object.values(obj).flatMap(x => x[HandlersProp] ?? []);
14
14
  }
15
15
 
16
16
  // Store handlers in class
17
- function storeHandler(cls: TransformerWithHandlers, fn: Function, phase: TransformPhase, type: TransformerType, target?: string[]) {
17
+ function storeHandler(cls: TransformerWithHandlers, fn: Function, phase: TransformPhase, type: TransformerType, target?: string[]): void {
18
18
  if (target) {
19
19
  const ns = cls[TransformerId].split('/')[0]; // Everything before the '/'
20
20
  target = target.map(x => x.startsWith('@') ? x : `${ns}/${x}`);
@@ -29,7 +29,7 @@ function storeHandler(cls: TransformerWithHandlers, fn: Function, phase: Transfo
29
29
  export function OnCall(...target: string[]) {
30
30
  return <S extends State = State, R extends ts.Node = ts.Node>(
31
31
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.CallExpression) => R>
32
- ) => storeHandler(inst, d.value!, 'before', 'call', target);
32
+ ): void => storeHandler(inst, d.value!, 'before', 'call', target);
33
33
  }
34
34
 
35
35
  /**
@@ -38,7 +38,7 @@ export function OnCall(...target: string[]) {
38
38
  export function OnFunction(...target: string[]) {
39
39
  return <S extends State = State, R extends ts.Node = ts.Node>(
40
40
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.FunctionDeclaration | ts.FunctionExpression) => R>
41
- ) => storeHandler(inst, d.value!, 'before', 'function', target);
41
+ ): void => storeHandler(inst, d.value!, 'before', 'function', target);
42
42
  }
43
43
 
44
44
  /**
@@ -47,7 +47,7 @@ export function OnFunction(...target: string[]) {
47
47
  export function OnParameter(...target: string[]) {
48
48
  return <S extends State = State, R extends ts.Node = ts.Node>(
49
49
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.ParameterDeclaration, dm?: DecoratorMeta) => R>
50
- ) => storeHandler(inst, d.value!, 'before', 'parameter', target);
50
+ ): void => storeHandler(inst, d.value!, 'before', 'parameter', target);
51
51
  }
52
52
 
53
53
  /**
@@ -56,7 +56,7 @@ export function OnParameter(...target: string[]) {
56
56
  export function OnProperty(...target: string[]) {
57
57
  return <S extends State = State, R extends ts.Node = ts.Node>(
58
58
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.PropertyDeclaration, dm?: DecoratorMeta) => R>
59
- ) => storeHandler(inst, d.value!, 'before', 'property', target);
59
+ ): void => storeHandler(inst, d.value!, 'before', 'property', target);
60
60
  }
61
61
 
62
62
  /**
@@ -65,7 +65,7 @@ export function OnProperty(...target: string[]) {
65
65
  export function OnGetter(...target: string[]) {
66
66
  return <S extends State = State, R extends ts.Node = ts.Node>(
67
67
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.GetAccessorDeclaration, dm?: DecoratorMeta) => R>
68
- ) => storeHandler(inst, d.value!, 'before', 'getter', target);
68
+ ): void => storeHandler(inst, d.value!, 'before', 'getter', target);
69
69
  }
70
70
 
71
71
  /**
@@ -74,7 +74,7 @@ export function OnGetter(...target: string[]) {
74
74
  export function OnSetter(...target: string[]) {
75
75
  return <S extends State = State, R extends ts.Node = ts.Node>(
76
76
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.SetAccessorDeclaration, dm?: DecoratorMeta) => R>
77
- ) => storeHandler(inst, d.value!, 'before', 'setter', target);
77
+ ): void => storeHandler(inst, d.value!, 'before', 'setter', target);
78
78
  }
79
79
 
80
80
  /**
@@ -83,7 +83,7 @@ export function OnSetter(...target: string[]) {
83
83
  export function OnMethod(...target: string[]) {
84
84
  return <S extends State = State, R extends ts.Node = ts.Node>(
85
85
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.MethodDeclaration, dm?: DecoratorMeta) => R>
86
- ) => storeHandler(inst, d.value!, 'before', 'method', target);
86
+ ): void => storeHandler(inst, d.value!, 'before', 'method', target);
87
87
  }
88
88
 
89
89
  /**
@@ -92,7 +92,7 @@ export function OnMethod(...target: string[]) {
92
92
  export function OnStaticMethod(...target: string[]) {
93
93
  return <S extends State = State, R extends ts.Node = ts.Node>(
94
94
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.MethodDeclaration, dm?: DecoratorMeta) => R>
95
- ) => storeHandler(inst, d.value!, 'before', 'static-method', target);
95
+ ): void => storeHandler(inst, d.value!, 'before', 'static-method', target);
96
96
  }
97
97
 
98
98
  /**
@@ -101,7 +101,7 @@ export function OnStaticMethod(...target: string[]) {
101
101
  export function OnClass(...target: string[]) {
102
102
  return <S extends State = State, R extends ts.Node = ts.Node>(
103
103
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.ClassDeclaration, dm?: DecoratorMeta) => R>
104
- ) => storeHandler(inst, d.value!, 'before', 'class', target);
104
+ ): void => storeHandler(inst, d.value!, 'before', 'class', target);
105
105
  }
106
106
 
107
107
  /**
@@ -110,7 +110,7 @@ export function OnClass(...target: string[]) {
110
110
  export function AfterCall(...target: string[]) {
111
111
  return <S extends State = State, R extends ts.Node = ts.Node>(
112
112
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.CallExpression, dm?: DecoratorMeta) => R>
113
- ) => storeHandler(inst, d.value!, 'after', 'call', target);
113
+ ): void => storeHandler(inst, d.value!, 'after', 'call', target);
114
114
  }
115
115
 
116
116
  /**
@@ -119,7 +119,7 @@ export function AfterCall(...target: string[]) {
119
119
  export function AfterFunction(...target: string[]) {
120
120
  return <S extends State = State, R extends ts.Node = ts.Node>(
121
121
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.FunctionDeclaration | ts.FunctionExpression) => R>
122
- ) => storeHandler(inst, d.value!, 'after', 'function', target);
122
+ ): void => storeHandler(inst, d.value!, 'after', 'function', target);
123
123
  }
124
124
 
125
125
  /**
@@ -128,7 +128,7 @@ export function AfterFunction(...target: string[]) {
128
128
  export function AfterParameter(...target: string[]) {
129
129
  return <S extends State = State, R extends ts.Node = ts.Node>(
130
130
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.ParameterDeclaration, dm?: DecoratorMeta) => R>
131
- ) => storeHandler(inst, d.value!, 'after', 'parameter', target);
131
+ ): void => storeHandler(inst, d.value!, 'after', 'parameter', target);
132
132
  }
133
133
 
134
134
  /**
@@ -137,7 +137,7 @@ export function AfterParameter(...target: string[]) {
137
137
  export function AfterProperty(...target: string[]) {
138
138
  return <S extends State = State, R extends ts.Node = ts.Node>(
139
139
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.PropertyDeclaration, dm?: DecoratorMeta) => R>
140
- ) => storeHandler(inst, d.value!, 'after', 'property', target);
140
+ ): void => storeHandler(inst, d.value!, 'after', 'property', target);
141
141
  }
142
142
 
143
143
  /**
@@ -146,7 +146,7 @@ export function AfterProperty(...target: string[]) {
146
146
  export function AfterGetter(...target: string[]) {
147
147
  return <S extends State = State, R extends ts.Node = ts.Node>(
148
148
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.GetAccessorDeclaration, dm?: DecoratorMeta) => R>
149
- ) => storeHandler(inst, d.value!, 'after', 'getter', target);
149
+ ): void => storeHandler(inst, d.value!, 'after', 'getter', target);
150
150
  }
151
151
 
152
152
  /**
@@ -155,7 +155,7 @@ export function AfterGetter(...target: string[]) {
155
155
  export function AfterSetter(...target: string[]) {
156
156
  return <S extends State = State, R extends ts.Node = ts.Node>(
157
157
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.SetAccessorDeclaration, dm?: DecoratorMeta) => R>
158
- ) => storeHandler(inst, d.value!, 'after', 'setter', target);
158
+ ): void => storeHandler(inst, d.value!, 'after', 'setter', target);
159
159
  }
160
160
 
161
161
  /**
@@ -164,7 +164,7 @@ export function AfterSetter(...target: string[]) {
164
164
  export function AfterMethod(...target: string[]) {
165
165
  return <S extends State = State, R extends ts.Node = ts.Node>(
166
166
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.MethodDeclaration, dm?: DecoratorMeta) => R>
167
- ) => storeHandler(inst, d.value!, 'after', 'method', target);
167
+ ): void => storeHandler(inst, d.value!, 'after', 'method', target);
168
168
  }
169
169
 
170
170
  /**
@@ -173,7 +173,7 @@ export function AfterMethod(...target: string[]) {
173
173
  export function AfterStaticMethod(...target: string[]) {
174
174
  return <S extends State = State, R extends ts.Node = ts.Node>(
175
175
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.MethodDeclaration, dm?: DecoratorMeta) => R>
176
- ) => storeHandler(inst, d.value!, 'after', 'static-method', target);
176
+ ): void => storeHandler(inst, d.value!, 'after', 'static-method', target);
177
177
  }
178
178
 
179
179
  /**
@@ -182,5 +182,5 @@ export function AfterStaticMethod(...target: string[]) {
182
182
  export function AfterClass(...target: string[]) {
183
183
  return <S extends State = State, R extends ts.Node = ts.Node>(
184
184
  inst: Transformer, __: unknown, d: TypedPropertyDescriptor<(state: S, node: ts.ClassDeclaration, dm?: DecoratorMeta) => R>
185
- ) => storeHandler(inst, d.value!, 'after', 'class', target);
185
+ ): void => storeHandler(inst, d.value!, 'after', 'class', target);
186
186
  }
@@ -117,6 +117,7 @@ export const TypeBuilder: {
117
117
 
118
118
  if (name in GLOBAL_SIMPLE) {
119
119
  const cons = GLOBAL_SIMPLE[name];
120
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
120
121
  const ret = LiteralUtil.isLiteralType(type) ? Util.coerceType(type.value, cons as typeof String, false) :
121
122
  undefined;
122
123
 
@@ -148,8 +149,7 @@ export const TypeBuilder: {
148
149
  }
149
150
  },
150
151
  union: {
151
- build: (checker, type) => {
152
- const uType = type as ts.UnionType;
152
+ build: (checker, uType: ts.UnionType) => {
153
153
  let undefinable = false;
154
154
  let nullable = false;
155
155
  const remainder = uType.types.filter(ut => {
@@ -159,7 +159,7 @@ export const TypeBuilder: {
159
159
  nullable = nullable || n;
160
160
  return !(u || n);
161
161
  });
162
- const name = CoreUtil.getSymbol(type)?.getName();
162
+ const name = CoreUtil.getSymbol(uType)?.getName();
163
163
  return { key: 'union', name, undefinable, nullable, tsSubTypes: remainder, subTypes: [] };
164
164
  },
165
165
  finalize: (type: UnionType) => {
@@ -208,9 +208,9 @@ export const TypeBuilder: {
208
208
  source = '.';
209
209
  }
210
210
 
211
- const sourceFile = DeclarationUtil.getDeclarations(type)
211
+ const sourceFile: string = DeclarationUtil.getDeclarations(type)
212
212
  ?.find(x => ts.getAllJSDocTags(x, (t): t is ts.JSDocTag => t.tagName.getText() === 'concrete').length)
213
- ?.getSourceFile().fileName as string;
213
+ ?.getSourceFile().fileName ?? '';
214
214
 
215
215
  if (source === '.') {
216
216
  source = sourceFile;
@@ -19,7 +19,7 @@ export class TypeResolver implements Checker {
19
19
  * Get type checker
20
20
  * @private
21
21
  */
22
- getChecker() {
22
+ getChecker(): ts.TypeChecker {
23
23
  return this.#tsChecker;
24
24
  }
25
25
 
@@ -27,21 +27,22 @@ export class TypeResolver implements Checker {
27
27
  * Get type from element
28
28
  * @param el
29
29
  */
30
- getType(el: ts.Type | ts.Node) {
31
- return 'getSourceFile' in el ? this.#tsChecker.getTypeAtLocation(el as ts.Node) : el;
30
+ getType(el: ts.Type | ts.Node): ts.Type {
31
+ return 'getSourceFile' in el ? this.#tsChecker.getTypeAtLocation(el) : el;
32
32
  }
33
33
 
34
34
  /**
35
35
  * Fetch all type arguments for a give type
36
36
  */
37
37
  getAllTypeArguments(ref: ts.Type): ts.Type[] {
38
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38
39
  return this.#tsChecker.getTypeArguments(ref as ts.TypeReference) as ts.Type[];
39
40
  }
40
41
 
41
42
  /**
42
43
  * Resolve the return type for a method
43
44
  */
44
- getReturnType(node: ts.MethodDeclaration) {
45
+ getReturnType(node: ts.MethodDeclaration): ts.Type {
45
46
  const type = this.getType(node);
46
47
  const [sig] = type.getCallSignatures();
47
48
  return this.#tsChecker.getReturnTypeOfSignature(sig);
@@ -50,14 +51,14 @@ export class TypeResolver implements Checker {
50
51
  /**
51
52
  * Get type as a string representation
52
53
  */
53
- getTypeAsString(type: ts.Type) {
54
+ getTypeAsString(type: ts.Type): string | undefined {
54
55
  return this.#tsChecker.typeToString(this.#tsChecker.getApparentType(type)) || undefined;
55
56
  }
56
57
 
57
58
  /**
58
59
  * Get list of properties
59
60
  */
60
- getPropertiesOfType(type: ts.Type) {
61
+ getPropertiesOfType(type: ts.Type): ts.Symbol[] {
61
62
  return this.#tsChecker.getPropertiesOfType(type);
62
63
  }
63
64
 
@@ -102,6 +103,7 @@ export class TypeResolver implements Checker {
102
103
  delete result.tsSubTypes;
103
104
  }
104
105
  if (finalize) {
106
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
105
107
  result = finalize(result as never);
106
108
  }
107
109
  }
@@ -112,6 +114,9 @@ export class TypeResolver implements Checker {
112
114
  try {
113
115
  return resolve(this.getType(node));
114
116
  } catch (err) {
117
+ if (!(err instanceof Error)) {
118
+ throw err;
119
+ }
115
120
  console.error('Unable to resolve type', err.stack);
116
121
  return { key: 'literal', ctor: Object, name: 'object' };
117
122
  }
@@ -141,7 +141,12 @@ export interface PointerType extends Type<'pointer'> {
141
141
  target: Exclude<AnyType, PointerType>;
142
142
  }
143
143
 
144
- export type AnyType = TupleType | ShapeType | UnionType | LiteralType | ExternalType | PointerType;
144
+ /**
145
+ * Unknown type, should default to object
146
+ */
147
+ export interface UnknownType extends Type<'unknown'> { }
148
+
149
+ export type AnyType = TupleType | ShapeType | UnionType | LiteralType | ExternalType | PointerType | UnknownType;
145
150
 
146
151
  /**
147
152
  * Simple interface for checked methods
package/src/state.ts CHANGED
@@ -12,12 +12,15 @@ import { DocUtil } from './util/doc';
12
12
  import { DecoratorUtil } from './util/decorator';
13
13
  import { DeclarationUtil } from './util/declaration';
14
14
  import { CoreUtil, LiteralUtil } from './util';
15
+ import { Import } from './types/shared';
15
16
 
16
17
  function hasOriginal(n: unknown): n is { original: ts.Node } {
18
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
17
19
  return !!n && !(n as { parent?: unknown }).parent && !!(n as { original: unknown }).original;
18
20
  }
19
21
 
20
22
  function hasEscapedName(n: unknown): n is { name: { escapedText: string } } {
23
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
21
24
  return !!n && !!(n as { name?: { escapedText?: string } }).name?.escapedText;
22
25
  }
23
26
 
@@ -45,28 +48,28 @@ export class TransformerState implements State {
45
48
  * Allow access to resolver
46
49
  * @private
47
50
  */
48
- getResolver() {
51
+ getResolver(): TypeResolver {
49
52
  return this.#resolver;
50
53
  }
51
54
 
52
55
  /**
53
56
  * Get or import the node or external type
54
57
  */
55
- getOrImport(type: ExternalType) {
58
+ getOrImport(type: ExternalType): ts.Identifier | ts.PropertyAccessExpression {
56
59
  return this.#imports.getOrImport(this.factory, type);
57
60
  }
58
61
 
59
62
  /**
60
63
  * Import a given file
61
64
  */
62
- importFile(file: string) {
65
+ importFile(file: string): Import {
63
66
  return this.#imports.importFile(file);
64
67
  }
65
68
 
66
69
  /**
67
70
  * Resolve an `AnyType` from a `ts.Type` or `ts.Node`
68
71
  */
69
- resolveType(node: ts.Type | ts.Node) {
72
+ resolveType(node: ts.Type | ts.Node): AnyType {
70
73
  const resolved = this.#resolver.resolveType(node);
71
74
  this.#imports.importFromResolved(resolved);
72
75
  return resolved;
@@ -75,7 +78,7 @@ export class TransformerState implements State {
75
78
  /**
76
79
  * Resolve external type
77
80
  */
78
- resolveExternalType(node: ts.Node) {
81
+ resolveExternalType(node: ts.Node): ExternalType {
79
82
  const resolved = this.resolveType(node);
80
83
  if (resolved.key !== 'external') {
81
84
  throw new Error(`Unable to import non-external type: ${node.getText()} ${resolved.key}: ${node.getSourceFile().fileName}`);
@@ -86,7 +89,7 @@ export class TransformerState implements State {
86
89
  /**
87
90
  * Convert a type to it's identifier, will return undefined if none match
88
91
  */
89
- typeToIdentifier(node: ts.Type | AnyType) {
92
+ typeToIdentifier(node: ts.Type | AnyType): ts.Identifier | ts.PropertyAccessExpression | undefined {
90
93
  const type = 'flags' in node ? this.resolveType(node) : node;
91
94
  switch (type.key) {
92
95
  case 'literal': return this.factory.createIdentifier(type.ctor!.name);
@@ -98,7 +101,7 @@ export class TransformerState implements State {
98
101
  /**
99
102
  * Resolve the return type
100
103
  */
101
- resolveReturnType(node: ts.MethodDeclaration) {
104
+ resolveReturnType(node: ts.MethodDeclaration): AnyType {
102
105
  const typeNode = ts.getJSDocReturnType(node);
103
106
  if (typeNode) {
104
107
  const resolved = this.#resolver.getChecker().getTypeFromTypeNode(typeNode);
@@ -111,14 +114,14 @@ export class TransformerState implements State {
111
114
  /**
112
115
  * Read all JSDoc tags
113
116
  */
114
- readDocTag(node: ts.Declaration, name: string) {
117
+ readDocTag(node: ts.Declaration, name: string): string[] {
115
118
  return DocUtil.readDocTag(this.#resolver.getType(node), name);
116
119
  }
117
120
 
118
121
  /**
119
122
  * Import a decorator, generally to handle erasure
120
123
  */
121
- importDecorator(pth: string, name: string) {
124
+ importDecorator(pth: string, name: string): ts.PropertyAccessExpression | undefined {
122
125
  if (!this.#decorators.has(`${pth}:${name}`)) {
123
126
  const ref = this.#imports.importFile(pth);
124
127
  const ident = this.factory.createIdentifier(name);
@@ -130,7 +133,7 @@ export class TransformerState implements State {
130
133
  /**
131
134
  * Create a decorator to add functionality to a declaration
132
135
  */
133
- createDecorator(pth: string, name: string, ...contents: (ts.Expression | undefined)[]) {
136
+ createDecorator(pth: string, name: string, ...contents: (ts.Expression | undefined)[]): ts.Decorator {
134
137
  this.importDecorator(pth, name);
135
138
  return CoreUtil.createDecorator(this.factory, this.#decorators.get(name)!, ...contents);
136
139
  }
@@ -151,6 +154,7 @@ export class TransformerState implements State {
151
154
  module: decl ? ModuleUtil.normalizePath(decl.getSourceFile().fileName) : undefined, // All #decorators will be absolute
152
155
  targets: DocUtil.readAugments(this.#resolver.getType(ident)),
153
156
  name: ident ?
157
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
154
158
  ident.escapedText! as string :
155
159
  undefined
156
160
  };
@@ -160,7 +164,7 @@ export class TransformerState implements State {
160
164
  * Get list of all #decorators for a node
161
165
  */
162
166
  getDecoratorList(node: ts.Node): DecoratorMeta[] {
163
- return ((node.decorators ?? []) as ts.Decorator[])
167
+ return (node.decorators ?? [])
164
168
  .map(dec => this.getDecoratorMeta(dec))
165
169
  .filter(x => !!x.ident);
166
170
  }
@@ -177,7 +181,7 @@ export class TransformerState implements State {
177
181
  * @param stmt
178
182
  * @param before
179
183
  */
180
- addStatement(stmt: ts.Statement, before?: ts.Node) {
184
+ addStatement(stmt: ts.Statement, before?: ts.Node): void {
181
185
  const stmts = this.source.statements.slice(0);
182
186
  let idx = stmts.length;
183
187
  let n = before;
@@ -187,8 +191,10 @@ export class TransformerState implements State {
187
191
  while (n && !ts.isSourceFile(n.parent)) {
188
192
  n = n.parent;
189
193
  }
190
- if (n && ts.isSourceFile(n.parent) && stmts.indexOf(n as ts.Statement) >= 0) {
191
- idx = stmts.indexOf(n as ts.Statement) - 1;
194
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
195
+ const nStmt: ts.Statement = n as ts.Statement;
196
+ if (n && ts.isSourceFile(n.parent) && stmts.indexOf(nStmt) >= 0) {
197
+ idx = stmts.indexOf(nStmt) - 1;
192
198
  }
193
199
  if (!this.added.has(idx)) {
194
200
  this.added.set(idx, []);
@@ -199,7 +205,7 @@ export class TransformerState implements State {
199
205
  /**
200
206
  * Finalize the source file for emission
201
207
  */
202
- finalize(ret: ts.SourceFile) {
208
+ finalize(ret: ts.SourceFile): ts.SourceFile {
203
209
  ret = this.#imports.finalize(ret);
204
210
  return ret;
205
211
  }
@@ -207,9 +213,9 @@ export class TransformerState implements State {
207
213
  /**
208
214
  * Get Filename as ᚕsrc
209
215
  */
210
- getFilenameAsSrc() {
216
+ getFilenameAsSrc(): ts.CallExpression {
211
217
  const ident = this.factory.createIdentifier('ᚕsrc');
212
- ident.getSourceFile = () => this.source;
218
+ ident.getSourceFile = (): ts.SourceFile => this.source;
213
219
  return this.factory.createCallExpression(ident, [], [this.createIdentifier('__filename')]);
214
220
  }
215
221
 
@@ -223,20 +229,21 @@ export class TransformerState implements State {
223
229
  fromLiteral(val: unknown[]): ts.ArrayLiteralExpression;
224
230
  fromLiteral(val: string | boolean | number): ts.LiteralExpression;
225
231
  fromLiteral(val: unknown): ts.Node {
232
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
226
233
  return LiteralUtil.fromLiteral(this.factory, val as object);
227
234
  }
228
235
 
229
236
  /**
230
237
  * Extend
231
238
  */
232
- extendObjectLiteral(src: object | ts.Expression, ...rest: (object | ts.Expression)[]) {
239
+ extendObjectLiteral(src: object | ts.Expression, ...rest: (object | ts.Expression)[]): ts.ObjectLiteralExpression {
233
240
  return LiteralUtil.extendObjectLiteral(this.factory, src, ...rest);
234
241
  }
235
242
 
236
243
  /**
237
244
  * Create property access
238
245
  */
239
- createAccess(first: string | ts.Expression, second: string | ts.Identifier, ...items: (string | ts.Identifier)[]) {
246
+ createAccess(first: string | ts.Expression, second: string | ts.Identifier, ...items: (string | ts.Identifier)[]): ts.PropertyAccessExpression {
240
247
  return CoreUtil.createAccess(this.factory, first, second, ...items);
241
248
  }
242
249
 
@@ -248,10 +255,10 @@ export class TransformerState implements State {
248
255
  }
249
256
 
250
257
  /**
251
- * Ceate identifier from node or text
258
+ * Create identifier from node or text
252
259
  * @param name
253
260
  */
254
- createIdentifier(name: string | { getText(): string }) {
261
+ createIdentifier(name: string | { getText(): string }): ts.Identifier {
255
262
  return this.factory.createIdentifier(typeof name === 'string' ? name : name.getText());
256
263
  }
257
264
 
@@ -262,7 +269,7 @@ export class TransformerState implements State {
262
269
  * @param name
263
270
  * @param module
264
271
  */
265
- findDecorator(cls: Transformer, node: ts.Node, name: string, module?: string) {
272
+ findDecorator(cls: Transformer, node: ts.Node, name: string, module?: string): ts.Decorator | undefined {
266
273
  const target = `${cls[TransformerId]}/${name}`;
267
274
  return this.getDecoratorList(node)
268
275
  .find(x => x.targets?.includes(target) && (!module || x.name === name && x.module === module))?.dec;
@@ -273,7 +280,7 @@ export class TransformerState implements State {
273
280
  * @param node
274
281
  * @param type
275
282
  */
276
- generateUniqueIdentifier(node: ts.Node, type: AnyType) {
283
+ generateUniqueIdentifier(node: ts.Node, type: AnyType): string {
277
284
  let unique: string;
278
285
  try {
279
286
  // Tie to source location if possible
@@ -295,16 +302,16 @@ export class TransformerState implements State {
295
302
  }
296
303
 
297
304
  /**
298
- * Register synthetic idetnifier
305
+ * Register synthetic identifier
299
306
  */
300
- createSyntheticIdentifier(id: string) {
307
+ createSyntheticIdentifier(id: string): [identifier: ts.Identifier, exists: boolean] {
301
308
  id = `${id}${TransformerState.SYNTHETIC_EXT}`;
302
309
  let exists = true;
303
310
  if (!this.#syntheticIdentifiers.has(id)) {
304
311
  this.#syntheticIdentifiers.set(id, this.factory.createIdentifier(id));
305
312
  exists = false;
306
313
  }
307
- return [this.#syntheticIdentifiers.get(id), exists] as [id: ts.Identifier, exists: boolean];
314
+ return [this.#syntheticIdentifiers.get(id)!, exists];
308
315
  }
309
316
 
310
317
  /**
@@ -315,8 +322,8 @@ export class TransformerState implements State {
315
322
  findMethodByName(cls: ts.ClassLikeDeclaration | ts.Type, method: string): ts.MethodDeclaration | undefined {
316
323
  if ('getSourceFile' in cls) {
317
324
  return cls.members.find(
318
- m => ts.isMethodDeclaration(m) && ts.isIdentifier(m.name) && m.name.escapedText === method
319
- ) as ts.MethodDeclaration;
325
+ (m): m is ts.MethodDeclaration => ts.isMethodDeclaration(m) && ts.isIdentifier(m.name) && m.name.escapedText === method
326
+ );
320
327
  } else {
321
328
  const props = this.getResolver().getPropertiesOfType(cls);
322
329
  for (const prop of props) {
package/src/util/core.ts CHANGED
@@ -8,6 +8,7 @@ export class CoreUtil {
8
8
  * See if inbound node has an original property
9
9
  */
10
10
  static hasOriginal(o: ts.Node): o is (ts.Node & { original: ts.Node }) {
11
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
11
12
  return 'original' in o && !!(o as { original?: ts.Node }).original;
12
13
  }
13
14
 
@@ -15,6 +16,7 @@ export class CoreUtil {
15
16
  * See if type has target
16
17
  */
17
18
  static hasTarget(o: ts.Type): o is (ts.Type & { target: ts.Type }) {
19
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
18
20
  return 'target' in o && !!(o as { target?: ts.Type }).target;
19
21
  }
20
22
 
@@ -22,7 +24,7 @@ export class CoreUtil {
22
24
  * Get first line of method body
23
25
  * @param m
24
26
  */
25
- static getRangeOf<T extends ts.Node>(source: ts.SourceFile, o: T | undefined) {
27
+ static getRangeOf<T extends ts.Node>(source: ts.SourceFile, o: T | undefined): { start: number, end: number } | undefined {
26
28
  if (o) {
27
29
  const start = ts.getLineAndCharacterOfPosition(source, o.getStart(source));
28
30
  const end = ts.getLineAndCharacterOfPosition(source, o.getEnd());
@@ -38,6 +40,7 @@ export class CoreUtil {
38
40
  */
39
41
  static getArgument<T extends ts.Expression = ts.Expression>(node: ts.CallExpression | undefined, position = 0): T | undefined {
40
42
  if (node && node!.arguments && node!.arguments.length >= position + 1) {
43
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
41
44
  return node.arguments[position] as T;
42
45
  }
43
46
  return;
@@ -57,11 +60,13 @@ export class CoreUtil {
57
60
  /**
58
61
  * Get `ts.Symbol` from a `ts.Type`
59
62
  */
60
- static getSymbol(type: ts.Type | ts.Symbol) {
63
+ static getSymbol(type: ts.Type | ts.Symbol | ts.TypeReference): ts.Symbol {
61
64
  if ('valueDeclaration' in type || 'escapedName' in type) {
62
65
  return type;
66
+ } else if ('aliasSymbol' in type && type.aliasSymbol) {
67
+ return type.aliasSymbol;
63
68
  } else {
64
- return (type as ts.TypeReference).aliasSymbol ?? (type as ts.Type).symbol;
69
+ return type.symbol;
65
70
  }
66
71
  }
67
72
 
@@ -70,7 +75,7 @@ export class CoreUtil {
70
75
  * @param src
71
76
  * @param statements
72
77
  */
73
- static updateSource(factory: ts.NodeFactory, src: ts.SourceFile, statements: ts.NodeArray<ts.Statement> | ts.Statement[]) {
78
+ static updateSource(factory: ts.NodeFactory, src: ts.SourceFile, statements: ts.NodeArray<ts.Statement> | ts.Statement[]): ts.SourceFile {
74
79
  return factory.updateSourceFile(
75
80
  src, statements, src.isDeclarationFile, src.referencedFiles, src.typeReferenceDirectives, src.hasNoDefaultLib
76
81
  );
@@ -79,7 +84,12 @@ export class CoreUtil {
79
84
  /**
80
85
  * Create property access
81
86
  */
82
- static createAccess(factory: ts.NodeFactory, first: string | ts.Expression, second: string | ts.Identifier, ...items: (string | ts.Identifier)[]) {
87
+ static createAccess(
88
+ factory: ts.NodeFactory,
89
+ first: string | ts.Expression,
90
+ second: string | ts.Identifier,
91
+ ...items: (string | ts.Identifier)[]
92
+ ): ts.PropertyAccessExpression {
83
93
  if (typeof first === 'string') {
84
94
  first = factory.createIdentifier(first);
85
95
  }
@@ -92,12 +102,12 @@ export class CoreUtil {
92
102
  /**
93
103
  * Create a decorator with a given name, and arguments
94
104
  */
95
- static createDecorator(factory: ts.NodeFactory, name: ts.Expression, ...contents: (ts.Expression | undefined)[]) {
105
+ static createDecorator(factory: ts.NodeFactory, name: ts.Expression, ...contents: (ts.Expression | undefined)[]): ts.Decorator {
96
106
  return factory.createDecorator(
97
107
  factory.createCallExpression(
98
108
  name,
99
109
  undefined,
100
- contents.filter(x => !!x) as ts.Expression[]
110
+ contents.filter((x?: ts.Expression): x is ts.Expression => !!x)
101
111
  )
102
112
  );
103
113
  }
@@ -105,7 +115,7 @@ export class CoreUtil {
105
115
  /**
106
116
  * Is declaration abstract?
107
117
  */
108
- static isAbstract(node: ts.Declaration) {
118
+ static isAbstract(node: ts.Declaration): boolean {
109
119
  // eslint-disable-next-line no-bitwise
110
120
  return !!(ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Abstract);
111
121
  }
@@ -10,7 +10,7 @@ export class DeclarationUtil {
10
10
  * Searches upward from the node until it finds the variable declaration list,
11
11
  * and then checks the toString for `const `
12
12
  */
13
- static isConstantDeclaration(node: ts.Node) {
13
+ static isConstantDeclaration(node: ts.Node): boolean {
14
14
  let s: ts.Node = node;
15
15
  while (s && !ts.isVariableDeclarationList(s)) {
16
16
  s = s.parent;
@@ -21,7 +21,7 @@ export class DeclarationUtil {
21
21
  /**
22
22
  * See if a declaration is public
23
23
  */
24
- static isPublic(node: ts.Declaration) {
24
+ static isPublic(node: ts.Declaration): boolean {
25
25
  // eslint-disable-next-line no-bitwise
26
26
  return !(ts.getCombinedModifierFlags(node) & ts.ModifierFlags.NonPublicAccessibilityModifier);
27
27
  }
@@ -57,8 +57,8 @@ export class DeclarationUtil {
57
57
  * Resolve the `ts.ObjectFlags`
58
58
  */
59
59
  static getObjectFlags(type: ts.Type): ts.ObjectFlags {
60
- // @ts-ignore
61
- return ts.getObjectFlags(type);
60
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
61
+ return (ts as unknown as { getObjectFlags(t: ts.Type): ts.ObjectFlags }).getObjectFlags(type);
62
62
  }
63
63
 
64
64
  /**
@@ -67,7 +67,9 @@ export class DeclarationUtil {
67
67
  * @param node
68
68
  * @returns
69
69
  */
70
- static getAccessorPair(node: ts.GetAccessorDeclaration | ts.SetAccessorDeclaration) {
70
+ static getAccessorPair(
71
+ node: ts.GetAccessorDeclaration | ts.SetAccessorDeclaration
72
+ ): { getter?: ts.GetAccessorDeclaration, setter?: ts.SetAccessorDeclaration } {
71
73
  const acc = { getter: ts.isGetAccessorDeclaration(node) ? node : undefined, setter: ts.isSetAccessorDeclaration(node) ? node : undefined };
72
74
  if (ts.isClassDeclaration(node.parent)) {
73
75
  for (const el of node.parent.members) {
@@ -10,10 +10,12 @@ export class DecoratorUtil {
10
10
  * Get identifier for a decorator
11
11
  */
12
12
  static getDecoratorIdent(d: ts.Decorator): ts.Identifier {
13
- if (ts.isCallExpression(d.expression)) {
14
- return d.expression.expression as ts.Identifier;
13
+ if (ts.isCallExpression(d.expression) && ts.isIdentifier(d.expression.expression)) {
14
+ return d.expression.expression;
15
15
  } else if (ts.isIdentifier(d.expression)) {
16
16
  return d.expression;
17
+ } else if (ts.isCallExpression(d.expression) && ts.isPropertyAccessExpression(d.expression.expression) && ts.isIdentifier(d.expression.expression.expression)) {
18
+ return d.expression.expression.expression;
17
19
  } else {
18
20
  throw new Error('No Identifier');
19
21
  }
@@ -22,7 +24,7 @@ export class DecoratorUtil {
22
24
  /**
23
25
  * Replace or add a decorator to a list of decorators
24
26
  */
25
- static spliceDecorators(node: ts.Node, target: ts.Decorator | undefined, replacements: ts.Decorator[], idx = -1) {
27
+ static spliceDecorators(node: ts.Node, target: ts.Decorator | undefined, replacements: ts.Decorator[], idx = -1): ts.Decorator[] {
26
28
  if (idx < 0 && target) {
27
29
  idx = node.decorators?.indexOf(target) ?? -1;
28
30
  }
@@ -46,6 +48,7 @@ export class DecoratorUtil {
46
48
  * Find the primary argument of a call expression, or decorator.
47
49
  */
48
50
  static getArguments<T extends ts.Expression = ts.Expression>(node: ts.Decorator | undefined): T[] | undefined {
51
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
49
52
  return node && ts.isCallExpression(node.expression) ? [...node.expression.arguments] as T[] : undefined;
50
53
  }
51
54
  }
package/src/util/doc.ts CHANGED
@@ -18,14 +18,14 @@ export class DocUtil {
18
18
  /**
19
19
  * Read doc comment for node
20
20
  */
21
- static getDocComment(o: ts.JSDoc | ts.JSDocTag, def?: string) {
21
+ static getDocComment(o: ts.JSDoc | ts.JSDocTag, def?: string): string | undefined {
22
22
  return (typeof o.comment === 'string' ? o.comment : undefined) ?? def;
23
23
  }
24
24
 
25
25
  /**
26
26
  * Read JS Docs from a `ts.Declaration`
27
27
  */
28
- static describeDocs(node: ts.Declaration | ts.Type) {
28
+ static describeDocs(node: ts.Declaration | ts.Type): DeclDocumentation {
29
29
  if (node && !('getSourceFile' in node)) {
30
30
  node = DeclarationUtil.getPrimaryDeclarationNode(node);
31
31
  }
@@ -38,6 +38,7 @@ export class DocUtil {
38
38
  if (node) {
39
39
  const tags = ts.getJSDocTags(node);
40
40
  while (!this.hasJSDoc(node) && CoreUtil.hasOriginal(node)) {
41
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
41
42
  node = node.original as ts.Declaration;
42
43
  }
43
44
 
@@ -80,7 +81,7 @@ export class DocUtil {
80
81
  * Read augments information
81
82
  * @param type
82
83
  */
83
- static readAugments(type: ts.Type | ts.Symbol) {
84
+ static readAugments(type: ts.Type | ts.Symbol): string[] {
84
85
  return this.readDocTag(type, 'augments').map(x => x.replace(/^.*?([^` ]+).*?$/, (_, b) => b));
85
86
  }
86
87
  }
@@ -12,7 +12,7 @@ export class ImportUtil {
12
12
  /*
13
13
  * useful for handling failed imports, but still transpiling
14
14
  */
15
- static optionalResolve(file: string, base?: string) {
15
+ static optionalResolve(file: string, base?: string): string {
16
16
  file = base ? pathResolve(base, file) : file;
17
17
  try {
18
18
  return require.resolve(file);
@@ -24,7 +24,7 @@ export class ImportUtil {
24
24
  /**
25
25
  * Collect all imports for a source file, as a hash map
26
26
  */
27
- static collectImports(src: ts.SourceFile) {
27
+ static collectImports(src: ts.SourceFile): Map<string, Import> {
28
28
  const pth = require.resolve(src.fileName);
29
29
  const base = PathUtil.toUnix(pth);
30
30
 
@@ -25,7 +25,9 @@ export class LiteralUtil {
25
25
  static fromLiteral(factory: ts.NodeFactory, val: unknown[]): ts.ArrayLiteralExpression;
26
26
  static fromLiteral(factory: ts.NodeFactory, val: string | boolean | number): ts.LiteralExpression;
27
27
  static fromLiteral(factory: ts.NodeFactory, val: unknown): ts.Node {
28
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
28
29
  if (val && (val as ts.Expression).kind) { // If already a node
30
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
29
31
  return val as ts.Node;
30
32
  } else if (Array.isArray(val)) {
31
33
  val = factory.createArrayLiteralExpression(val.map(v => this.fromLiteral(factory, v)));
@@ -40,11 +42,13 @@ export class LiteralUtil {
40
42
  } else if (typeof val === 'boolean') {
41
43
  val = val ? factory.createTrue() : factory.createFalse();
42
44
  } else if (val === String || val === Number || val === Boolean || val === Date || val === RegExp) {
45
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
43
46
  val = factory.createIdentifier((val as Function).name);
44
47
  } else {
48
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
45
49
  const ov = val as object;
46
50
  const pairs: ts.PropertyAssignment[] = [];
47
- for (const k of Object.keys(ov) as (keyof typeof ov)[]) {
51
+ for (const k of Object.keys(ov)) {
48
52
  if (ov[k] !== undefined) {
49
53
  pairs.push(
50
54
  factory.createPropertyAssignment(k, this.fromLiteral(factory, ov[k]))
@@ -53,13 +57,22 @@ export class LiteralUtil {
53
57
  }
54
58
  return factory.createObjectLiteralExpression(pairs);
55
59
  }
60
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
56
61
  return val as ts.Expression;
57
62
  }
58
63
 
59
64
  /**
60
65
  * Convert a `ts.Node` to a JS literal
61
66
  */
62
- static toLiteral(val: ts.Node, strict = true): unknown {
67
+ static toLiteral(val: ts.NullLiteral, strict?: boolean): null;
68
+ static toLiteral(val: ts.NumericLiteral, strict?: boolean): number;
69
+ static toLiteral(val: ts.StringLiteral, strict?: boolean): string;
70
+ static toLiteral(val: ts.BooleanLiteral, strict?: boolean): boolean;
71
+ static toLiteral(val: ts.ObjectLiteralExpression, strict?: boolean): object;
72
+ static toLiteral(val: ts.ArrayLiteralExpression, strict?: boolean): unknown[];
73
+ static toLiteral(val: undefined, strict?: boolean): undefined;
74
+ static toLiteral(val: ts.Node, strict?: boolean): unknown;
75
+ static toLiteral(val?: ts.Node, strict = true): unknown {
63
76
  if (!val) {
64
77
  throw new Error('Val is not defined');
65
78
  } else if (ts.isArrayLiteralExpression(val)) {
@@ -102,7 +115,7 @@ export class LiteralUtil {
102
115
  /**
103
116
  * Extend object literal, whether JSON or ts.ObjectLiteralExpression
104
117
  */
105
- static extendObjectLiteral(factory: ts.NodeFactory, src: object | ts.Expression, ...rest: (object | ts.Expression)[]) {
118
+ static extendObjectLiteral(factory: ts.NodeFactory, src: object | ts.Expression, ...rest: (object | ts.Expression)[]): ts.ObjectLiteralExpression {
106
119
  let ret = this.fromLiteral(factory, src);
107
120
  if (rest.find(x => !!x)) {
108
121
  ret = factory.createObjectLiteralExpression([
@@ -116,7 +129,7 @@ export class LiteralUtil {
116
129
  /**
117
130
  * Get a value from the an object expression
118
131
  */
119
- static getObjectValue(node: ts.Expression | undefined, key: string) {
132
+ static getObjectValue(node: ts.Expression | undefined, key: string): ts.Expression | undefined {
120
133
  if (node && ts.isObjectLiteralExpression(node) && node.properties) {
121
134
  for (const prop of node.properties) {
122
135
  if (prop.name!.getText() === key) {
package/src/util/log.ts CHANGED
@@ -14,7 +14,7 @@ export class LogUtil {
14
14
  /**
15
15
  * Clean up `ts.Node` contents for logging
16
16
  */
17
- static collapseNodes(all: unknown[]) {
17
+ static collapseNodes(all: unknown[]): unknown[] {
18
18
  return all.map(x => this.collapseNode(x));
19
19
  }
20
20
 
@@ -35,15 +35,16 @@ export class LogUtil {
35
35
  if (Array.isArray(x)) {
36
36
  return x.map(v => this.collapseNode(v, cache));
37
37
  } else {
38
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38
39
  const ox = x as object;
39
40
  const out: Record<string, unknown> = {};
40
- for (const key of Object.keys(ox) as (keyof typeof x)[]) {
41
+ for (const key of Object.keys(ox)) {
41
42
  if (Util.isFunction(ox[key]) || exclude.has(key) || ox[key] === undefined) {
42
43
  continue;
43
44
  }
44
45
  try {
45
46
  out[key] = this.collapseNode(ox[key], cache);
46
- } catch (err) {
47
+ } catch {
47
48
  return undefined;
48
49
  }
49
50
  }
package/src/visitor.ts CHANGED
@@ -54,7 +54,7 @@ export class VisitorFactory<S extends State = State> {
54
54
  /**
55
55
  * Initialize internal mapping given a list of transformers
56
56
  */
57
- #init(transformers: NodeTransformer<S, TransformerType, ts.Node>[]) {
57
+ #init(transformers: NodeTransformer<S, TransformerType, ts.Node>[]): void {
58
58
  for (const trn of transformers) {
59
59
  if (!this.#transformers.has(trn.type)) {
60
60
  this.#transformers.set(trn.type, {});
@@ -116,10 +116,13 @@ export class VisitorFactory<S extends State = State> {
116
116
  ret = CoreUtil.updateSource(context.factory, ret, statements);
117
117
  }
118
118
  return state.finalize(ret);
119
- } catch (e) {
120
- console.error('Failed transforming', { error: e, file: file.fileName });
121
- const out = new Error(`Failed transforming: ${file.fileName}: ${e.message}`);
122
- out.stack = e.stack;
119
+ } catch (err) {
120
+ if (!(err instanceof Error)) {
121
+ throw err;
122
+ }
123
+ console.error('Failed transforming', { error: err, file: file.fileName });
124
+ const out = new Error(`Failed transforming: ${file.fileName}: ${err.message}`);
125
+ out.stack = err.stack;
123
126
  throw out;
124
127
  } finally {
125
128
  ConsoleManager.clear(); // Reset logging
@@ -130,12 +133,13 @@ export class VisitorFactory<S extends State = State> {
130
133
  /**
131
134
  * Handle transformer that target both ascent and descent
132
135
  */
133
- executePhaseAlways<T extends ts.Node>(state: S, set: TransformerSet<S>, phase: TransformPhase, node: T) {
136
+ executePhaseAlways<T extends ts.Node>(state: S, set: TransformerSet<S>, phase: TransformPhase, node: T): T | undefined {
134
137
  if (!set[phase]?.size) {
135
138
  return;
136
139
  }
137
140
 
138
141
  for (const all of set[phase]!.get('ALL') ?? []) {
142
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
139
143
  node = (all[phase]!(state, node) as T) ?? node;
140
144
  }
141
145
  return node;
@@ -144,7 +148,7 @@ export class VisitorFactory<S extends State = State> {
144
148
  /**
145
149
  * Handle a single phase of transformation
146
150
  */
147
- executePhase<T extends ts.Node>(state: S, set: TransformerSet<S>, phase: TransformPhase, node: T) {
151
+ executePhase<T extends ts.Node>(state: S, set: TransformerSet<S>, phase: TransformPhase, node: T): T | undefined {
148
152
  if (!set[phase]?.size) {
149
153
  return;
150
154
  }
@@ -169,6 +173,7 @@ export class VisitorFactory<S extends State = State> {
169
173
 
170
174
  // For all matching handlers, execute
171
175
  for (const item of values) {
176
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
172
177
  node = (item[phase]!(state, node, dec) as T) ?? node;
173
178
  }
174
179
  }
@@ -13,14 +13,14 @@ export class TransformerTestUtil {
13
13
  /**
14
14
  * Compile a single file from a folder
15
15
  */
16
- static async compile(folder: string, file?: string) {
16
+ static async compile(folder: string, file?: string): Promise<string> {
17
17
 
18
18
  const tsconfigObj = await import('@travetto/boot/tsconfig.trv.json');
19
19
 
20
20
  const prog = ts.createProgram({
21
21
  options: ts.convertCompilerOptionsFromJson(tsconfigObj, '').options,
22
22
  rootNames: (await ScanFs.scanDir({ testFile: f => f.startsWith('src/') && f.endsWith('.ts') }, folder))
23
- .filter(x => x.stats.isFile())
23
+ .filter(x => x.stats?.isFile())
24
24
  .filter(x => !file || x.file.endsWith(file))
25
25
  .map(x => x.file),
26
26
  });
@@ -30,7 +30,7 @@ export class TransformerTestUtil {
30
30
 
31
31
  const transformers =
32
32
  (await ScanFs.scanDir({ testFile: f => f.startsWith('support/transformer') }, folder))
33
- .filter(x => x.stats.isFile())
33
+ .filter(x => x.stats?.isFile())
34
34
  .map(x => import(x.file).then(getAllTransformers));
35
35
 
36
36
  const visitor = new VisitorFactory(