@bleedingdev/modern-js-server-utils 3.2.0-ultramodern.99 → 3.4.0-ultramodern.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.
@@ -0,0 +1,204 @@
1
+ const IDENTIFIER_CHAR = /[A-Za-z0-9_$]/;
2
+ const WHITESPACE = /\s/;
3
+ const KEYWORDS_BEFORE_REGEX = new Set([
4
+ 'return',
5
+ 'typeof',
6
+ 'instanceof',
7
+ 'in',
8
+ 'of',
9
+ 'new',
10
+ 'delete',
11
+ 'void',
12
+ 'throw',
13
+ 'case',
14
+ 'do',
15
+ 'else',
16
+ 'yield',
17
+ 'await'
18
+ ]);
19
+ const PUNCTUATORS_BEFORE_REGEX = new Set('{}(,;[=:?!&|+-*%^~<>/');
20
+ const isRegexAllowed = (lastToken)=>{
21
+ if (!lastToken) return true;
22
+ if (KEYWORDS_BEFORE_REGEX.has(lastToken)) return true;
23
+ return 1 === lastToken.length && PUNCTUATORS_BEFORE_REGEX.has(lastToken);
24
+ };
25
+ const isSpecifierContext = (prev1, prev2, prev3)=>{
26
+ if (('from' === prev1 || 'import' === prev1) && '.' !== prev2) return true;
27
+ return '(' === prev1 && ('import' === prev2 || 'require' === prev2) && '.' !== prev3;
28
+ };
29
+ const skipRegexLiteral = (content, start)=>{
30
+ let i = start + 1;
31
+ let inClass = false;
32
+ while(i < content.length){
33
+ const ch = content[i];
34
+ if ('\\' === ch) {
35
+ i += 2;
36
+ continue;
37
+ }
38
+ if ('\n' === ch) break;
39
+ if ('[' === ch) inClass = true;
40
+ else if (']' === ch) inClass = false;
41
+ else if ('/' === ch && !inClass) {
42
+ i++;
43
+ while(i < content.length && IDENTIFIER_CHAR.test(content[i]))i++;
44
+ break;
45
+ }
46
+ i++;
47
+ }
48
+ return i;
49
+ };
50
+ const scanSpecifiers = (content)=>{
51
+ const specifiers = [];
52
+ const length = content.length;
53
+ const templateExpressionDepths = [];
54
+ let prev1 = '';
55
+ let prev2 = '';
56
+ let prev3 = '';
57
+ const pushToken = (token)=>{
58
+ prev3 = prev2;
59
+ prev2 = prev1;
60
+ prev1 = token;
61
+ };
62
+ let mode = 'code';
63
+ let i = 0;
64
+ while(i < length){
65
+ const ch = content[i];
66
+ if ('template' === mode) {
67
+ if ('\\' === ch) {
68
+ i += 2;
69
+ continue;
70
+ }
71
+ if ('`' === ch) {
72
+ mode = 'code';
73
+ pushToken('`');
74
+ i++;
75
+ continue;
76
+ }
77
+ if ('$' === ch && '{' === content[i + 1]) {
78
+ templateExpressionDepths.push(0);
79
+ mode = 'code';
80
+ pushToken('{');
81
+ i += 2;
82
+ continue;
83
+ }
84
+ i++;
85
+ continue;
86
+ }
87
+ if (WHITESPACE.test(ch)) {
88
+ i++;
89
+ continue;
90
+ }
91
+ if ('/' === ch) {
92
+ const next = content[i + 1];
93
+ if ('/' === next) {
94
+ const newline = content.indexOf('\n', i + 2);
95
+ i = -1 === newline ? length : newline + 1;
96
+ continue;
97
+ }
98
+ if ('*' === next) {
99
+ const end = content.indexOf('*/', i + 2);
100
+ i = -1 === end ? length : end + 2;
101
+ continue;
102
+ }
103
+ if (isRegexAllowed(prev1)) {
104
+ i = skipRegexLiteral(content, i);
105
+ pushToken('/regex/');
106
+ continue;
107
+ }
108
+ pushToken('/');
109
+ i++;
110
+ continue;
111
+ }
112
+ if ('`' === ch) {
113
+ mode = 'template';
114
+ i++;
115
+ continue;
116
+ }
117
+ if ('{' === ch) {
118
+ if (templateExpressionDepths.length > 0) templateExpressionDepths[templateExpressionDepths.length - 1]++;
119
+ pushToken('{');
120
+ i++;
121
+ continue;
122
+ }
123
+ if ('}' === ch) {
124
+ if (templateExpressionDepths.length > 0) {
125
+ const top = templateExpressionDepths.length - 1;
126
+ if (0 === templateExpressionDepths[top]) {
127
+ templateExpressionDepths.pop();
128
+ mode = 'template';
129
+ i++;
130
+ continue;
131
+ }
132
+ templateExpressionDepths[top]--;
133
+ }
134
+ pushToken('}');
135
+ i++;
136
+ continue;
137
+ }
138
+ if ('"' === ch || "'" === ch) {
139
+ const start = i;
140
+ let j = i + 1;
141
+ let terminated = false;
142
+ while(j < length){
143
+ const sch = content[j];
144
+ if ('\\' === sch) {
145
+ j += 2;
146
+ continue;
147
+ }
148
+ if (sch === ch) {
149
+ terminated = true;
150
+ j++;
151
+ break;
152
+ }
153
+ if ('\n' === sch) break;
154
+ j++;
155
+ }
156
+ if (terminated && isSpecifierContext(prev1, prev2, prev3)) specifiers.push({
157
+ start: start + 1,
158
+ end: j - 1,
159
+ value: content.slice(start + 1, j - 1)
160
+ });
161
+ pushToken('"string"');
162
+ i = j;
163
+ continue;
164
+ }
165
+ if (IDENTIFIER_CHAR.test(ch)) {
166
+ let j = i + 1;
167
+ while(j < length && IDENTIFIER_CHAR.test(content[j]))j++;
168
+ pushToken(content.slice(i, j));
169
+ i = j;
170
+ continue;
171
+ }
172
+ pushToken(ch);
173
+ i++;
174
+ }
175
+ return specifiers;
176
+ };
177
+ const rewriteImportSpecifiers = (content, rewrite)=>{
178
+ const specifiers = scanSpecifiers(content);
179
+ if (0 === specifiers.length) return {
180
+ content,
181
+ changed: false
182
+ };
183
+ let result = '';
184
+ let cursor = 0;
185
+ let changed = false;
186
+ for (const specifier of specifiers){
187
+ if (specifier.value.includes('\\')) continue;
188
+ const next = rewrite(specifier.value);
189
+ if (void 0 !== next && next !== specifier.value) {
190
+ changed = true;
191
+ result += content.slice(cursor, specifier.start) + next;
192
+ cursor = specifier.end;
193
+ }
194
+ }
195
+ if (!changed) return {
196
+ content,
197
+ changed: false
198
+ };
199
+ return {
200
+ content: result + content.slice(cursor),
201
+ changed: true
202
+ };
203
+ };
204
+ export { rewriteImportSpecifiers };
@@ -1,8 +1,8 @@
1
1
  import { fs, getAliasConfig, logger } from "@modern-js/utils";
