@bleedingdev/modern-js-server-utils 3.2.0-ultramodern.98 → 3.4.0-ultramodern.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.
@@ -3,8 +3,11 @@ const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(/*#__PURE__*/
3
3
  import { fs, getAliasConfig, logger } from "@modern-js/utils";
4
4
  import { spawn } from "child_process";
5
5
  import path from "path";
6
+ import { rewriteImportSpecifiers } from "./importRewriter.mjs";
6
7
  import { createTsconfigPathsMatcher, getNotAliasedPath } from "./tsconfigPathsPlugin.mjs";
7
- const importSpecifierRE = /((?:from\s*|import\s*\(\s*|require\s*\(\s*)['"])([^'"]+)(['"])/g;
8
+ import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
9
+ import { dirname as __rspack_dirname } from "node:path";
10
+ var typescript_dirname = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
8
11
  const copyFiles = async (from, to, appDirectory)=>{
9
12
  if (await fs.pathExists(from)) {
10
13
  const relativePath = path.relative(appDirectory, from);
@@ -17,42 +20,55 @@ const copyFiles = async (from, to, appDirectory)=>{
17
20
  });
18
21
  }
19
22
  };
20
- const createResolvedTsgoConfig = async (appDirectory, tsconfigPath, distDir, sourceDirs)=>{
21
- const output = await runTsgo([
23
+ let resolvedConfigCount = 0;
24
+ const createResolvedTsgoConfig = async (appDirectory, tsconfigPath, distDir, sourceDirs, moduleType, tsgoBinPath)=>{
25
+ const tsconfigDir = path.dirname(tsconfigPath);
26
+ const output = await runTsgo(tsgoBinPath, [
22
27
  '--showConfig',
23
28
  '-p',
24
29
  tsconfigPath
25
30
  ], {
26
- cwd: path.dirname(tsconfigPath)
31
+ cwd: tsconfigDir
27
32
  });
28
33
  const config = JSON.parse(output.stdout);
29
34
  config.compilerOptions ??= {};
30
35
  config.compilerOptions.rootDir = appDirectory;
31
36
  config.compilerOptions.outDir = distDir;
32
- config.files = filterSourceFiles(appDirectory, sourceDirs, config.files);
37
+ config.files = filterSourceFiles(tsconfigDir, sourceDirs, config.files);
33
38
  delete config.include;
34
39
  delete config.compilerOptions.baseUrl;
35
40
  if ([
36
41
  'node',
37
42
  'node10'
38
43
  ].includes(String(config.compilerOptions.moduleResolution).toLowerCase())) delete config.compilerOptions.moduleResolution;
39
- const resolvedConfigPath = path.join(appDirectory, `.tsgo.${process.pid}.resolved.json`);
44
+ if ('module' !== moduleType && [
45
+ 'preserve',
46
+ 'esnext',
47
+ 'es2015',
48
+ 'es2020',
49
+ 'es2022',
50
+ 'es6'
51
+ ].includes(String(config.compilerOptions.module).toLowerCase())) {
52
+ config.compilerOptions.module = 'commonjs';
53
+ delete config.compilerOptions.moduleResolution;
54
+ }
55
+ const resolvedConfigPath = path.join(tsconfigDir, `.tsgo.${process.pid}.${resolvedConfigCount++}.resolved.json`);
40
56
  await fs.writeFile(resolvedConfigPath, JSON.stringify(config, null, 2));
41
57
  return {
42
58
  config,
43
59
  resolvedConfigPath
44
60
  };
45
61
  };
46
- const filterSourceFiles = (appDirectory, sourceDirs, files = [])=>{
62
+ const filterSourceFiles = (tsconfigDir, sourceDirs, files = [])=>{
47
63
  const sourcePosixPaths = sourceDirs.map((sourceDir)=>sourceDir.split(path.sep).join(path.posix.sep));
48
64
  return files.filter((fileName)=>{
49
- const absoluteFileName = path.resolve(appDirectory, fileName).split(path.sep).join(path.posix.sep);
65
+ const absoluteFileName = path.resolve(tsconfigDir, fileName).split(path.sep).join(path.posix.sep);
50
66
  return fileName.endsWith('.d.ts') || sourcePosixPaths.some((sourceDir)=>absoluteFileName.includes(sourceDir));
51
67
  });
52
68
  };
53
- const runTsgo = (args, options)=>new Promise((resolve, reject)=>{
69
+ const runTsgo = (tsgoBinPath, args, options)=>new Promise((resolve, reject)=>{
54
70
  const child = spawn(process.execPath, [
55
- getTsgoBinPath(),
71
+ tsgoBinPath,
56
72
  ...args
57
73
  ], {
58
74
  cwd: options.cwd,
@@ -81,14 +97,51 @@ const runTsgo = (args, options)=>new Promise((resolve, reject)=>{
81
97
  resolve(result);
82
98
  });
83
99
  });
84
- const getTsgoBinPath = ()=>path.join(path.dirname(require.resolve("@typescript/native-preview/package.json")), 'bin/tsgo.js');
100
+ const getTsgoBinPath = (appDirectory, resolvePaths = [
101
+ appDirectory,
102
+ typescript_dirname
103
+ ])=>{
104
+ try {
105
+ const pkgPath = require.resolve("@typescript/native-preview/package.json", {
106
+ paths: resolvePaths
107
+ });
108
+ return path.join(path.dirname(pkgPath), 'bin/tsgo.js');
109
+ } catch {
110
+ throw new Error('tsgo could not be found! Please install "@typescript/native-preview" in your project to compile BFF/server code.');
111
+ }
112
+ };
113
+ const OUTPUT_SOURCE_EXTENSIONS = {
114
+ '.js': [
115
+ '.ts',
116
+ '.tsx',
117
+ '.js',
118
+ '.jsx'
119
+ ],
120
+ '.mjs': [
121
+ '.mts',
122
+ '.mjs'
123
+ ],
124
+ '.cjs': [
125
+ '.cts',
126
+ '.cjs'
127
+ ]
128
+ };
85
129
  const getSourceFileForOutput = (appDirectory, distDir, outputFile)=>{
86
130
  const relativeOutput = path.relative(distDir, outputFile);
87
131
  const parsed = path.parse(relativeOutput);
88
132
  const sourceBase = path.join(appDirectory, parsed.dir, parsed.name);
89
- return findExistingSource(`${sourceBase}.ts`) || findExistingSource(`${sourceBase}.tsx`) || findExistingSource(`${sourceBase}.js`) || findExistingSource(`${sourceBase}.jsx`);
133
+ const extensions = OUTPUT_SOURCE_EXTENSIONS[parsed.ext] ?? OUTPUT_SOURCE_EXTENSIONS['.js'];
134
+ for (const extension of extensions){
135
+ const candidate = `${sourceBase}${extension}`;
136
+ if (fs.existsSync(candidate)) return candidate;
137
+ }
138
+ };
139
+ const sourceMappingUrlRE = /^\/\/[#@] sourceMappingURL=.*$/gm;
140
+ const dropStaleSourceMap = async (outputFile, content)=>{
141
+ const mapFile = `${outputFile}.map`;
142
+ if (await fs.pathExists(mapFile)) await fs.remove(mapFile);
143
+ return content.replace(sourceMappingUrlRE, '');
90
144
  };
91
- const findExistingSource = (filePath)=>fs.existsSync(filePath) ? filePath : void 0;
92
145
  const rewriteOutputSpecifiers = async (appDirectory, distDir, baseUrl, paths, moduleType)=>{
93
146
  if (0 === Object.keys(paths).length || !await fs.pathExists(distDir)) return;
94
147
  const matcher = createTsconfigPathsMatcher(baseUrl, paths);
@@ -98,14 +151,8 @@ const rewriteOutputSpecifiers = async (appDirectory, distDir, baseUrl, paths, mo
98
151
  const sourceFile = getSourceFileForOutput(appDirectory, distDir, file);
99
152
  if (!sourceFile) return;
100
153
  const content = await fs.readFile(file, 'utf8');
101
- let changed = false;
102
- const rewritten = content.replace(importSpecifierRE, (match, prefix, specifier, suffix)=>{
103
- const nextSpecifier = getNotAliasedPath(sourceFile, matcher, specifier, moduleType);
104
- if (!nextSpecifier || nextSpecifier === specifier) return match;
105
- changed = true;
106
- return `${prefix}${nextSpecifier}${suffix}`;
107
- });
108
- if (changed) await fs.writeFile(file, rewritten);
154
+ const { content: rewritten, changed } = rewriteImportSpecifiers(content, (specifier)=>getNotAliasedPath(sourceFile, matcher, specifier, moduleType));
155
+ if (changed) await fs.writeFile(file, await dropStaleSourceMap(file, rewritten));
109
156
  }));
110
157
  };
111
158
  const collectOutputFiles = async (dir)=>{
@@ -131,24 +178,34 @@ const compileByTs = async (appDirectory, config, compileOptions)=>{
131
178
  tsconfigPath
132
179
  });
133
180
  const { paths = {}, absoluteBaseUrl = './' } = aliasOption;
134
- const { config: tsgoConfig, resolvedConfigPath } = await createResolvedTsgoConfig(appDirectory, tsconfigPath, distDir, sourceDirs);
135
- const result = await runTsgo([
136
- '-p',
137
- resolvedConfigPath
138
- ], {
139
- cwd: appDirectory,
140
- reject: false
141
- });
142
- await fs.remove(resolvedConfigPath);
181
+ const tsgoBinPath = getTsgoBinPath(appDirectory);
182
+ const { config: tsgoConfig, resolvedConfigPath } = await createResolvedTsgoConfig(appDirectory, tsconfigPath, distDir, sourceDirs, compileOptions.moduleType, tsgoBinPath);
183
+ let result;
184
+ try {
185
+ result = await runTsgo(tsgoBinPath, [
186
+ '-p',
187
+ resolvedConfigPath
188
+ ], {
189
+ cwd: appDirectory,
190
+ reject: false
191
+ });
192
+ } finally{
193
+ await fs.remove(resolvedConfigPath);
194
+ }
143
195
  if (result.stderr) logger.error(result.stderr);
144
196
  if (result.stdout) logger.info(result.stdout);
145
197
  if (0 !== result.code) {
146
198
  const noEmitOnError = tsgoConfig.compilerOptions?.noEmitOnError;
147
- if (void 0 === noEmitOnError || true === noEmitOnError) if (compileOptions.throwErrorInsteadOfExit) logger.error('TS-Go compilation failed');
148
- else process.exit(1);
199
+ if (void 0 === noEmitOnError || true === noEmitOnError) if (compileOptions.throwErrorInsteadOfExit) {
200
+ logger.error('TS-Go compilation failed');
201
+ throw new Error([
202
+ `TS-Go compilation failed with exit code ${result.code}.`,
203
+ result.stderr.trim() || result.stdout.trim()
204
+ ].filter(Boolean).join('\n'));
205
+ } else process.exit(1);
149
206
  }
150
207
  await rewriteOutputSpecifiers(appDirectory, distDir, absoluteBaseUrl, paths, compileOptions.moduleType);
151
208
  for (const source of sourceDirs)await copyFiles(source, distDir, appDirectory);
152
209
  logger.info("TS-Go compile succeed");
153
210
  };
154
- export { compileByTs };
211
+ export { compileByTs, createResolvedTsgoConfig, getTsgoBinPath, rewriteOutputSpecifiers };
@@ -0,0 +1,12 @@
1
+ export type SpecifierRewrite = (specifier: string) => string | undefined;
2
+ /**
3
+ * Rewrite the import/export/require specifiers of emitted JavaScript.
4
+ *
5
+ * Specifiers whose contents contain escape sequences are left untouched (the
6
+ * raw source slice would not round-trip), which never happens for the
7
+ * compiler-emitted relative/alias specifiers this is used on.
8
+ */
9
+ export declare const rewriteImportSpecifiers: (content: string, rewrite: SpecifierRewrite) => {
10
+ content: string;
11
+ changed: boolean;
12
+ };
@@ -1,2 +1,21 @@
1
1
  import type { CompileFunc } from '../../common';
2
+ type TsgoConfig = {
3
+ compilerOptions?: {
4
+ baseUrl?: unknown;
5
+ module?: string;
6
+ moduleResolution?: string;
7
+ noEmitOnError?: boolean;
8
+ outDir?: string;
9
+ rootDir?: string;
10
+ };
11
+ files?: string[];
12
+ include?: string[];
13
+ };
14
+ export declare const createResolvedTsgoConfig: (appDirectory: string, tsconfigPath: string, distDir: string, sourceDirs: string[], moduleType: 'module' | 'commonjs' | undefined, tsgoBinPath: string) => Promise<{
15
+ config: TsgoConfig;
16
+ resolvedConfigPath: string;
17
+ }>;
18
+ export declare const getTsgoBinPath: (appDirectory: string, resolvePaths?: string[]) => string;
19
+ export declare const rewriteOutputSpecifiers: (appDirectory: string, distDir: string, baseUrl: string, paths: Record<string, string[] | string>, moduleType?: 'module' | 'commonjs') => Promise<void>;
2
20
  export declare const compileByTs: CompileFunc;
21
+ export {};
@@ -1,3 +1,3 @@
1
1
  import type { MatchPath } from '@modern-js/utils/tsconfig-paths';
2
2
  export declare const createTsconfigPathsMatcher: (baseUrl: string, paths: Record<string, string[] | string>) => MatchPath | undefined;
3
- export declare function getNotAliasedPath(sourceFile: string, matcher: MatchPath, text: string, moduleType?: 'module' | 'commonjs'): any;
3
+ export declare function getNotAliasedPath(sourceFile: string, matcher: MatchPath, text: string, moduleType?: 'module' | 'commonjs'): string | undefined;
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "modern",
18
18
  "modern.js"
19
19
  ],
20
- "version": "3.2.0-ultramodern.98",
20
+ "version": "3.4.0-ultramodern.0",
21
21
  "types": "./dist/types/index.d.ts",
22
22
  "main": "./dist/cjs/index.js",
23
23
  "exports": {
@@ -40,14 +40,22 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@swc/helpers": "^0.5.23",
43
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.2.0-ultramodern.98"
43
+ "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.4.0-ultramodern.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@rslib/core": "0.21.5",
47
- "@types/node": "^25.9.1",
48
- "@typescript/native-preview": "7.0.0-dev.20260527.2",
49
- "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.2.0-ultramodern.98",
50
- "@scripts/rstest-config": "2.66.0"
46
+ "@rslib/core": "0.23.0",
47
+ "@types/node": "^26.0.0",
48
+ "@typescript/native-preview": "7.0.0-dev.20260624.1",
49
+ "@scripts/rstest-config": "2.66.0",
50
+ "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.4.0-ultramodern.0"
51
+ },
52
+ "peerDependencies": {
53
+ "@typescript/native-preview": ">=7.0.0-dev.20260624.1"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "@typescript/native-preview": {
57
+ "optional": true
58
+ }
51
59
  },
52
60
  "sideEffects": false,
53
61
  "publishConfig": {