@modern-js/module-tools 1.3.0 → 1.4.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/js/modern/features/dev/index.js +1 -1
  3. package/dist/js/node/features/dev/index.js +1 -1
  4. package/dist/types/index.d.ts +2 -0
  5. package/lib/types.d.ts +0 -10
  6. package/package.json +16 -17
  7. package/tests/dev-feature.test.ts +17 -1
  8. package/src/.eslintrc.json +0 -5
  9. package/src/cli/build.ts +0 -39
  10. package/src/cli/dev.ts +0 -24
  11. package/src/cli/index.ts +0 -3
  12. package/src/cli/new.ts +0 -32
  13. package/src/commands/build.ts +0 -74
  14. package/src/commands/dev.ts +0 -52
  15. package/src/commands/index.ts +0 -2
  16. package/src/features/build/build-platform.ts +0 -83
  17. package/src/features/build/build-watch.ts +0 -99
  18. package/src/features/build/build.ts +0 -111
  19. package/src/features/build/constants.ts +0 -52
  20. package/src/features/build/index.ts +0 -54
  21. package/src/features/build/logger/index.ts +0 -2
  22. package/src/features/build/logger/logText.ts +0 -80
  23. package/src/features/build/logger/loggerManager.ts +0 -132
  24. package/src/features/build/utils.ts +0 -235
  25. package/src/features/dev/index.ts +0 -74
  26. package/src/index.ts +0 -55
  27. package/src/locale/en.ts +0 -21
  28. package/src/locale/index.ts +0 -15
  29. package/src/locale/zh.ts +0 -21
  30. package/src/schema/index.ts +0 -4
  31. package/src/schema/output.ts +0 -41
  32. package/src/schema/schema.d.ts +0 -13
  33. package/src/schema/source.ts +0 -16
  34. package/src/tasks/build-source-code.ts +0 -234
  35. package/src/tasks/build-style.ts +0 -194
  36. package/src/tasks/build-watch-source-code.ts +0 -186
  37. package/src/tasks/build-watch-style.ts +0 -271
  38. package/src/tasks/constants.ts +0 -1
  39. package/src/tasks/copy-assets.ts +0 -123
  40. package/src/tasks/generator-dts.ts +0 -277
  41. package/src/type.d.ts +0 -1
  42. package/src/types.ts +0 -65
  43. package/src/utils/babel.ts +0 -104
  44. package/src/utils/color.ts +0 -3
  45. package/src/utils/copy.ts +0 -71
  46. package/src/utils/init-env.ts +0 -31
  47. package/src/utils/json.ts +0 -13
  48. package/src/utils/language.ts +0 -9
  49. package/src/utils/logger.ts +0 -141
  50. package/src/utils/readline.ts +0 -28
  51. package/src/utils/tsconfig.ts +0 -37
  52. package/src/utils/tspaths-transform/constants.ts +0 -19
  53. package/src/utils/tspaths-transform/index.ts +0 -139
  54. package/src/utils/tspaths-transform/utils.ts +0 -25
  55. package/src/utils/valide.ts +0 -37