2
2
  import { spawn } from "child_process";
3
3
  import path from "path";
4
+ import { rewriteImportSpecifiers } from "./importRewriter.mjs";
4
5
  import { createTsconfigPathsMatcher, getNotAliasedPath } from "./tsconfigPathsPlugin.mjs";
5
- const importSpecifierRE = /((?:from\s*|import\s*\(\s*|require\s*\(\s*)['"])([^'"]+)(['"])/g;
6
6
  const copyFiles = async (from, to, appDirectory)=>{
7
7
  if (await fs.pathExists(from)) {
8
8
  const relativePath = path.relative(appDirectory, from);
@@ -15,42 +15,58 @@ const copyFiles = async (from, to, appDirectory)=>{
15
15
  });
16
16
  }
17
17
  };
18
- const createResolvedTsgoConfig = async (appDirectory, tsconfigPath, distDir, sourceDirs)=>{
19
- const output = await runTsgo([
18
+ let resolvedConfigCount = 0;
19
+ const createResolvedTsgoConfig = async (appDirectory, tsconfigPath, distDir, sourceDirs, moduleType, tsgoBinPath)=>{
20
+ const tsconfigDir = path.dirname(tsconfigPath);
21
+ const output = await runTsgo(tsgoBinPath, [
20
22
  '--showConfig',
21
23
  '-p',
22
24
  tsconfigPath
23
25
  ], {
24
- cwd: path.dirname(tsconfigPath)
26
+ cwd: tsconfigDir
25
27
  });
26
28
  const config = JSON.parse(output.stdout);
27
29
  config.compilerOptions ??= {};
28
30
  config.compilerOptions.rootDir = appDirectory;
29
31
  config.compilerOptions.outDir = distDir;
30
- config.files = filterSourceFiles(appDirectory, sourceDirs, config.files);
32
+ config.files = filterSourceFiles(tsconfigDir, sourceDirs, config.files);
31
33
  delete config.include;
32
34
  delete config.compilerOptions.baseUrl;
33
35
  if ([
34
36
  'node',
35
37
  'node10'
36
38
  ].includes(String(config.compilerOptions.moduleResolution).toLowerCase())) delete config.compilerOptions.moduleResolution;
37
- const resolvedConfigPath = path.join(appDirectory, `.tsgo.${process.pid}.resolved.json`);
39
+ if ('module' !== moduleType) {
40
+ if ([
41
+ 'preserve',
42
+ 'esnext',
43
+ 'es2015',
44
+ 'es2020',
45
+ 'es2022',
46
+ 'es6'
47
+ ].includes(String(config.compilerOptions.module).toLowerCase())) {
48
+ config.compilerOptions.module = 'commonjs';
49
+ delete config.compilerOptions.moduleResolution;
50
+ }
51
+ config.compilerOptions.verbatimModuleSyntax = false;
52
+ }
53
+ const resolvedConfigPath = path.join(tsconfigDir, `.tsgo.${process.pid}.${resolvedConfigCount++}.resolved.json`);
38
54
  await fs.writeFile(resolvedConfigPath, JSON.stringify(config, null, 2));
39
55
  return {
40
56
  config,
41
57
  resolvedConfigPath
42
58
  };
43
59
  };
44
- const filterSourceFiles = (appDirectory, sourceDirs, files = [])=>{
60
+ const filterSourceFiles = (tsconfigDir, sourceDirs, files = [])=>{
45
61
  const sourcePosixPaths = sourceDirs.map((sourceDir)=>sourceDir.split(path.sep).join(path.posix.sep));
46
62
  return files.filter((fileName)=>{
47
- const absoluteFileName = path.resolve(appDirectory, fileName).split(path.sep).join(path.posix.sep);
63
+ const absoluteFileName = path.resolve(tsconfigDir, fileName).split(path.sep).join(path.posix.sep);
48
64
  return fileName.endsWith('.d.ts') || sourcePosixPaths.some((sourceDir)=>absoluteFileName.includes(sourceDir));
49
65
  });
50
66
  };
51
- const runTsgo = (args, options)=>new Promise((resolve, reject)=>{
67
+ const runTsgo = (tsgoBinPath, args, options)=>new Promise((resolve, reject)=>{
52
68
  const child = spawn(process.execPath, [
53
- getTsgoBinPath(),
69
+ tsgoBinPath,
54
70
  ...args
55
71
  ], {
56
72
  cwd: options.cwd,
@@ -79,14 +95,51 @@ const runTsgo = (args, options)=>new Promise((resolve, reject)=>{
79
95
  resolve(result);
80
96
  });
81
97
  });
82
- const getTsgoBinPath = ()=>path.join(path.dirname(require.resolve("@typescript/native-preview/package.json")), 'bin/tsgo.js');
98
+ const getTsgoBinPath = (appDirectory, resolvePaths = [
99
+ appDirectory,
100
+ __dirname
101
+ ])=>{
102
+ try {
103
+ const pkgPath = require.resolve("@typescript/native-preview/package.json", {
104
+ paths: resolvePaths
105
+ });
106
+ return path.join(path.dirname(pkgPath), 'bin/tsgo.js');
107
+ } catch {
108
+ throw new Error('tsgo could not be found! Please install "@typescript/native-preview" in your project to compile BFF/server code.');
109
+ }
110
+ };
111
+ const OUTPUT_SOURCE_EXTENSIONS = {
112
+ '.js': [
113
+ '.ts',
114
+ '.tsx',
115
+ '.js',
116
+ '.jsx'
117
+ ],
118
+ '.mjs': [
119
+ '.mts',
120
+ '.mjs'
121
+ ],
122
+ '.cjs': [
123
+ '.cts',
124
+ '.cjs'
125
+ ]
126
+ };
83
127
  const getSourceFileForOutput = (appDirectory, distDir, outputFile)=>{
84
128
  const relativeOutput = path.relative(distDir, outputFile);
85
129
  const parsed = path.parse(relativeOutput);
86
130
  const sourceBase = path.join(appDirectory, parsed.dir, parsed.name);
87
- return findExistingSource(`${sourceBase}.ts`) || findExistingSource(`${sourceBase}.tsx`) || findExistingSource(`${sourceBase}.js`) || findExistingSource(`${sourceBase}.jsx`);
131
+ const extensions = OUTPUT_SOURCE_EXTENSIONS[parsed.ext] ?? OUTPUT_SOURCE_EXTENSIONS['.js'];
132
+ for (const extension of extensions){
133
+ const candidate = `${sourceBase}${extension}`;
134
+ if (fs.existsSync(candidate)) return candidate;
135
+ }
136
+ };
137
+ const sourceMappingUrlRE = /^\/\/[#@] sourceMappingURL=.*$/gm;
138
+ const dropStaleSourceMap = async (outputFile, content)=>{
139
+ const mapFile = `${outputFile}.map`;
140
+ if (await fs.pathExists(mapFile)) await fs.remove(mapFile);
141
+ return content.replace(sourceMappingUrlRE, '');
88
142
  };
89
- const findExistingSource = (filePath)=>fs.existsSync(filePath) ? filePath : void 0;
90
143
  const rewriteOutputSpecifiers = async (appDirectory, distDir, baseUrl, paths, moduleType)=>{
91
144
  if (0 === Object.keys(paths).length || !await fs.pathExists(distDir)) return;
92
145
  const matcher = createTsconfigPathsMatcher(baseUrl, paths);
@@ -96,14 +149,8 @@ const rewriteOutputSpecifiers = async (appDirectory, distDir, baseUrl, paths, mo
96
149
  const sourceFile = getSourceFileForOutput(appDirectory, distDir, file);
97
150
  if (!sourceFile) return;
98
151
  const content = await fs.readFile(file, 'utf8');
99
- let changed = false;
100
- const rewritten = content.replace(importSpecifierRE, (match, prefix, specifier, suffix)=>{
101
- const nextSpecifier = getNotAliasedPath(sourceFile, matcher, specifier, moduleType);
102
- if (!nextSpecifier || nextSpecifier === specifier) return match;
103
- changed = true;
104
- return `${prefix}${nextSpecifier}${suffix}`;
105
- });
106
- if (changed) await fs.writeFile(file, rewritten);
152
+ const { content: rewritten, changed } = rewriteImportSpecifiers(content, (specifier)=>getNotAliasedPath(sourceFile, matcher, specifier, moduleType));
153
+ if (changed) await fs.writeFile(file, await dropStaleSourceMap(file, rewritten));
107
154
  }));
108
155
  };
109
156
  const collectOutputFiles = async (dir)=>{
@@ -129,24 +176,34 @@ const compileByTs = async (appDirectory, config, compileOptions)=>{
129
176
  tsconfigPath
130
177
  });
131
178
  const { paths = {}, absoluteBaseUrl = './' } = aliasOption;
132
- const { config: tsgoConfig, resolvedConfigPath } = await createResolvedTsgoConfig(appDirectory, tsconfigPath, distDir, sourceDirs);
133
- const result = await runTsgo([
134
- '-p',
135
- resolvedConfigPath
136
- ], {
137
- cwd: appDirectory,
138
- reject: false
139
- });
140
- await fs.remove(resolvedConfigPath);
179
+ const tsgoBinPath = getTsgoBinPath(appDirectory);
180
+ const { config: tsgoConfig, resolvedConfigPath } = await createResolvedTsgoConfig(appDirectory, tsconfigPath, distDir, sourceDirs, compileOptions.moduleType, tsgoBinPath);
181
+ let result;
182
+ try {
183
+ result = await runTsgo(tsgoBinPath, [
184
+ '-p',
185
+ resolvedConfigPath
186
+ ], {
187
+ cwd: appDirectory,
188
+ reject: false
189
+ });
190
+ } finally{
191
+ await fs.remove(resolvedConfigPath);
192
+ }
141
193
  if (result.stderr) logger.error(result.stderr);
142
194
  if (result.stdout) logger.info(result.stdout);
143
195
  if (0 !== result.code) {
144
196
  const noEmitOnError = tsgoConfig.compilerOptions?.noEmitOnError;
145
- if (void 0 === noEmitOnError || true === noEmitOnError) if (compileOptions.throwErrorInsteadOfExit) logger.error('TS-Go compilation failed');
146
- else process.exit(1);
197
+ if (void 0 === noEmitOnError || true === noEmitOnError) if (compileOptions.throwErrorInsteadOfExit) {
198
+ logger.error('TS-Go compilation failed');
199
+ throw new Error([
200
+ `TS-Go compilation failed with exit code ${result.code}.`,
201
+ result.stderr.trim() || result.stdout.trim()
202
+ ].filter(Boolean).join('\n'));
203
+ } else process.exit(1);
147
204
  }
148
205
  await rewriteOutputSpecifiers(appDirectory, distDir, absoluteBaseUrl, paths, compileOptions.moduleType);
149
206
  for (const source of sourceDirs)await copyFiles(source, distDir, appDirectory);
150
207
  logger.info("TS-Go compile succeed");
151
208
  };
152
- export { compileByTs };
209
+ export { compileByTs, createResolvedTsgoConfig, getTsgoBinPath, rewriteOutputSpecifiers };
@@ -0,0 +1,205 @@
1
+ import "node:module";
2
+ const IDENTIFIER_CHAR = /[A-Za-z0-9_$]/;
3
+ const WHITESPACE = /\s/;
4
+ const KEYWORDS_BEFORE_REGEX = new Set([
5
+ 'return',
6
+ 'typeof',
7
+ 'instanceof',
8
+ 'in',
9
+ 'of',
10
+ 'new',
11
+ 'delete',
12
+ 'void',
13
+ 'throw',
14
+ 'case',
15
+ 'do',
16
+ 'else',
17
+ 'yield',
18
+ 'await'
19
+ ]);
20
+ const PUNCTUATORS_BEFORE_REGEX = new Set('{}(,;[=:?!&|+-*%^~<>/');
21
+ const isRegexAllowed = (lastToken)=>{
22
+ if (!lastToken) return true;
23
+ if (KEYWORDS_BEFORE_REGEX.has(lastToken)) return true;
24
+ return 1 === lastToken.length && PUNCTUATORS_BEFORE_REGEX.has(lastToken);
25
+ };
26
+ const isSpecifierContext = (prev1, prev2, prev3)=>{
27
+ if (('from' === prev1 || 'import' === prev1) && '.' !== prev2) return true;
28
+ return '(' === prev1 && ('import' === prev2 || 'require' === prev2) && '.' !== prev3;
29
+ };
30
+ const skipRegexLiteral = (content, start)=>{
31
+ let i = start + 1;
32
+ let inClass = false;
33
+ while(i < content.length){
34
+ const ch = content[i];
35
+ if ('\\' === ch) {
36
+ i += 2;
37
+ continue;
38
+ }
39
+ if ('\n' === ch) break;
40
+ if ('[' === ch) inClass = true;
41
+ else if (']' === ch) inClass = false;
42
+ else if ('/' === ch && !inClass) {
43
+ i++;
44
+ while(i < content.length && IDENTIFIER_CHAR.test(content[i]))i++;
45
+ break;
46
+ }
47
+ i++;
48
+ }
49
+ return i;
50
+ };
51
+ const scanSpecifiers = (content)=>{
52
+ const specifiers = [];
53
+ const length = content.length;
54
+ const templateExpressionDepths = [];
55
+ let prev1 = '';
56
+ let prev2 = '';
57
+ let prev3 = '';
58
+ const pushToken = (token)=>{
59
+ prev3 = prev2;
60
+ prev2 = prev1;
61
+ prev1 = token;
62
+ };
63
+ let mode = 'code';
64
+ let i = 0;
65
+ while(i < length){
66
+ const ch = content[i];
67
+ if ('template' === mode) {
68
+ if ('\\' === ch) {
69
+ i += 2;
70
+ continue;
71
+ }
72
+ if ('`' === ch) {
73
+ mode = 'code';
74
+ pushToken('`');
75
+ i++;
76
+ continue;
77
+ }
78
+ if ('$' === ch && '{' === content[i + 1]) {
79
+ templateExpressionDepths.push(0);
80
+ mode = 'code';
81
+ pushToken('{');
82
+ i += 2;
83
+ continue;
84
+ }
85
+ i++;
86
+ continue;
87
+ }
88
+ if (WHITESPACE.test(ch)) {
89
+ i++;
90
+ continue;
91
+ }
92
+ if ('/' === ch) {
93
+ const next = content[i + 1];
94
+ if ('/' === next) {
95
+ const newline = content.indexOf('\n', i + 2);
96
+ i = -1 === newline ? length : newline + 1;
97
+ continue;
98
+ }
99
+ if ('*' === next) {
100
+ const end = content.indexOf('*/', i + 2);
101
+ i = -1 === end ? length : end + 2;
102
+ continue;
103
+ }
104
+ if (isRegexAllowed(prev1)) {
105
+ i = skipRegexLiteral(content, i);
106
+ pushToken('/regex/');
107
+ continue;
108
+ }
109
+ pushToken('/');
110
+ i++;
111
+ continue;
112
+ }
113
+ if ('`' === ch) {
114
+ mode = 'template';
115
+ i++;
116
+ continue;
117
+ }
118
+ if ('{' === ch) {
119
+ if (templateExpressionDepths.length > 0) templateExpressionDepths[templateExpressionDepths.length - 1]++;
120
+ pushToken('{');
121
+ i++;
122
+ continue;
123
+ }
124
+ if ('}' === ch) {
125
+ if (templateExpressionDepths.length > 0) {
126
+ const top = templateExpressionDepths.length - 1;
127
+ if (0 === templateExpressionDepths[top]) {
128
+ templateExpressionDepths.pop();
129
+ mode = 'template';
130
+ i++;
131
+ continue;
132
+ }
133
+ templateExpressionDepths[top]--;
134
+ }
135
+ pushToken('}');
136
+ i++;
137
+ continue;
138
+ }
139
+ if ('"' === ch || "'" === ch) {
140
+ const start = i;
141
+ let j = i + 1;
142
+ let terminated = false;
143
+ while(j < length){
144
+ const sch = content[j];
145
+ if ('\\' === sch) {
146
+ j += 2;
147
+ continue;
148
+ }
149
+ if (sch === ch) {
150
+ terminated = true;
151
+ j++;
152
+ break;
153
+ }
154
+ if ('\n' === sch) break;
155
+ j++;
156
+ }
157
+ if (terminated && isSpecifierContext(prev1, prev2, prev3)) specifiers.push({
158
+ start: start + 1,
159
+ end: j - 1,
160
+ value: content.slice(start + 1, j - 1)
161
+ });
162
+ pushToken('"string"');
163
+ i = j;
164
+ continue;
165
+ }
166
+ if (IDENTIFIER_CHAR.test(ch)) {
167
+ let j = i + 1;
168
+ while(j < length && IDENTIFIER_CHAR.test(content[j]))j++;
169
+ pushToken(content.slice(i, j));
170
+ i = j;
171
+ continue;
172
+ }
173
+ pushToken(ch);
174
+ i++;
175
+ }
176
+ return specifiers;
177
+ };
178
+ const rewriteImportSpecifiers = (content, rewrite)=>{
179
+ const specifiers = scanSpecifiers(content);
180
+ if (0 === specifiers.length) return {
181
+ content,
182
+ changed: false
183
+ };
184
+ let result = '';
185
+ let cursor = 0;
186
+ let changed = false;
187
+ for (const specifier of specifiers){
188
+ if (specifier.value.includes('\\')) continue;
189
+ const next = rewrite(specifier.value);
190
+ if (void 0 !== next && next !== specifier.value) {
191
+ changed = true;
192
+ result += content.slice(cursor, specifier.start) + next;
193
+ cursor = specifier.end;
194
+ }
195
+ }
196
+ if (!changed) return {
197
+ content,
198
+ changed: false
199
+ };
200
+ return {
201
+ content: result + content.slice(cursor),
202
+ changed: true
203
+ };
204
+ };
205
+ export { rewriteImportSpecifiers };