@esportsplus/typescript 0.28.4 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/cli/tsc.js CHANGED
@@ -22,7 +22,7 @@ async function build(config, tsconfig, pluginConfigs) {
22
22
  if (!sourceFile) {
23
23
  continue;
24
24
  }
25
- let result = coordinator.transform(plugins, sourceFile.getFullText(), sourceFile, program, shared);
25
+ let result = coordinator.transform(plugins, sourceFile.getFullText(), sourceFile, program, root, shared);
26
26
  if (result.changed) {
27
27
  transformedFiles.set(normalizePath(fileName), result.code);
28
28
  }
@@ -6,7 +6,7 @@ type CoordinatorResult = {
6
6
  sourceFile: ts.SourceFile;
7
7
  };
8
8
  declare const _default: {
9
- transform: (plugins: Plugin[], code: string, file: ts.SourceFile, program: ts.Program, shared: SharedContext) => {
9
+ transform: (plugins: Plugin[], code: string, file: ts.SourceFile, program: ts.Program, root: string, shared: SharedContext) => {
10
10
  changed: boolean;
11
11
  code: string;
12
12
  sourceFile: ts.SourceFile;
@@ -1,5 +1,6 @@
1
1
  import { ts } from '../index.js';
2
2
  import imports from './imports.js';
3
+ import languageService from './language-service.js';
3
4
  function applyImports(code, file, intents) {
4
5
  for (let i = 0, n = intents.length; i < n; i++) {
5
6
  let intent = intents[i];
@@ -43,20 +44,6 @@ function applyPrepend(code, file, prepend) {
43
44
  }
44
45
  return code.slice(0, position) + prepend.join('\n') + code.slice(position);
45
46
  }
46
- function createPatchedProgram(baseProgram, fileName, newContent) {
47
- let baseHost = ts.createCompilerHost(baseProgram.getCompilerOptions()), options = baseProgram.getCompilerOptions();
48
- return ts.createProgram(baseProgram.getRootFileNames(), options, {
49
- ...baseHost,
50
- getSourceFile: (name, languageVersion) => {
51
- if (name === fileName || name === fileName.replace(/\\/g, '/')) {
52
- return ts.createSourceFile(name, newContent, languageVersion, true);
53
- }
54
- return baseProgram.getSourceFile(name) ?? baseHost.getSourceFile(name, languageVersion);
55
- },
56
- fileExists: (name) => baseHost.fileExists(name),
57
- readFile: (name) => name === fileName ? newContent : baseHost.readFile(name)
58
- }, baseProgram);
59
- }
60
47
  function hasPattern(code, patterns) {
61
48
  for (let i = 0, n = patterns.length; i < n; i++) {
62
49
  if (code.indexOf(patterns[i]) !== -1) {
@@ -125,11 +112,11 @@ function replaceReverse(code, replacements) {
125
112
  }
126
113
  return result;
127
114
  }
128
- const transform = (plugins, code, file, program, shared) => {
115
+ const transform = (plugins, code, file, program, root, shared) => {
129
116
  if (plugins.length === 0) {
130
117
  return { changed: false, code, sourceFile: file };
131
118
  }
132
- let changed = false, currentCode = code, currentFile = file, currentProgram = program, fileName = file.fileName;
119
+ let changed = false, currentCode = code, currentFile = file, currentProgram = program, fileName = file.fileName, last = plugins.length - 1;
133
120
  for (let i = 0, n = plugins.length; i < n; i++) {
134
121
  let plugin = plugins[i];
135
122
  if (plugin.patterns && !hasPattern(currentCode, plugin.patterns)) {
@@ -156,8 +143,8 @@ const transform = (plugins, code, file, program, shared) => {
156
143
  }
157
144
  if (pluginChanged) {
158
145
  changed = true;
159
- if (i < n - 1) {
160
- currentProgram = createPatchedProgram(program, fileName, currentCode);
146
+ if (i < last) {
147
+ currentProgram = languageService.update(root, fileName, currentCode);
161
148
  currentFile = currentProgram.getSourceFile(fileName) ||
162
149
  ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
163
150
  }
@@ -0,0 +1,12 @@
1
+ import ts from 'typescript';
2
+ declare const get: (root: string) => ts.Program;
3
+ declare const invalidate: (root: string, fileName: string) => void;
4
+ declare const update: (root: string, fileName: string, content: string) => ts.Program;
5
+ declare const _default: {
6
+ delete: (root: string) => void;
7
+ get: (root: string) => ts.Program;
8
+ invalidate: (root: string, fileName: string) => void;
9
+ update: (root: string, fileName: string, content: string) => ts.Program;
10
+ };
11
+ export default _default;
12
+ export { get, invalidate, update };
@@ -0,0 +1,83 @@
1
+ import path from 'path';
2
+ import ts from 'typescript';
3
+ import { PACKAGE_NAME } from '../constants.js';
4
+ let cache = new Map();
5
+ function create(root) {
6
+ let tsconfig = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');
7
+ if (!tsconfig) {
8
+ throw new Error(`${PACKAGE_NAME}: tsconfig.json not found`);
9
+ }
10
+ let file = ts.readConfigFile(tsconfig, ts.sys.readFile);
11
+ if (file.error) {
12
+ throw new Error(`${PACKAGE_NAME}: error reading tsconfig.json ${file.error.messageText}`);
13
+ }
14
+ let parsed = ts.parseJsonConfigFileContent(file.config, ts.sys, path.dirname(tsconfig));
15
+ if (parsed.errors.length > 0) {
16
+ throw new Error(`${PACKAGE_NAME}: error parsing tsconfig.json ${parsed.errors[0].messageText}`);
17
+ }
18
+ let contents = new Map(), rootFiles = new Set(parsed.fileNames.map(f => f.replace(/\\/g, '/'))), versions = new Map();
19
+ for (let fileName of rootFiles) {
20
+ versions.set(fileName, 0);
21
+ }
22
+ let host = {
23
+ fileExists: ts.sys.fileExists,
24
+ getCompilationSettings: () => parsed.options,
25
+ getCurrentDirectory: () => root,
26
+ getDefaultLibFileName: ts.getDefaultLibFilePath,
27
+ getScriptFileNames: () => [...rootFiles],
28
+ getScriptSnapshot: (fileName) => {
29
+ let content = contents.get(fileName);
30
+ if (content !== undefined) {
31
+ return ts.ScriptSnapshot.fromString(content);
32
+ }
33
+ if (!ts.sys.fileExists(fileName)) {
34
+ return undefined;
35
+ }
36
+ return ts.ScriptSnapshot.fromString(ts.sys.readFile(fileName) || '');
37
+ },
38
+ getScriptVersion: (fileName) => String(versions.get(fileName) || 0),
39
+ readFile: ts.sys.readFile
40
+ };
41
+ return { contents, host, rootFiles, service: ts.createLanguageService(host), versions };
42
+ }
43
+ function getEntry(root) {
44
+ let entry = cache.get(root);
45
+ if (!entry) {
46
+ entry = create(root);
47
+ cache.set(root, entry);
48
+ }
49
+ return entry;
50
+ }
51
+ const del = (root) => {
52
+ cache.delete(root);
53
+ };
54
+ const get = (root) => {
55
+ let entry = getEntry(root), program = entry.service.getProgram();
56
+ if (!program) {
57
+ throw new Error(`${PACKAGE_NAME}: failed to get program from language service`);
58
+ }
59
+ return program;
60
+ };
61
+ const invalidate = (root, fileName) => {
62
+ let entry = cache.get(root);
63
+ if (entry) {
64
+ let normalized = fileName.replace(/\\/g, '/');
65
+ entry.contents.delete(normalized);
66
+ entry.versions.set(normalized, (entry.versions.get(normalized) || 0) + 1);
67
+ }
68
+ };
69
+ const update = (root, fileName, content) => {
70
+ let entry = getEntry(root), normalized = fileName.replace(/\\/g, '/');
71
+ if (!entry.rootFiles.has(normalized)) {
72
+ entry.rootFiles.add(normalized);
73
+ }
74
+ entry.contents.set(normalized, content);
75
+ entry.versions.set(normalized, (entry.versions.get(normalized) || 0) + 1);
76
+ let program = entry.service.getProgram();
77
+ if (!program) {
78
+ throw new Error(`${PACKAGE_NAME}: failed to get program from language service`);
79
+ }
80
+ return program;
81
+ };
82
+ export default { delete: del, get, invalidate, update };
83
+ export { get, invalidate, update };
@@ -1,9 +1,8 @@
1
1
  import { ts } from '../../index.js';
2
2
  import coordinator from '../coordinator.js';
3
- import program from '../program.js';
4
- const FILE_REGEX = /\.[tj]sx?$/;
3
+ import languageService from '../language-service.js';
5
4
  const DIRECTORY_SEPARATOR_REGEX = /\\/g;
6
- const LINE_ENDINGS_REGEX = /\r\n/g;
5
+ const FILE_REGEX = /\.[tj]sx?$/;
7
6
  let contexts = new Map();
8
7
  export default ({ name, onWatchChange, plugins }) => {
9
8
  return ({ root } = {}) => {
@@ -18,12 +17,11 @@ export default ({ name, onWatchChange, plugins }) => {
18
17
  return null;
19
18
  }
20
19
  try {
21
- let prog = program.get(root || ''), sourceFile = prog.getSourceFile(id.replace(DIRECTORY_SEPARATOR_REGEX, '/')) || prog.getSourceFile(id);
22
- if (!sourceFile ||
23
- sourceFile.getText().replace(LINE_ENDINGS_REGEX, '\n') !== code.replace(LINE_ENDINGS_REGEX, '\n')) {
20
+ let normalizedId = id.replace(DIRECTORY_SEPARATOR_REGEX, '/'), prog = languageService.update(root || '', normalizedId, code), sourceFile = prog.getSourceFile(normalizedId);
21
+ if (!sourceFile) {
24
22
  sourceFile = ts.createSourceFile(id, code, ts.ScriptTarget.Latest, true);
25
23
  }
26
- let result = coordinator.transform(plugins, code, sourceFile, prog, contexts.get(root || '') ?? contexts.set(root || '', new Map()).get(root || ''));
24
+ let result = coordinator.transform(plugins, code, sourceFile, prog, root || '', contexts.get(root || '') ?? contexts.set(root || '', new Map()).get(root || ''));
27
25
  if (!result.changed) {
28
26
  return null;
29
27
  }
@@ -38,7 +36,7 @@ export default ({ name, onWatchChange, plugins }) => {
38
36
  if (FILE_REGEX.test(id)) {
39
37
  onWatchChange?.();
40
38
  contexts.delete(root || '');
41
- program.delete(root || '');
39
+ languageService.invalidate(root || '', id);
42
40
  }
43
41
  }
44
42
  };
package/package.json CHANGED
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "type": "module",
41
41
  "types": "build/index.d.ts",
42
- "version": "0.28.4",
42
+ "version": "0.29.0",
43
43
  "scripts": {
44
44
  "build": "tsc && tsc-alias",
45
45
  "-": "-"
package/src/cli/tsc.ts CHANGED
@@ -54,6 +54,7 @@ async function build(config: object, tsconfig: string, pluginConfigs: PluginConf
54
54
  sourceFile.getFullText(),
55
55
  sourceFile,
56
56
  program,
57
+ root,
57
58
  shared
58
59
  );
59
60
 
@@ -1,6 +1,7 @@
1
1
  import type { ImportIntent, Plugin, Replacement, ReplacementIntent, SharedContext } from './types';
2
2
  import { ts } from '~/index';
3
3
  import imports, { ModifyOptions } from './imports';
4
+ import languageService from './language-service';
4
5
 
5
6
 
6
7
  type CoordinatorResult = {
@@ -73,28 +74,6 @@ function applyPrepend(code: string, file: ts.SourceFile, prepend: string[]): str
73
74
  return code.slice(0, position) + prepend.join('\n') + code.slice(position);
74
75
  }
75
76
 
76
- function createPatchedProgram(baseProgram: ts.Program, fileName: string, newContent: string) {
77
- let baseHost = ts.createCompilerHost(baseProgram.getCompilerOptions()),
78
- options = baseProgram.getCompilerOptions();
79
-
80
- return ts.createProgram(
81
- baseProgram.getRootFileNames(),
82
- options,
83
- {
84
- ...baseHost,
85
- getSourceFile: (name, languageVersion) => {
86
- if (name === fileName || name === fileName.replace(/\\/g, '/')) {
87
- return ts.createSourceFile(name, newContent, languageVersion, true);
88
- }
89
- return baseProgram.getSourceFile(name) ?? baseHost.getSourceFile(name, languageVersion);
90
- },
91
- fileExists: (name) => baseHost.fileExists(name),
92
- readFile: (name) => name === fileName ? newContent : baseHost.readFile(name)
93
- },
94
- baseProgram
95
- );
96
- }
97
-
98
77
  function hasPattern(code: string, patterns: string[]): boolean {
99
78
  for (let i = 0, n = patterns.length; i < n; i++) {
100
79
  if (code.indexOf(patterns[i]) !== -1) {
@@ -190,11 +169,13 @@ function replaceReverse(code: string, replacements: Replacement[]): string {
190
169
  return result;
191
170
  }
192
171
 
172
+
193
173
  const transform = (
194
174
  plugins: Plugin[],
195
175
  code: string,
196
176
  file: ts.SourceFile,
197
177
  program: ts.Program,
178
+ root: string,
198
179
  shared: SharedContext
199
180
  ) => {
200
181
  if (plugins.length === 0) {
@@ -205,7 +186,8 @@ const transform = (
205
186
  currentCode = code,
206
187
  currentFile = file,
207
188
  currentProgram = program,
208
- fileName = file.fileName;
189
+ fileName = file.fileName,
190
+ last = plugins.length - 1;
209
191
 
210
192
  for (let i = 0, n = plugins.length; i < n; i++) {
211
193
  let plugin = plugins[i];
@@ -240,9 +222,9 @@ const transform = (
240
222
 
241
223
  if (pluginChanged) {
242
224
  changed = true;
243
- // Create patched program for next plugin
244
- if (i < n - 1) {
245
- currentProgram = createPatchedProgram(program, fileName, currentCode);
225
+
226
+ if (i < last) {
227
+ currentProgram = languageService.update(root, fileName, currentCode);
246
228
  currentFile = currentProgram.getSourceFile(fileName) ||
247
229
  ts.createSourceFile(fileName, currentCode, file.languageVersion, true);
248
230
  }
@@ -0,0 +1,135 @@
1
+ import path from 'path';
2
+ import ts from 'typescript';
3
+ import { PACKAGE_NAME } from '~/constants';
4
+
5
+
6
+ type LanguageServiceEntry = {
7
+ contents: Map<string, string>;
8
+ host: ts.LanguageServiceHost;
9
+ rootFiles: Set<string>;
10
+ service: ts.LanguageService;
11
+ versions: Map<string, number>;
12
+ };
13
+
14
+
15
+ let cache = new Map<string, LanguageServiceEntry>();
16
+
17
+
18
+ function create(root: string): LanguageServiceEntry {
19
+ let tsconfig = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');
20
+
21
+ if (!tsconfig) {
22
+ throw new Error(`${PACKAGE_NAME}: tsconfig.json not found`);
23
+ }
24
+
25
+ let file = ts.readConfigFile(tsconfig, ts.sys.readFile);
26
+
27
+ if (file.error) {
28
+ throw new Error(`${PACKAGE_NAME}: error reading tsconfig.json ${file.error.messageText}`);
29
+ }
30
+
31
+ let parsed = ts.parseJsonConfigFileContent(
32
+ file.config,
33
+ ts.sys,
34
+ path.dirname(tsconfig)
35
+ );
36
+
37
+ if (parsed.errors.length > 0) {
38
+ throw new Error(`${PACKAGE_NAME}: error parsing tsconfig.json ${parsed.errors[0].messageText}`);
39
+ }
40
+
41
+ let contents = new Map<string, string>(),
42
+ rootFiles = new Set(parsed.fileNames.map(f => f.replace(/\\/g, '/'))),
43
+ versions = new Map<string, number>();
44
+
45
+ for (let fileName of rootFiles) {
46
+ versions.set(fileName, 0);
47
+ }
48
+
49
+ let host: ts.LanguageServiceHost = {
50
+ fileExists: ts.sys.fileExists,
51
+ getCompilationSettings: () => parsed.options,
52
+ getCurrentDirectory: () => root,
53
+ getDefaultLibFileName: ts.getDefaultLibFilePath,
54
+ getScriptFileNames: () => [...rootFiles],
55
+ getScriptSnapshot: (fileName: string) => {
56
+ let content = contents.get(fileName);
57
+
58
+ if (content !== undefined) {
59
+ return ts.ScriptSnapshot.fromString(content);
60
+ }
61
+
62
+ if (!ts.sys.fileExists(fileName)) {
63
+ return undefined;
64
+ }
65
+
66
+ return ts.ScriptSnapshot.fromString(ts.sys.readFile(fileName) || '');
67
+ },
68
+ getScriptVersion: (fileName: string) => String(versions.get(fileName) || 0),
69
+ readFile: ts.sys.readFile
70
+ };
71
+
72
+ return { contents, host, rootFiles, service: ts.createLanguageService(host), versions };
73
+ }
74
+
75
+ function getEntry(root: string): LanguageServiceEntry {
76
+ let entry = cache.get(root);
77
+
78
+ if (!entry) {
79
+ entry = create(root);
80
+ cache.set(root, entry);
81
+ }
82
+
83
+ return entry;
84
+ }
85
+
86
+
87
+ const del = (root: string): void => {
88
+ cache.delete(root);
89
+ };
90
+
91
+ const get = (root: string): ts.Program => {
92
+ let entry = getEntry(root),
93
+ program = entry.service.getProgram();
94
+
95
+ if (!program) {
96
+ throw new Error(`${PACKAGE_NAME}: failed to get program from language service`);
97
+ }
98
+
99
+ return program;
100
+ };
101
+
102
+ const invalidate = (root: string, fileName: string): void => {
103
+ let entry = cache.get(root);
104
+
105
+ if (entry) {
106
+ let normalized = fileName.replace(/\\/g, '/');
107
+
108
+ entry.contents.delete(normalized);
109
+ entry.versions.set(normalized, (entry.versions.get(normalized) || 0) + 1);
110
+ }
111
+ };
112
+
113
+ const update = (root: string, fileName: string, content: string): ts.Program => {
114
+ let entry = getEntry(root),
115
+ normalized = fileName.replace(/\\/g, '/');
116
+
117
+ if (!entry.rootFiles.has(normalized)) {
118
+ entry.rootFiles.add(normalized);
119
+ }
120
+
121
+ entry.contents.set(normalized, content);
122
+ entry.versions.set(normalized, (entry.versions.get(normalized) || 0) + 1);
123
+
124
+ let program = entry.service.getProgram();
125
+
126
+ if (!program) {
127
+ throw new Error(`${PACKAGE_NAME}: failed to get program from language service`);
128
+ }
129
+
130
+ return program;
131
+ };
132
+
133
+
134
+ export default { delete: del, get, invalidate, update };
135
+ export { get, invalidate, update };
@@ -2,7 +2,7 @@ import type { ResolvedConfig } from 'vite';
2
2
  import type { Plugin, SharedContext } from '../types';
3
3
  import { ts } from '~/index';
4
4
  import coordinator from '../coordinator';
5
- import program from '../program';
5
+ import languageService from '../language-service';
6
6
 
7
7
 
8
8
  type VitePlugin = {
@@ -20,11 +20,9 @@ type VitePluginOptions = {
20
20
  };
21
21
 
22
22
 
23
- const FILE_REGEX = /\.[tj]sx?$/;
24
-
25
23
  const DIRECTORY_SEPARATOR_REGEX = /\\/g;
26
24
 
27
- const LINE_ENDINGS_REGEX = /\r\n/g;
25
+ const FILE_REGEX = /\.[tj]sx?$/;
28
26
 
29
27
 
30
28
  let contexts = new Map<string, SharedContext>();
@@ -44,13 +42,11 @@ export default ({ name, onWatchChange, plugins }: VitePluginOptions) => {
44
42
  }
45
43
 
46
44
  try {
47
- let prog = program.get(root || ''),
48
- sourceFile = prog.getSourceFile(id.replace(DIRECTORY_SEPARATOR_REGEX, '/')) || prog.getSourceFile(id);
45
+ let normalizedId = id.replace(DIRECTORY_SEPARATOR_REGEX, '/'),
46
+ prog = languageService.update(root || '', normalizedId, code),
47
+ sourceFile = prog.getSourceFile(normalizedId);
49
48
 
50
- if (
51
- !sourceFile ||
52
- sourceFile.getText().replace(LINE_ENDINGS_REGEX, '\n') !== code.replace(LINE_ENDINGS_REGEX, '\n')
53
- ) {
49
+ if (!sourceFile) {
54
50
  sourceFile = ts.createSourceFile(id, code, ts.ScriptTarget.Latest, true);
55
51
  }
56
52
 
@@ -59,6 +55,7 @@ export default ({ name, onWatchChange, plugins }: VitePluginOptions) => {
59
55
  code,
60
56
  sourceFile,
61
57
  prog,
58
+ root || '',
62
59
  contexts.get(root || '') ?? contexts.set(root || '', new Map()).get(root || '')!
63
60
  );
64
61
 
@@ -77,7 +74,7 @@ export default ({ name, onWatchChange, plugins }: VitePluginOptions) => {
77
74
  if (FILE_REGEX.test(id)) {
78
75
  onWatchChange?.();
79
76
  contexts.delete(root || '');
80
- program.delete(root || '');
77
+ languageService.invalidate(root || '', id);
81
78
  }
82
79
  }
83
80
  };
@@ -1,6 +0,0 @@
1
- import ts from 'typescript';
2
- declare const _default: {
3
- get: (root: string) => ts.Program;
4
- delete: (root: string) => void;
5
- };
6
- export default _default;
@@ -1,34 +0,0 @@
1
- import path from 'path';
2
- import ts from 'typescript';
3
- import { PACKAGE_NAME } from '../constants.js';
4
- let cache = new Map();
5
- function create(root) {
6
- let tsconfig = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');
7
- if (!tsconfig) {
8
- throw new Error('tsconfig.json not found');
9
- }
10
- let file = ts.readConfigFile(tsconfig, ts.sys.readFile);
11
- if (file.error) {
12
- throw new Error(`${PACKAGE_NAME}: error reading tsconfig.json ${file.error.messageText}`);
13
- }
14
- let parsed = ts.parseJsonConfigFileContent(file.config, ts.sys, path.dirname(tsconfig));
15
- if (parsed.errors.length > 0) {
16
- throw new Error(`${PACKAGE_NAME}: error parsing tsconfig.json ${parsed.errors[0].messageText}`);
17
- }
18
- return ts.createProgram({
19
- options: parsed.options,
20
- rootNames: parsed.fileNames
21
- });
22
- }
23
- const get = (root) => {
24
- let program = cache.get(root);
25
- if (!program) {
26
- program = create(root);
27
- cache.set(root, program);
28
- }
29
- return program;
30
- };
31
- const del = (root) => {
32
- cache.delete(root);
33
- };
34
- export default { get, delete: del };
@@ -1,55 +0,0 @@
1
- import path from 'path';
2
- import ts from 'typescript';
3
- import { PACKAGE_NAME } from '~/constants';
4
-
5
-
6
- let cache = new Map<string, ts.Program>();
7
-
8
-
9
- function create(root: string): ts.Program {
10
- let tsconfig = ts.findConfigFile(root, ts.sys.fileExists, 'tsconfig.json');
11
-
12
- if (!tsconfig) {
13
- throw new Error('tsconfig.json not found');
14
- }
15
-
16
- let file = ts.readConfigFile(tsconfig, ts.sys.readFile);
17
-
18
- if (file.error) {
19
- throw new Error(`${PACKAGE_NAME}: error reading tsconfig.json ${file.error.messageText}`);
20
- }
21
-
22
- let parsed = ts.parseJsonConfigFileContent(
23
- file.config,
24
- ts.sys,
25
- path.dirname(tsconfig)
26
- );
27
-
28
- if (parsed.errors.length > 0) {
29
- throw new Error(`${PACKAGE_NAME}: error parsing tsconfig.json ${parsed.errors[0].messageText}`);
30
- }
31
-
32
- return ts.createProgram({
33
- options: parsed.options,
34
- rootNames: parsed.fileNames
35
- });
36
- }
37
-
38
-
39
- const get = (root: string): ts.Program => {
40
- let program = cache.get(root);
41
-
42
- if (!program) {
43
- program = create(root);
44
- cache.set(root, program);
45
- }
46
-
47
- return program;
48
- }
49
-
50
- const del = (root: string): void => {
51
- cache.delete(root);
52
- }
53
-
54
-
55
- export default { get, delete: del };