@@ -1,277 +0,0 @@
1
- import type { ChildProcess } from 'child_process';
2
- import * as path from 'path';
3
- import * as os from 'os';
4
- import { Import, fs } from '@modern-js/utils';
5
- import type { NormalizedConfig, CoreOptions } from '@modern-js/core';
6
- import type { ITsconfig } from '../types';
7
-
8
- const tsPathsTransform: typeof import('../utils/tspaths-transform') =
9
- Import.lazy('../utils/tspaths-transform', require);
10
- const babel: typeof import('../utils/babel') = Import.lazy(
11
- '../utils/babel',
12
- require,
13
- );
14
- const constants: typeof import('./constants') = Import.lazy(
15
- './constants',
16
- require,
17
- );
18
-
19
- const core: typeof import('@modern-js/core') = Import.lazy(
20
- '@modern-js/core',
21
- require,
22
- );
23
-
24
- const execa: typeof import('execa') = Import.lazy('execa', require);
25
- const JSON5: typeof import('json5') = Import.lazy('json5', require);
26
- const argv: typeof import('process.argv').default = Import.lazy(
27
- 'process.argv',
28
- require,
29
- );
30
- const deepMerge: typeof import('lodash.merge') = Import.lazy(
31
- 'lodash.merge',
32
- require,
33
- );
34
- const glob: typeof import('glob') = Import.lazy('glob', require);
35
-
36
- let removeTsconfigPath = '';
37
-
38
- const generatorTsConfig = (
39
- projectTsconfig: ITsconfig,
40
- {
41
- appDirectory,
42
- distDir,
43
- sourceDir = 'src',
44
- }: { appDirectory: string; distDir: string; sourceDir?: string },
45
- ) => {
46
- const tempPath = path.resolve(appDirectory, './node_modules');
47
- const resolvePath = path.relative(tempPath, appDirectory);
48
- // const rootDir = projectTsconfig.compilerOptions?.rootDir
49
- // ? path.join(resolvePath, projectTsconfig.compilerOptions?.rootDir)
50
- // : resolvePath;
51
- // 目前限制 rootDir 的路径为 sourceDir
52
- const rootDir = path.join(resolvePath, sourceDir);
53
- const baseUrl = projectTsconfig.compilerOptions?.baseUrl
54
- ? path.join(appDirectory, projectTsconfig.compilerOptions?.baseUrl)
55
- : appDirectory;
56
- // if include = ['src'], final include should be ['../src']
57
- const include = projectTsconfig.include?.map(includePath =>
58
- path.join(resolvePath, includePath),
59
- );
60
- const exclude = projectTsconfig.exclude?.map(excludePath =>
61
- path.join(resolvePath, excludePath),
62
- );
63
-
64
- const resetConfig: ITsconfig = {
65
- compilerOptions: {
66
- rootDir,
67
- baseUrl,
68
- // Ensure that .d.ts files are created by tsc, but not .js files
69
- declaration: true,
70
- emitDeclarationOnly: true,
71
- outDir: distDir,
72
- },
73
- include,
74
- exclude,
75
- };
76
-
77
- const recommendOption = {
78
- // Ensure that Babel can safely transpile files in the TypeScript project
79
- compilerOptions: {
80
- isolatedModules: true,
81
- },
82
- };
83
-
84
- const tempTsconfigPath = path.join(tempPath, constants.tempTsconfigName);
85
- fs.ensureFileSync(tempTsconfigPath);
86
- fs.writeJSONSync(
87
- tempTsconfigPath,
88
- deepMerge(
89
- recommendOption,
90
- projectTsconfig,
91
- // 此处是必须要覆盖用户默认配置
92
- resetConfig,
93
- ),
94
- );
95
- return tempTsconfigPath;
96
- };
97
-
98
- const getProjectTsconfig = (tsconfigPath: string | undefined): ITsconfig => {
99
- if (!tsconfigPath || !fs.existsSync(tsconfigPath)) {
100
- return {};
101
- }
102
-
103
- return JSON5.parse(fs.readFileSync(tsconfigPath, 'utf-8'));
104
- };
105
-
106
- const resolveLog = (
107
- childProgress: ChildProcess,
108
- { tsCheck = false, watch = false } = {},
109
- ) => {
110
- /**
111
- * tsc 所有的log信息都是从stdout data 事件中获取
112
- * 正常模式下,如果有报错信息,交给 resolveLog 后面的逻辑来处理
113
- * watch 模式下,则使用这里的信息
114
- */
115
- childProgress.stdout?.on('data', data => {
116
- if (!tsCheck) {
117
- return;
118
- }
119
- if (watch) {
120
- console.info(data.toString());
121
- }
122
- });
123
- // 正常以下内容都不会触发,因为tsc 不会产生以下类型的log信息,不过防止意外情况
124
- childProgress.stdout?.on('error', error => {
125
- console.error(error.message);
126
- });
127
- childProgress.stderr?.on('data', chunk => {
128
- console.error(chunk.toString());
129
- });
130
- };
131
-
132
- interface IGeneratorConfig {
133
- sourceDirName?: string;
134
- srcDir: string;
135
- distDir: string;
136
- projectData: {
137
- appDirectory: string;
138
- };
139
- tsconfigPath?: string;
140
- tsCheck?: boolean;
141
- watch?: boolean;
142
- }
143
-
144
- const generatorDts = async (_: NormalizedConfig, config: IGeneratorConfig) => {
145
- const {
146
- tsconfigPath,
147
- distDir,
148
- sourceDirName = 'src',
149
- projectData: { appDirectory },
150
- tsCheck = false,
151
- watch = false,
152
- } = config;
153
-
154
- const userTsconfig = getProjectTsconfig(tsconfigPath);
155
- const willDeleteTsconfigPath = generatorTsConfig(userTsconfig, {
156
- appDirectory,
157
- distDir,
158
- sourceDir: sourceDirName,
159
- });
160
- removeTsconfigPath = willDeleteTsconfigPath;
161
- const tscBinFile = path.join(appDirectory, './node_modules/.bin/tsc');
162
- const watchParams = watch ? ['-w'] : [];
163
- const childProgress = execa(
164
- tscBinFile,
165
- ['-p', willDeleteTsconfigPath, ...watchParams],
166
- {
167
- stdio: 'pipe',
168
- cwd: appDirectory,
169
- },
170
- );
171
- resolveLog(childProgress, { tsCheck, watch });
172
- try {
173
- await childProgress;
174
- console.info('[Tsc Compiler]: Successfully');
175
- } catch (e) {
176
- if (!tsCheck) {
177
- console.warn(
178
- `There are some type issues, which can be checked by configuring 'source.enableTsChecker = true' ${os.EOL} in modern.config.js`,
179
- );
180
- } else {
181
- const isRecord = (input: any): input is Record<string, any> =>
182
- typeof input === 'object';
183
- // 通过使用 execa,可以将tsc 的 data 类型的报错信息变为异常错误信息
184
- if (isRecord(e)) {
185
- console.error(e.stdout);
186
- }
187
- }
188
- }
189
- fs.removeSync(willDeleteTsconfigPath);
190
- };
191
-
192
- const resolveAlias = (
193
- modernConfig: NormalizedConfig,
194
- config: IGeneratorConfig,
195
- watchFilenames: string[] = [],
196
- ) => {
197
- const { output } = modernConfig;
198
- const defaultPaths = { '@': ['./src'] };
199
- const dtsDistPath = `${config.distDir}/**/*.d.ts`;
200
- const dtsFilenames =
201
- watchFilenames.length > 0
202
- ? watchFilenames
203
- : glob.sync(dtsDistPath, { absolute: true });
204
- const alias = babel.getFinalAlias(modernConfig, {
205
- appDirectory: config.projectData.appDirectory,
206
- tsconfigPath:
207
- config.tsconfigPath ||
208
- path.join(config.projectData.appDirectory, './tsconfig.json'),
209
- sourceAbsDir: config.distDir,
210
- });
211
- const mergedPaths = alias.isTsPath
212
- ? alias.paths || {}
213
- : { ...defaultPaths, ...(alias.paths || {}) };
214
- const result = tsPathsTransform.transformDtsAlias({
215
- filenames: dtsFilenames,
216
- baseUrl: path.join(config.projectData.appDirectory, output.path || 'dist'),
217
- paths: mergedPaths,
218
- });
219
- for (const r of result) {
220
- fs.writeFileSync(r.path, r.content);
221
- }
222
- };
223
-
224
- interface ITaskConfig {
225
- srcDir: string;
226
- sourceDirName: string;
227
- distDir: string;
228
- appDirectory: string;
229
- tsconfigPath?: string;
230
- tsCheck?: boolean;
231
- watch?: boolean;
232
- debug?: boolean;
233
- }
234
-
235
- const taskMain = async ({
236
- modernConfig,
237
- }: {
238
- modernConfig: NormalizedConfig;
239
- }) => {
240
- const processArgv = argv(process.argv.slice(2));
241
- const config = processArgv<ITaskConfig>({
242
- appDirectory: process.cwd(),
243
- srcDir: 'src',
244
- distDir: 'dist/types',
245
- tsconfigPath: './tsconfig.json',
246
- sourceDirName: 'src',
247
- });
248
-
249
- const option = {
250
- srcDir: config.srcDir,
251
- distDir: config.distDir,
252
- projectData: { appDirectory: config.appDirectory },
253
- tsconfigPath: config.tsconfigPath,
254
- watch: config.watch,
255
- tsCheck: config.tsCheck,
256
- sourceDirName: config.sourceDirName,
257
- };
258
- await generatorDts(modernConfig, option);
259
- // TODO: watch 模式下无法转换
260
- resolveAlias(modernConfig, option);
261
- };
262
-
263
- (async () => {
264
- let options: CoreOptions | undefined;
265
- if (process.env.CORE_INIT_OPTION_FILE) {
266
- ({ options } = require(process.env.CORE_INIT_OPTION_FILE));
267
- }
268
- const { resolved } = await core.cli.init([], options);
269
- await core.manager.run(async () => {
270
- try {
271
- await taskMain({ modernConfig: resolved });
272
- } catch (e: any) {
273
- console.error(e.message);
274
- fs.removeSync(removeTsconfigPath);
275
- }
276
- });
277
- })();
package/src/type.d.ts DELETED
@@ -1 +0,0 @@
1
- /// <reference types="@modern-js/module-tools-hooks" />
package/src/types.ts DELETED
@@ -1,65 +0,0 @@
1
- import type { OutputConfig, SourceConfig } from '@modern-js/core/config';
2
- import type { ImportStyleType } from '@modern-js/babel-preset-module';
3
- import type { NormalizedConfig } from '@modern-js/core';
4
- import type { LoggerText } from './features/build/logger/logText';
5
- import type { Platform } from './features/build/build-platform';
6
-
7
- export type { Platform } from './features/build/build-platform';
8
- export type { ITsconfig } from './utils/tsconfig';
9
-
10
- export interface ITaskMapper {
11
- logger: LoggerText | null;
12
- taskPath: string;
13
- params?: string[];
14
- }
15
-
16
- export type PackageModeType =
17
- | 'universal-js'
18
- | 'universal-js-lite'
19
- | 'browser-js'
20
- | 'browser-js-lite'
21
- | 'node-js';
22
-
23
- export type JsSyntaxType = 'CJS+ES6' | 'ESM+ES5' | 'ESM+ES6';
24
-
25
- export interface IPackageFields {
26
- main?: JsSyntaxType;
27
- modern?: JsSyntaxType;
28
- module?: JsSyntaxType;
29
- }
30
-
31
- export interface IBuildConfig {
32
- appDirectory: string;
33
- platform: boolean | Exclude<Platform, 'all'>;
34
- enableTscCompiler: boolean;
35
- enableWatchMode?: boolean;
36
- isTsProject: boolean;
37
- sourceDir: string;
38
- tsconfigName?: string;
39
- clear?: boolean;
40
- }
41
-
42
- export interface IPackageModeValue {
43
- type: 'module' | 'commonjs';
44
- syntax: 'es5' | 'es6+';
45
- outDir: 'node' | 'treeshaking' | 'modern';
46
- copyDirs?: ('node' | 'treeshaking' | 'modern')[];
47
- }
48
-
49
- export interface ModuleToolsOutput extends OutputConfig {
50
- assetsPath: string;
51
- disableTsChecker: boolean;
52
- enableSourceMap: boolean;
53
- packageMode: PackageModeType;
54
- packageFields: IPackageFields;
55
- importStyle: ImportStyleType;
56
- }
57
-
58
- export interface ModuleToolsSource extends SourceConfig {
59
- jsxTransformRuntime: 'automatic' | 'classic';
60
- }
61
-
62
- export type ModuleToolsConfig = NormalizedConfig & {
63
- output: OutputConfig & ModuleToolsOutput;
64
- source: NormalizedConfig['source'] & ModuleToolsSource;
65
- };
@@ -1,104 +0,0 @@
1
- import {
2
- getBabelConfig,
3
- getModuleBabelChain,
4
- } from '@modern-js/babel-preset-module';
5
- import { TransformOptions } from '@babel/core';
6
- import { applyOptionsChain, getAlias } from '@modern-js/utils';
7
- import { NormalizedConfig } from '@modern-js/core';
8
- import type { BabelChain } from '@modern-js/babel-chain';
9
- import { IPackageModeValue, ModuleToolsConfig } from '../types';
10
-
11
- export const getFinalAlias: any = (
12
- modernConfig: NormalizedConfig,
13
- option: { appDirectory: string; tsconfigPath: string; sourceAbsDir: string },
14
- ) => {
15
- const aliasConfig = getAlias(modernConfig.source.alias, option);
16
- // 排除内部别名,因为不需要处理
17
- const finalPaths: Record<string, string | string[]> = {};
18
- const internalAliasPrefix = '@modern-js/runtime';
19
- if (aliasConfig.paths && typeof aliasConfig.paths === 'object') {
20
- const pathsKey = Object.keys(aliasConfig.paths);
21
- for (const key of pathsKey) {
22
- if (!key.includes(internalAliasPrefix)) {
23
- finalPaths[key] = aliasConfig.paths[key];
24
- }
25
- }
26
- }
27
-
28
- aliasConfig.paths = finalPaths;
29
- return aliasConfig;
30
- };
31
-
32
- export const resolveBabelConfig = (
33
- appDirectory: string,
34
- modernConfig: NormalizedConfig,
35
- option: Pick<IPackageModeValue, 'syntax' | 'type'> & {
36
- sourceAbsDir: string;
37
- tsconfigPath: string;
38
- },
39
- ) => {
40
- const {
41
- source: { envVars, globalVars, jsxTransformRuntime = 'automatic' },
42
- output: { importStyle },
43
- tools: { lodash: userLodashOption },
44
- } = modernConfig as ModuleToolsConfig;
45
-
46
- // alias config
47
- const aliasConfig = getFinalAlias(modernConfig, {
48
- appDirectory,
49
- ...option,
50
- });
51
-
52
- // lodash config
53
- const lodashOptions = applyOptionsChain(
54
- { id: ['lodash', 'ramda'] },
55
- // TODO: 需要处理类型问题
56
- userLodashOption as any,
57
- );
58
- // babel config
59
- const internalBabelConfig = getBabelConfig(
60
- {
61
- appDirectory,
62
- enableReactPreset: true,
63
- enableTypescriptPreset: true,
64
- alias: aliasConfig,
65
- envVars,
66
- globalVars,
67
- lodashOptions,
68
- jsxTransformRuntime,
69
- importStyle,
70
- },
71
- {
72
- type: option.type,
73
- syntax: option.syntax,
74
- },
75
- );
76
-
77
- // Preventing warning when files are too large
78
- internalBabelConfig.compact = false;
79
-
80
- const babelChain = getModuleBabelChain(
81
- {
82
- appDirectory,
83
- enableReactPreset: true,
84
- enableTypescriptPreset: true,
85
- alias: aliasConfig,
86
- envVars,
87
- globalVars,
88
- lodashOptions,
89
- jsxTransformRuntime,
90
- importStyle,
91
- },
92
- {
93
- type: option.type,
94
- syntax: option.syntax,
95
- },
96
- );
97
- const userBabelConfig = modernConfig.tools.babel;
98
- return applyOptionsChain<TransformOptions, { chain: BabelChain }>(
99
- internalBabelConfig,
100
- // TODO: 感觉 userBabelConfig 的类型应该是TransformOptions
101
- userBabelConfig as any,
102
- { chain: babelChain },
103
- );
104
- };
@@ -1,3 +0,0 @@
1
- import { chalk } from '@modern-js/utils';
2
-
3
- export const devMenuTitle = chalk.rgb(255, 153, 0);
package/src/utils/copy.ts DELETED
@@ -1,71 +0,0 @@
1
- import * as path from 'path';
2
- import { fs, Import } from '@modern-js/utils';
3
- import type { NormalizedConfig, IAppContext } from '@modern-js/core';
4
-
5
- const globby: typeof import('globby') = Import.lazy('globby', require);
6
- const fastGlob: typeof import('fast-glob') = Import.lazy('fast-glob', require);
7
- const normalizePath: typeof import('normalize-path') = Import.lazy(
8
- 'normalize-path',
9
- require,
10
- );
11
-
12
- // eslint-disable-next-line max-statements
13
- export const copyTask = async (option: {
14
- modernConfig: NormalizedConfig;
15
- appContext: IAppContext;
16
- }) => {
17
- const { modernConfig, appContext } = option;
18
- const { appDirectory } = appContext;
19
- const {
20
- output: { copy, path: outputPath = 'dist', jsPath = 'js' },
21
- } = modernConfig;
22
- const copyDistDir = path.join(outputPath, jsPath);
23
-
24
- if (!copy) {
25
- return;
26
- }
27
- try {
28
- // 类型暂时这样处理,待之后优化copy的逻辑
29
- for (const copyOption of copy as any) {
30
- // 在原来的基础上,引入了类似于 copy-webpck-plugin 的 context 属性,可以设置项目根路径
31
- const {
32
- context = appDirectory,
33
- from,
34
- globOptions,
35
- to: toOrigin,
36
- } = copyOption;
37
- let fromOrigin = from;
38
- // 获取 glob 规则
39
- let glob = '';
40
- let options = {};
41
- if (fromOrigin !== null && typeof fromOrigin === 'object') {
42
- ({ glob, ...options } = fromOrigin);
43
- fromOrigin = glob;
44
- } else if (globOptions && typeof globOptions === 'object') {
45
- options = globOptions;
46
- }
47
- glob = path.isAbsolute(fromOrigin)
48
- ? fromOrigin
49
- : path.posix.join(
50
- fastGlob.escapePath(normalizePath(path.resolve(context))),
51
- fromOrigin,
52
- );
53
- // 计算 glob,获取目标文件
54
- const paths = await globby(glob, options);
55
- if (!paths.length) {
56
- return;
57
- }
58
- const to = path.normalize(toOrigin ? toOrigin : '');
59
- const isToDirectory = path.extname(to) === '';
60
- paths.forEach(item => {
61
- const relativeFrom = path.relative(context, item);
62
- // 如果 to 是目录,通过相对路径计算完整的产物路径;如果 to 是文件,直接作为最终产物路径
63
- const fileName = isToDirectory ? path.join(to, relativeFrom) : to;
64
- const finalToPath = path.resolve(copyDistDir, fileName);
65
- fs.copySync(item, finalToPath);
66
- });
67
- }
68
- } catch (e: any) {
69
- console.error(`copy error: ${e.message}`);
70
- }
71
- };
@@ -1,31 +0,0 @@
1
- interface ITaskConfig {
2
- srcRootDir: string; // 源码的根目录
3
- willCompilerDirOrFile: string; // 用于编译的源码文件或者源码目录
4
- distDir: string;
5
- appDirectory: string;
6
- sourceMaps: boolean;
7
- syntax: 'es5' | 'es6+';
8
- type: 'module' | 'commonjs';
9
- tsconfigPath: string;
10
- copyDirs?: string;
11
- compiler?: 'babel' | 'esbuild' | 'swc';
12
- watch: boolean;
13
- }
14
-
15
- export const initEnv = ({
16
- syntax,
17
- type,
18
- }: {
19
- syntax: ITaskConfig['syntax'];
20
- type: ITaskConfig['type'];
21
- }) => {
22
- if (syntax === 'es6+' && type === 'commonjs') {
23
- return 'CJS_ES6';
24
- } else if (syntax === 'es6+' && type === 'module') {
25
- return 'ESM_ES6';
26
- } else if (syntax === 'es5' && type === 'module') {
27
- return 'ESM_ES5';
28
- }
29
-
30
- return '';
31
- };
package/src/utils/json.ts DELETED
@@ -1,13 +0,0 @@
1
- export const safeParse = (jsonString: string) => {
2
- try {
3
- return {
4
- code: 0,
5
- value: JSON.parse(jsonString),
6
- };
7
- } catch (e) {
8
- return {
9
- code: 1,
10
- value: jsonString,
11
- };
12
- }
13
- };
@@ -1,9 +0,0 @@
1
- import { Import } from '@modern-js/utils';
2
-
3
- const i18n: typeof import('@modern-js/i18n-cli-language-detector') =
4
- Import.lazy('@modern-js/i18n-cli-language-detector', require);
5
-
6
- export function getLocaleLanguage() {
7
- const detector = new i18n.I18CLILanguageDetector();
8
- return detector.detect();
9
- }