@travetto/transformer 3.0.0-rc.3 → 3.0.0-rc.6

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.
@@ -1,5 +1,5 @@
1
- import * as ts from 'typescript';
2
- import { AnyType } from './types';
1
+ import ts from 'typescript';
2
+ import type { AnyType } from './types';
3
3
 
4
4
  /**
5
5
  * Cache for handling recursive checks
@@ -0,0 +1,103 @@
1
+ const REGEX_PAT = /[\/](.*)[\/](i|g|m|s)?/;
2
+
3
+ export class CoerceUtil {
4
+ /**
5
+ * Is a value a plain JS object, created using {}
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
13
+ }
14
+
15
+ /**
16
+ * Create regex from string, including flags
17
+ */
18
+ static #toRegex(input: string | RegExp): RegExp {
19
+ if (input instanceof RegExp) {
20
+ return input;
21
+ } else if (REGEX_PAT.test(input)) {
22
+ const [, pat, mod] = input.match(REGEX_PAT) ?? [];
23
+ return new RegExp(pat, mod);
24
+ } else {
25
+ return new RegExp(input);
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Coerce an input of any type to the class provided
31
+ * @param input Input value
32
+ * @param type Class to coerce to (String, Boolean, Number, Date, RegEx, Object)
33
+ * @param strict Should a failure to coerce throw an error?
34
+ */
35
+ static coerce(input: unknown, type: typeof String, strict?: boolean): string;
36
+ static coerce(input: unknown, type: typeof Number, strict?: boolean): number;
37
+ static coerce(input: unknown, type: typeof Boolean, strict?: boolean): boolean;
38
+ static coerce(input: unknown, type: typeof Date, strict?: boolean): Date;
39
+ static coerce(input: unknown, type: typeof RegExp, strict?: boolean): RegExp;
40
+ static coerce(input: unknown, type: Function, strict = true): unknown {
41
+ // Do nothing
42
+ if (input === null || input === undefined) {
43
+ return input;
44
+ } else if (!strict && type !== String && input === '') {
45
+ return undefined; // treat empty string as undefined for non-strings in non-strict mode
46
+ } else if (type && input instanceof type) {
47
+ return input;
48
+ }
49
+
50
+ switch (type) {
51
+ case Date: {
52
+ const res = typeof input === 'number' || /^[-]?\d+$/.test(`${input}`) ?
53
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
54
+ new Date(parseInt(input as string, 10)) : new Date(input as Date);
55
+ if (strict && Number.isNaN(res.getTime())) {
56
+ throw new Error(`Invalid date value: ${input}`);
57
+ }
58
+ return res;
59
+ }
60
+ case Number: {
61
+ const res = `${input}`.includes('.') ? parseFloat(`${input}`) : parseInt(`${input}`, 10);
62
+ if (strict && Number.isNaN(res)) {
63
+ throw new Error(`Invalid numeric value: ${input}`);
64
+ }
65
+ return res;
66
+ }
67
+ case Boolean: {
68
+ const match = `${input}`.match(/^((?<TRUE>true|yes|1|on)|false|no|off|0)$/i);
69
+ if (strict && !match) {
70
+ throw new Error(`Invalid boolean value: ${input}`);
71
+ }
72
+ return !!match?.groups?.TRUE;
73
+ }
74
+ case RegExp: {
75
+ if (typeof input === 'string') {
76
+ try {
77
+ return this.#toRegex(input);
78
+ } catch {
79
+ if (strict) {
80
+ throw new Error(`Invalid regex: ${input}`);
81
+ } else {
82
+ return;
83
+ }
84
+ }
85
+ } else if (strict) {
86
+ throw new Error('Invalid regex type');
87
+ } else {
88
+ return;
89
+ }
90
+ }
91
+ case Object: {
92
+ if (!strict || this.#isPlainObject(input)) {
93
+ return input;
94
+ } else {
95
+ throw new Error('Invalid object type');
96
+ }
97
+ }
98
+ case undefined:
99
+ case String: return `${input}`;
100
+ }
101
+ throw new Error(`Unknown type ${type.name}`);
102
+ }
103
+ }
@@ -1,18 +1,21 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
- import { AnyType, Checker } from './types';
3
+ import type { AnyType, Checker } from './types';
4
4
  import { TypeCategorize, TypeBuilder } from './builder';
5
5
  import { VisitCache } from './cache';
6
- import { DocUtil } from '../util';
6
+ import { DocUtil } from '../util/doc';
7
+ import { TransformerIndex } from '../manifest-index';
7
8
 
