maishu-scripts 1.4.2 → 1.4.5
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/out/index.d.ts +2 -4
- package/out/index.js +4 -2
- package/out/modules/actions/babel-compile.d.ts +11 -1
- package/out/modules/actions/babel-compile.js +76 -55
- package/out/modules/actions/copy-file.js +12 -4
- package/out/modules/compile.js +2 -2
- package/out/modules/configs.d.ts +3 -3
- package/out/modules/configs.js +7 -4
- package/out/modules/errors.d.ts +1 -0
- package/out/modules/errors.js +8 -0
- package/out/package.json +33 -0
- package/package.json +1 -1
- package/src/index.ts +2 -1
- package/src/modules/actions/babel-compile.test.ts +436 -0
- package/src/modules/actions/babel-compile.ts +80 -64
- package/src/modules/actions/copy-file.ts +12 -4
- package/src/modules/compile.ts +7 -7
- package/src/modules/configs.ts +5 -6
- package/src/modules/errors.ts +8 -0
- package/src/modules/project-compiler.test.ts +245 -40
package/src/modules/configs.ts
CHANGED
|
@@ -2,8 +2,7 @@ import { FileAction } from "../types";
|
|
|
2
2
|
import scssCompile from "./actions/scss-compile";
|
|
3
3
|
import lessCompile from "./actions/less-compile";
|
|
4
4
|
import { create as createBielCompiler } from "./actions/babel-compile";
|
|
5
|
-
import
|
|
6
|
-
import ts from "typescript";
|
|
5
|
+
import copyFile from "./actions/copy-file";
|
|
7
6
|
|
|
8
7
|
// const skipFiles = ["\\S+\\.d\\.tsx?$", "\\S+\\.test\\.tsx?$", "\\S+\\.spec\\.tsx?$"]
|
|
9
8
|
|
|
@@ -12,9 +11,10 @@ const fileActions: Record<string, FileAction> = {
|
|
|
12
11
|
".tsx": createBielCompiler(),
|
|
13
12
|
".scss": scssCompile,
|
|
14
13
|
".less": lessCompile,
|
|
14
|
+
".map": copyFile,
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
class
|
|
17
|
+
export class Config {
|
|
18
18
|
fileActions: Record<string, FileAction> = fileActions;
|
|
19
19
|
skipFiles: Record<string, RegExp[]> = {
|
|
20
20
|
".tsx": [/\.d\.tsx?$/, /\.test\.tsx?$/, /\.spec\.tsx?$/],
|
|
@@ -24,6 +24,5 @@ class Options {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
export default (global as any)[NAME] as Options;
|
|
27
|
+
const config = new Config();
|
|
28
|
+
export default config;
|
package/src/modules/errors.ts
CHANGED
|
@@ -21,6 +21,14 @@ class Errors extends BaseErrors {
|
|
|
21
21
|
error.name = Errors.prototype.invalidBabelConfigExtension.name;
|
|
22
22
|
return error;
|
|
23
23
|
}
|
|
24
|
+
copyFileError(sourcePath: string, destPath: string, innerError?: Error) {
|
|
25
|
+
let error = new Error(`Failed to copy file from "${sourcePath}" to "${destPath}"`);
|
|
26
|
+
error.name = Errors.prototype.copyFileError.name;
|
|
27
|
+
if (innerError) {
|
|
28
|
+
error.cause = innerError;
|
|
29
|
+
}
|
|
30
|
+
return error;
|
|
31
|
+
}
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
export const errors = new Errors();
|
|
@@ -1,40 +1,245 @@
|
|
|
1
|
-
import * as path from "path";
|
|
2
|
-
import * as fs from "fs";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as os from "os";
|
|
4
|
+
import { ProjectCompiler } from "./project-compiler";
|
|
5
|
+
import { errors } from "./errors";
|
|
6
|
+
|
|
7
|
+
describe('ProjectCompiler', () => {
|
|
8
|
+
let projectPath = path.join(__dirname, "..", "..", "test");
|
|
9
|
+
|
|
10
|
+
beforeAll(() => {
|
|
11
|
+
if (!fs.existsSync(projectPath)) {
|
|
12
|
+
throw errors.pathNotExists(projectPath);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// ========== findBabelConfigPath ==========
|
|
17
|
+
|
|
18
|
+
describe('findBabelConfigPath', () => {
|
|
19
|
+
test('should find babel.config.json in the same directory', () => {
|
|
20
|
+
const staticPath = path.join(projectPath, "src", "static");
|
|
21
|
+
const result = ProjectCompiler.findBabelConfigPath(projectPath, staticPath);
|
|
22
|
+
expect(result).toBe(path.join(staticPath, "babel.config.json"));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('should find babel.config.js in the same directory', () => {
|
|
26
|
+
const designPath = path.join(projectPath, "src", "static", "design");
|
|
27
|
+
const result = ProjectCompiler.findBabelConfigPath(projectPath, designPath);
|
|
28
|
+
expect(result).toBe(path.join(designPath, "babel.config.js"));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('should find config in parent directory when child has none', () => {
|
|
32
|
+
const staticPath = path.join(projectPath, "src", "static");
|
|
33
|
+
const componentsPath = path.join(staticPath, "components");
|
|
34
|
+
expect(fs.existsSync(componentsPath)).toBeTruthy();
|
|
35
|
+
|
|
36
|
+
const result = ProjectCompiler.findBabelConfigPath(projectPath, componentsPath);
|
|
37
|
+
expect(result).toBe(path.join(staticPath, "babel.config.json"));
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('should find config in project root when config exists at root', () => {
|
|
41
|
+
// projectPath is test/, which has src/babel.config.js but not at root
|
|
42
|
+
// Use src path which has babel.config.js
|
|
43
|
+
const srcPath = path.join(projectPath, "src");
|
|
44
|
+
const result = ProjectCompiler.findBabelConfigPath(srcPath, srcPath);
|
|
45
|
+
expect(result).not.toBeNull();
|
|
46
|
+
expect(result).toContain('babel.config.js');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('should return null when no babel config found anywhere', () => {
|
|
50
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-test-'));
|
|
51
|
+
try {
|
|
52
|
+
const subDir = path.join(tmpDir, 'sub');
|
|
53
|
+
fs.mkdirSync(subDir);
|
|
54
|
+
const result = ProjectCompiler.findBabelConfigPath(tmpDir, subDir);
|
|
55
|
+
expect(result).toBeNull();
|
|
56
|
+
} finally {
|
|
57
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('should prefer babel.config.js over babel.config.json when both exist', () => {
|
|
62
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-test-'));
|
|
63
|
+
try {
|
|
64
|
+
const jsConfig = path.join(tmpDir, 'babel.config.js');
|
|
65
|
+
const jsonConfig = path.join(tmpDir, 'babel.config.json');
|
|
66
|
+
fs.writeFileSync(jsConfig, 'module.exports = {};');
|
|
67
|
+
fs.writeFileSync(jsonConfig, '{}');
|
|
68
|
+
|
|
69
|
+
const result = ProjectCompiler.findBabelConfigPath(tmpDir, tmpDir);
|
|
70
|
+
expect(result).toBe(jsConfig);
|
|
71
|
+
} finally {
|
|
72
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('should resolve relative directoryPath to absolute', () => {
|
|
77
|
+
const staticPath = path.join(projectPath, "src", "static");
|
|
78
|
+
const relativeDir = path.relative(projectPath, staticPath);
|
|
79
|
+
const result = ProjectCompiler.findBabelConfigPath(projectPath, relativeDir);
|
|
80
|
+
expect(result).not.toBeNull();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// ========== loadBabelConfig ==========
|
|
85
|
+
|
|
86
|
+
describe('loadBabelConfig', () => {
|
|
87
|
+
test('should load config from .json file', () => {
|
|
88
|
+
const staticPath = path.join(projectPath, "src", "static");
|
|
89
|
+
const configPath = path.join(staticPath, "babel.config.json");
|
|
90
|
+
const config = ProjectCompiler.loadBabelConfig(configPath);
|
|
91
|
+
|
|
92
|
+
expect(config).toBeDefined();
|
|
93
|
+
expect(config.plugins).toBeDefined();
|
|
94
|
+
expect(config.plugins).toContainEqual("@babel/plugin-transform-typescript");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('should load config from .js file', () => {
|
|
98
|
+
const designPath = path.join(projectPath, "src", "static", "design");
|
|
99
|
+
const configPath = path.join(designPath, "babel.config.js");
|
|
100
|
+
const config = ProjectCompiler.loadBabelConfig(configPath);
|
|
101
|
+
|
|
102
|
+
expect(config).toBeDefined();
|
|
103
|
+
expect(config.presets).toBeDefined();
|
|
104
|
+
expect(config.presets!.length).toBeGreaterThan(0);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('should throw argumentNull when configPath is empty', () => {
|
|
108
|
+
expect(() => ProjectCompiler.loadBabelConfig("")).toThrow();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('should throw pathNotExists when configPath does not exist', () => {
|
|
112
|
+
expect(() => ProjectCompiler.loadBabelConfig("/nonexistent/babel.config.json")).toThrow();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('should throw invalidBabelConfigExtension for unsupported file extension', () => {
|
|
116
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-test-'));
|
|
117
|
+
try {
|
|
118
|
+
const configPath = path.join(tmpDir, 'babel.config.yaml');
|
|
119
|
+
fs.writeFileSync(configPath, 'test: true');
|
|
120
|
+
|
|
121
|
+
expect(() => ProjectCompiler.loadBabelConfig(configPath)).toThrow();
|
|
122
|
+
} finally {
|
|
123
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('should load config from .js file with default export', () => {
|
|
128
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-test-'));
|
|
129
|
+
try {
|
|
130
|
+
const configPath = path.join(tmpDir, 'babel.config.js');
|
|
131
|
+
fs.writeFileSync(configPath, 'module.exports = { presets: ["@babel/preset-env"] };');
|
|
132
|
+
// Clear require cache
|
|
133
|
+
delete require.cache[require.resolve(configPath)];
|
|
134
|
+
|
|
135
|
+
const config = ProjectCompiler.loadBabelConfig(configPath);
|
|
136
|
+
expect(config.presets).toBeDefined();
|
|
137
|
+
expect(config.presets).toContainEqual("@babel/preset-env");
|
|
138
|
+
} finally {
|
|
139
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// ========== getBabelConfig ==========
|
|
145
|
+
|
|
146
|
+
describe('getBabelConfig', () => {
|
|
147
|
+
test('should return config with ast=true and code=false when config exists', () => {
|
|
148
|
+
const staticPath = path.join(projectPath, "src", "static");
|
|
149
|
+
const result = ProjectCompiler.getBabelConfig(projectPath, staticPath);
|
|
150
|
+
|
|
151
|
+
expect(result.options).toBeDefined();
|
|
152
|
+
expect(result.options.ast).toBe(true);
|
|
153
|
+
expect(result.options.code).toBe(false);
|
|
154
|
+
expect(result.path).toBeTruthy();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('should return default config when no config file found', () => {
|
|
158
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-test-'));
|
|
159
|
+
try {
|
|
160
|
+
const result = ProjectCompiler.getBabelConfig(tmpDir, tmpDir);
|
|
161
|
+
|
|
162
|
+
expect(result.options).toBeDefined();
|
|
163
|
+
expect(result.options.ast).toBe(true);
|
|
164
|
+
expect(result.options.code).toBe(false);
|
|
165
|
+
expect(result.options.plugins).toBeDefined();
|
|
166
|
+
expect(result.options.presets).toBeDefined();
|
|
167
|
+
expect(result.path).toBe('');
|
|
168
|
+
} finally {
|
|
169
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test('should set ast=true and code=false on found config', () => {
|
|
174
|
+
const staticPath = path.join(projectPath, "src", "static");
|
|
175
|
+
const result = ProjectCompiler.getBabelConfig(projectPath, staticPath);
|
|
176
|
+
|
|
177
|
+
expect(result.options.ast).toBe(true);
|
|
178
|
+
expect(result.options.code).toBe(false);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test('should return path to the found config file', () => {
|
|
182
|
+
const staticPath = path.join(projectPath, "src", "static");
|
|
183
|
+
const result = ProjectCompiler.getBabelConfig(projectPath, staticPath);
|
|
184
|
+
expect(result.path).toContain('babel.config.json');
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// ========== getDefaultBabelConfig ==========
|
|
189
|
+
|
|
190
|
+
describe('getDefaultBabelConfig', () => {
|
|
191
|
+
test('should return config with plugins and presets', () => {
|
|
192
|
+
const config = ProjectCompiler.getDefaultBabelConfig();
|
|
193
|
+
|
|
194
|
+
expect(config).toBeDefined();
|
|
195
|
+
expect(config.plugins).toBeDefined();
|
|
196
|
+
expect(config.presets).toBeDefined();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test('should include expected plugins', () => {
|
|
200
|
+
const config = ProjectCompiler.getDefaultBabelConfig();
|
|
201
|
+
const pluginNames = config.plugins!.map(p => Array.isArray(p) ? p[0] : p);
|
|
202
|
+
|
|
203
|
+
expect(pluginNames).toContain("babel-plugin-transform-typescript-metadata");
|
|
204
|
+
expect(pluginNames).toContain("@babel/plugin-transform-typescript");
|
|
205
|
+
expect(pluginNames).toContain("@babel/plugin-transform-react-jsx");
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test('should include expected presets', () => {
|
|
209
|
+
const config = ProjectCompiler.getDefaultBabelConfig();
|
|
210
|
+
const presetNames = config.presets!.map(p => Array.isArray(p) ? p[0] : p);
|
|
211
|
+
|
|
212
|
+
expect(presetNames).toContain("@babel/preset-env");
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('should have decorator plugin with legacy option', () => {
|
|
216
|
+
const config = ProjectCompiler.getDefaultBabelConfig();
|
|
217
|
+
const decoratorsPlugin = config.plugins!.find(p =>
|
|
218
|
+
Array.isArray(p) && p[0] === "@babel/plugin-proposal-decorators"
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
expect(decoratorsPlugin).toBeDefined();
|
|
222
|
+
expect(Array.isArray(decoratorsPlugin)).toBe(true);
|
|
223
|
+
expect((decoratorsPlugin as any[])[1]).toEqual({ legacy: true });
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test('should include typescript plugin with isTSX option', () => {
|
|
227
|
+
const config = ProjectCompiler.getDefaultBabelConfig();
|
|
228
|
+
const tsPlugin = config.plugins!.find(p =>
|
|
229
|
+
Array.isArray(p) && p[0] === "@babel/plugin-transform-typescript"
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
expect(tsPlugin).toBeDefined();
|
|
233
|
+
expect(Array.isArray(tsPlugin)).toBe(true);
|
|
234
|
+
expect((tsPlugin as any[])[1]).toEqual({ isTSX: true });
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// ========== tsOutExt ==========
|
|
239
|
+
|
|
240
|
+
describe('tsOutExt', () => {
|
|
241
|
+
test('should be ".js"', () => {
|
|
242
|
+
expect(ProjectCompiler.tsOutExt).toBe(".js");
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
});
|