8
9
  /**
9
10
  * Type resolver
10
11
  */
11
12
  export class TypeResolver implements Checker {
12
13
  #tsChecker: ts.TypeChecker;
14
+ #index: TransformerIndex;
13
15
 
14
- constructor(tsChecker: ts.TypeChecker) {
16
+ constructor(tsChecker: ts.TypeChecker, idx: TransformerIndex) {
15
17
  this.#tsChecker = tsChecker;
18
+ this.#index = idx;
16
19
  }
17
20
 
18
21
  /**
@@ -23,6 +26,10 @@ export class TypeResolver implements Checker {
23
26
  return this.#tsChecker;
24
27
  }
25
28
 
29
+ getIndex(): TransformerIndex {
30
+ return this.#index;
31
+ }
32
+
26
33
  /**
27
34
  * Get type from element
28
35
  * @param el
@@ -73,7 +80,7 @@ export class TypeResolver implements Checker {
73
80
  throw new Error('Object structure too nested');
74
81
  }
75
82
 
76
- const { category, type } = TypeCategorize(this.#tsChecker, resType);
83
+ const { category, type } = TypeCategorize(this.#tsChecker, resType, this.#index);
77
84
  const { build, finalize } = TypeBuilder[category];
78
85
 
79
86
  let result = build(this, type, alias);
@@ -1,4 +1,6 @@
1
- import type * as ts from 'typescript';
1
+ import type ts from 'typescript';
2
+
3
+ import { TransformerIndex } from '../manifest-index';
2
4
 
3
5
  /**
4
6
  * Base type for a simplistic type structure
@@ -37,7 +39,7 @@ export interface ExternalType extends Type<'external'> {
37
39
  /**
38
40
  * Location the type came from, for class references
39
41
  */
40
- source: string;
42
+ importName: string;
41
43
  /**
42
44
  * Type arguments
43
45
  */
@@ -55,7 +57,7 @@ export interface ShapeType extends Type<'shape'> {
55
57
  /**
56
58
  * Location the type came from, for class references
57
59
  */
58
- source: string;
60
+ importName: string;
59
61
  /**
60
62
  * Does not include methods, used for shapes not concrete types
61
63
  */
@@ -156,4 +158,5 @@ export interface Checker {
156
158
  getPropertiesOfType(type: ts.Type): ts.Symbol[];
157
159
  getTypeAsString(type: ts.Type): string | undefined;
158
160
  getType(node: ts.Node): ts.Type;
161
+ getIndex(): TransformerIndex;
159
162
  }
package/src/state.ts CHANGED
@@ -1,18 +1,20 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
- import { SystemUtil } from '@travetto/boot/src/internal/system';
4
- import { ModuleUtil } from '@travetto/boot/src/internal/module-util';
5
- import { Util } from '@travetto/base';
3
+ import { path } from '@travetto/manifest';
6
4
 
7
5
  import { ExternalType, AnyType } from './resolver/types';
8
- import { State, DecoratorMeta, Transformer, TransformerId } from './types/visitor';
6
+ import { State, DecoratorMeta, Transformer, ModuleNameⲐ } from './types/visitor';
9
7
  import { TypeResolver } from './resolver/service';
10
8
  import { ImportManager } from './importer';
9
+ import { Import } from './types/shared';
10
+
11
11
  import { DocUtil } from './util/doc';
12
12
  import { DecoratorUtil } from './util/decorator';
13
13
  import { DeclarationUtil } from './util/declaration';
14
- import { CoreUtil, LiteralUtil } from './util';
15
- import { Import } from './types/shared';
14
+ import { CoreUtil } from './util/core';
15
+ import { LiteralUtil } from './util/literal';
16
+ import { SystemUtil } from './util/system';
17
+ import { TransformerIndex } from './manifest-index';
16
18
 
17
19
  function hasOriginal(n: unknown): n is { original: ts.Node } {
18
20
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -28,20 +30,32 @@ function hasEscapedName(n: unknown): n is { name: { escapedText: string } } {
28
30
  * Transformer runtime state
29
31
  */
30
32
  export class TransformerState implements State {
31
- static SYNTHETIC_EXT = 'syn';
33
+ static SYNTHETIC_EXT = 'syn';
32
34
 
33
35
  #resolver: TypeResolver;
34
36
  #imports: ImportManager;
37
+ #index: TransformerIndex;
35
38
  #syntheticIdentifiers = new Map<string, ts.Identifier>();
36
39
  #decorators = new Map<string, ts.PropertyAccessExpression>();
37
-
40
+ #options: ts.CompilerOptions;
38
41
  added = new Map<number, ts.Statement[]>();
39
- module: string;
42
+ importName: string;
43
+ file: string;
44
+
45
+ constructor(public source: ts.SourceFile, public factory: ts.NodeFactory, checker: ts.TypeChecker, index: TransformerIndex, options: ts.CompilerOptions) {
46
+ this.#index = index;
47
+ this.#imports = new ImportManager(source, factory, index);
48
+ this.#resolver = new TypeResolver(checker, index);
49
+ this.file = path.toPosix(this.source.fileName);
50
+ this.importName = this.#index.getImportName(this.file, true);
51
+ this.#options = options;
52
+ }
40
53
 
41
- constructor(public source: ts.SourceFile, public factory: ts.NodeFactory, checker: ts.TypeChecker) {
42
- this.#imports = new ImportManager(source, factory);
43
- this.#resolver = new TypeResolver(checker);
44
- this.module = ModuleUtil.normalizePath(this.source.fileName);
54
+ /**
55
+ * Are we building ESM Output?
56
+ */
57
+ isEsmOutput(): boolean {
58
+ return this.#options.module !== ts.ModuleKind.CommonJS;
45
59
  }
46
60
 
47
61
  /**
@@ -62,8 +76,8 @@ export class TransformerState implements State {
62
76
  /**
63
77
  * Import a given file
64
78
  */
65
- importFile(file: string): Import {
66
- return this.#imports.importFile(file);
79
+ importFile(file: string, name?: string): Import {
80
+ return this.#imports.importFile(file, name);
67
81
  }
68
82
 
69
83
  /**
@@ -81,7 +95,9 @@ export class TransformerState implements State {
81
95
  resolveExternalType(node: ts.Node): ExternalType {
82
96
  const resolved = this.resolveType(node);
83
97
  if (resolved.key !== 'external') {
84
- throw new Error(`Unable to import non-external type: ${node.getText()} ${resolved.key}: ${node.getSourceFile().fileName}`);
98
+ const file = node.getSourceFile().fileName;
99
+ const src = this.#index.getImportName(file);
100
+ throw new Error(`Unable to import non-external type: ${node.getText()} ${resolved.key}: ${src}`);
85
101
  }
86
102
  return resolved;
87
103
  }
@@ -141,23 +157,24 @@ export class TransformerState implements State {
141
157
  /**
142
158
  * Read a decorator's metadata
143
159
  */
144
- getDecoratorMeta(dec: ts.Decorator): DecoratorMeta {
160
+ getDecoratorMeta(dec: ts.Decorator): DecoratorMeta | undefined {
145
161
  const ident = DecoratorUtil.getDecoratorIdent(dec);
146
162
  const decl = DeclarationUtil.getPrimaryDeclarationNode(
147
163
  this.#resolver.getType(ident)
148
164
  );
149
-
150
- return {
151
- dec,
152
- ident,
153
- file: decl?.getSourceFile().fileName,
154
- module: decl ? ModuleUtil.normalizePath(decl.getSourceFile().fileName) : undefined, // All #decorators will be absolute
155
- targets: DocUtil.readAugments(this.#resolver.getType(ident)),
156
- name: ident ?
157
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
158
- ident.escapedText! as string :
159
- undefined
160
- };
165
+ const src = decl?.getSourceFile().fileName;
166
+ const mod = src ? this.#index.getImportName(src, true) : undefined;
167
+ const file = this.#index.getFromImport(mod ?? '')?.output;
168
+ const targets = DocUtil.readAugments(this.#resolver.getType(ident));
169
+ const module = file ? mod : undefined;
170
+ const name = ident ?
171
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
172
+ ident.escapedText! as string :
173
+ undefined;
174
+
175
+ if (ident && name) {
176
+ return { dec, ident, file, module, targets, name };
177
+ }
161
178
  }
162
179
 
163
180
  /**
@@ -166,7 +183,7 @@ export class TransformerState implements State {
166
183
  getDecoratorList(node: ts.Node): DecoratorMeta[] {
167
184
  return ts.canHaveDecorators(node) ? (ts.getDecorators(node) ?? [])
168
185
  .map(dec => this.getDecoratorMeta(dec))
169
- .filter(x => !!x.ident) : [];
186
+ .filter((x): x is DecoratorMeta => !!x) : [];
170
187
  }
171
188
 
172
189
  /**
@@ -181,44 +198,40 @@ export class TransformerState implements State {
181
198
  * @param stmt
182
199
  * @param before
183
200
  */
184
- addStatement(stmt: ts.Statement, before?: ts.Node): void {
201
+ addStatements(added: ts.Statement[], before?: ts.Node | number): void {
185
202
  const stmts = this.source.statements.slice(0);
186
- let idx = stmts.length;
187
- let n = before;
188
- if (hasOriginal(n)) {
189
- n = n.original;
190
- }
191
- while (n && !ts.isSourceFile(n.parent)) {
192
- n = n.parent;
193
- }
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;
203
+ let idx = stmts.length + 1000;
204
+
205
+ if (before && typeof before !== 'number') {
206
+ let n = before;
207
+ if (hasOriginal(n)) {
208
+ n = n.original;
209
+ }
210
+ while (n && !ts.isSourceFile(n.parent) && n !== n.parent) {
211
+ n = n.parent;
212
+ }
213
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
214
+ const nStmt: ts.Statement = n as ts.Statement;
215
+ if (n && ts.isSourceFile(n.parent) && stmts.indexOf(nStmt) >= 0) {
216
+ idx = stmts.indexOf(nStmt) - 1;
217
+ }
218
+ } else if (before !== undefined) {
219
+ idx = before;
198
220
  }
199
221
  if (!this.added.has(idx)) {
200
222
  this.added.set(idx, []);
201
223
  }
202
- this.added.get(idx)!.push(stmt);
224
+ this.added.get(idx)!.push(...added);
203
225
  }
204
226
 
205
227
  /**
206
228
  * Finalize the source file for emission
207
229
  */
208
230
  finalize(ret: ts.SourceFile): ts.SourceFile {
209
- ret = this.#imports.finalize(ret);
231
+ ret = this.#imports.finalize(ret, this.#resolver.getChecker());
210
232
  return ret;
211
233
  }
212
234
 
213
- /**
214
- * Get Filename as ᚕsrc
215
- */
216
- getFilenameAsSrc(): ts.CallExpression {
217
- const ident = this.factory.createIdentifier('ᚕsrc');
218
- ident.getSourceFile = (): ts.SourceFile => this.source;
219
- return this.factory.createCallExpression(ident, [], [this.createIdentifier('__filename')]);
220
- }
221
-
222
235
  /**
223
236
  * From literal
224
237
  */
@@ -243,7 +256,7 @@ export class TransformerState implements State {
243
256
  /**
244
257
  * Create property access
245
258
  */
246
- createAccess(first: string | ts.Expression, second: string | ts.Identifier, ...items: (string | ts.Identifier)[]): ts.PropertyAccessExpression {
259
+ createAccess(first: string | ts.Expression, second: string | ts.Identifier, ...items: (string | number | ts.Identifier)[]): ts.Expression {
247
260
  return CoreUtil.createAccess(this.factory, first, second, ...items);
248
261
  }
249
262
 
@@ -262,6 +275,24 @@ export class TransformerState implements State {
262
275
  return this.factory.createIdentifier(typeof name === 'string' ? name : name.getText());
263
276
  }
264
277
 
278
+ /**
279
+ * Get filename identifier, regardless of module system
280
+ */
281
+ getFilenameIdentifier(): ts.Expression {
282
+ return this.isEsmOutput() ?
283
+ this.createAccess('import', 'meta', 'url') :
284
+ this.createIdentifier('__filename');
285
+ }
286
+
287
+ /**
288
+ * Get the entry file identifier, supports both ESM and commonjs
289
+ */
290
+ getEntryFileIdentifier(): ts.Expression {
291
+ return this.isEsmOutput() ?
292
+ this.createAccess('process', 'argv', 1) :
293
+ this.createAccess('require', 'main', 'filename');
294
+ }
295
+
265
296
  /**
266
297
  * Find decorator, relative to registered key
267
298
  * @param state
@@ -269,10 +300,11 @@ export class TransformerState implements State {
269
300
  * @param name
270
301
  * @param module
271
302
  */
272
- findDecorator(cls: Transformer, node: ts.Node, name: string, module?: string): ts.Decorator | undefined {
273
- const target = `${cls[TransformerId]}/${name}`;
274
- return this.getDecoratorList(node)
275
- .find(x => x.targets?.includes(target) && (!module || x.name === name && x.module === module))?.dec;
303
+ findDecorator(mod: string | Transformer, node: ts.Node, name: string, module?: string): ts.Decorator | undefined {
304
+ mod = typeof mod === 'string' ? mod : mod[ModuleNameⲐ]!;
305
+ const target = `${mod}:${name}`;
306
+ const list = this.getDecoratorList(node);
307
+ return list.find(x => x.targets?.includes(target) && (!module || x.name === name && x.module === module))?.dec;
276
308
  }
277
309
 
278
310
  /**
@@ -291,7 +323,7 @@ export class TransformerState implements State {
291
323
  }
292
324
  } catch {
293
325
  // Determine type unique ident
294
- unique = Util.uuid(type.name ? 5 : 10);
326
+ unique = SystemUtil.uuid(type.name ? 5 : 10);
295
327
  }
296
328
  // Otherwise read name with uuid
297
329
  let name = type.name && !type.name.startsWith('_') ? type.name : '';
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import type { default as ts } from 'typescript';
2
2
 
3
3
  /**
4
4
  * Param documentation
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
3
  /**
4
4
  * Decorator metadata
@@ -14,7 +14,7 @@ export type DecoratorMeta = {
14
14
 
15
15
  export type State = {
16
16
  source: ts.SourceFile;
17
- module: string;
17
+ importName: string;
18
18
  added: Map<number, ts.Statement[]>;
19
19
  getDecoratorList(node: ts.Node): DecoratorMeta[];
20
20
  finalize(src: ts.SourceFile): ts.SourceFile;
@@ -22,12 +22,14 @@ export type State = {
22
22
 
23
23
  export type TransformPhase = 'before' | 'after';
24
24
 
25
- export type TransformerType = 'class' | 'method' | 'property' | 'getter' | 'setter' | 'parameter' | 'static-method' | 'call' | 'function';
25
+ export type TransformerType =
26
+ 'class' | 'method' | 'property' | 'getter' | 'setter' | 'parameter' |
27
+ 'static-method' | 'call' | 'function' | 'file';
26
28
 
27
- export const TransformerId = Symbol.for('@trv:transformer/id');
29
+ export const ModuleNameⲐ = Symbol.for('@travetto/transformer:id');
28
30
 
29
31
  export type Transformer = {
30
- [TransformerId]: string;
32
+ [ModuleNameⲐ]?: string;
31
33
  name: string;
32
34
  };
33
35
 
package/src/util/core.ts CHANGED
@@ -1,9 +1,10 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
3
  /**
4
4
  * Core utilities util
5
5
  */
6
6
  export class CoreUtil {
7
+
7
8
  /**
8
9
  * See if inbound node has an original property
9
10
  */
@@ -51,7 +52,6 @@ export class CoreUtil {
51
52
  */
52
53
  static createStaticField(factory: ts.NodeFactory, name: string, val: ts.Expression): ts.PropertyDeclaration {
53
54
  return factory.createPropertyDeclaration(
54
- undefined,
55
55
  [factory.createToken(ts.SyntaxKind.StaticKeyword)],
56
56
  name, undefined, undefined, val
57
57
  );
@@ -88,13 +88,15 @@ export class CoreUtil {
88
88
  factory: ts.NodeFactory,
89
89
  first: string | ts.Expression,
90
90
  second: string | ts.Identifier,
91
- ...items: (string | ts.Identifier)[]
92
- ): ts.PropertyAccessExpression {
91
+ ...items: (string | number | ts.Identifier)[]
92
+ ): ts.Expression {
93
93
  if (typeof first === 'string') {
94
94
  first = factory.createIdentifier(first);
95
95
  }
96
- return items.reduce(
97
- (acc, p) => factory.createPropertyAccessExpression(acc, p),
96
+ return items.reduce<ts.Expression>(
97
+ (acc, p) => typeof p === 'number' ?
98
+ factory.createElementAccessExpression(acc, p) :
99
+ factory.createPropertyAccessExpression(acc, p),
98
100
  factory.createPropertyAccessExpression(first, second)
99
101
  );
100
102
  }
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
  import { CoreUtil } from './core';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
  import { CoreUtil } from './core';
3
3
 
4
4
  /**
package/src/util/doc.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
3
  import { DeclDocumentation } from '../types/shared';
4
4
  import { CoreUtil } from './core';
@@ -1,7 +1,6 @@
1
- import * as ts from 'typescript';
2
- import { resolve as pathResolve } from 'path';
1
+ import ts from 'typescript';
3
2
 
4
- import { PathUtil } from '@travetto/boot';
3
+ import { PackageUtil, path } from '@travetto/manifest';
5
4
 
6
5
  import { Import } from '../types/shared';
7
6
 
@@ -13,9 +12,17 @@ export class ImportUtil {
13
12
  * useful for handling failed imports, but still transpiling
14
13
  */
15
14
  static optionalResolve(file: string, base?: string): string {
16
- file = base ? pathResolve(base, file) : file;
15
+ if (base?.endsWith('.ts')) {
16
+ base = path.dirname(base);
17
+ }
18
+ if (base && file.startsWith('.')) {
19
+ return path.resolve(base, file);
20
+ // TODO: Replace with manifest reverse lookup
21
+ } else if (file.startsWith('@')) {
22
+ return path.resolve('node_modules', file);
23
+ }
17
24
  try {
18
- return require.resolve(file);
25
+ return PackageUtil.resolveImport(file);
19
26
  } catch {
20
27
  return file;
21
28
  }
@@ -25,23 +32,23 @@ export class ImportUtil {
25
32
  * Collect all imports for a source file, as a hash map
26
33
  */
27
34
  static collectImports(src: ts.SourceFile): Map<string, Import> {
28
- const pth = require.resolve(src.fileName);
29
- const base = PathUtil.toUnix(pth);
35
+ // TODO: Replace with manifest reverse lookup
36
+ const base = path.toPosix(src.fileName);
30
37
 
31
38
  const imports = new Map<string, Import>();
32
39
 
33
40
  for (const stmt of src.statements) {
34
41
  if (ts.isImportDeclaration(stmt) && ts.isStringLiteral(stmt.moduleSpecifier)) {
35
- const path = this.optionalResolve(stmt.moduleSpecifier.text, base);
42
+ const resolved = this.optionalResolve(stmt.moduleSpecifier.text, base);
36
43
 
37
44
  if (stmt.importClause) {
38
45
  if (stmt.importClause.namedBindings) {
39
46
  const bindings = stmt.importClause.namedBindings;
40
47
  if (ts.isNamespaceImport(bindings)) {
41
- imports.set(bindings.name.text, { path, ident: bindings.name, stmt });
48
+ imports.set(bindings.name.text, { path: resolved, ident: bindings.name, stmt });
42
49
  } else if (ts.isNamedImports(bindings)) {
43
50
  for (const n of bindings.elements) {
44
- imports.set(n.name.text, { path, ident: n.name, stmt });
51
+ imports.set(n.name.text, { path: resolved, ident: n.name, stmt });
45
52
  }
46
53
  }
47
54
  }
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
3
  /**
4
4
  * Utilities for dealing with literals
@@ -48,7 +48,8 @@ export class LiteralUtil {
48
48
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
49
49
  const ov = val as object;
50
50
  const pairs: ts.PropertyAssignment[] = [];
51
- for (const k of Object.keys(ov)) {
51
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
52
+ for (const k of Object.keys(ov) as (keyof typeof ov)[]) {
52
53
  if (ov[k] !== undefined) {
53
54
  pairs.push(
54
55
  factory.createPropertyAssignment(k, this.fromLiteral(factory, ov[k]))
package/src/util/log.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { Util } from '@travetto/base';
2
-
3
1
  const exclude = new Set([
4
2
  'parent', 'checker', 'end', 'pos', 'id', 'source', 'sourceFile', 'getSourceFile',
5
3
  'statements', 'stringIndexInfo', 'numberIndexInfo', 'instantiations', 'thisType',
@@ -22,7 +20,7 @@ export class LogUtil {
22
20
  * Clean up `ts.Node` contents for logging
23
21
  */
24
22
  static collapseNode(x: unknown, cache: Set<unknown> = new Set()): unknown {
25
- if (!x || Util.isPrimitive(x)) {
23
+ if (!x || !(typeof x === 'object' || typeof x === 'function')) {
26
24
  return x;
27
25
  }
28
26
 
@@ -39,7 +37,7 @@ export class LogUtil {
39
37
  const ox = x as object;
40
38
  const out: Record<string, unknown> = {};
41
39
  for (const key of Object.keys(ox)) {
42
- if (Util.isFunction(ox[key]) || exclude.has(key) || ox[key] === undefined) {
40
+ if (Object.getPrototypeOf(ox[key]) === Function.prototype || exclude.has(key) || ox[key] === undefined) {
43
41
  continue;
44
42
  }
45
43
  try {