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.
@@ -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 { create as createTsCompiler } from "./actions/ts-compile";
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 Options {
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 NAME = "maishu-scripts-options";
28
- (global as any)[NAME] = (global as any)[NAME] || new Options();
29
- export default (global as any)[NAME] as Options;
27
+ const config = new Config();
28
+ export default config;
@@ -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 { ProjectCompiler } from "./project-compiler";
4
- import { errors } from "./errors";
5
- describe('project-compiler test', function () {
6
-
7
- let projectPath = path.join(__dirname, "..", "..", "test");
8
- if (fs.existsSync(projectPath) === false)
9
- throw errors.pathNotExists(projectPath);
10
-
11
- // let projectCompiler = new ProjectCompiler(projectPath, "src", "out");
12
-
13
- test("findBabelConfigPath test", function () {
14
- let staticPath = path.join(projectPath, "src", "static");
15
- let babelConfigPath = ProjectCompiler.findBabelConfigPath(projectPath, staticPath);
16
- expect(babelConfigPath).toBe(path.join(staticPath, "babel.config.json"));
17
-
18
- let componentsPath = path.join(staticPath, "components");
19
- expect(fs.existsSync(componentsPath)).toBeTruthy();
20
- babelConfigPath = ProjectCompiler.findBabelConfigPath(projectPath, componentsPath);
21
- expect(babelConfigPath).toBe(path.join(staticPath, "babel.config.json"));
22
-
23
- let designPath = path.join(staticPath, "design");
24
- babelConfigPath = ProjectCompiler.findBabelConfigPath(projectPath, designPath);
25
- expect(babelConfigPath).toBe(path.join(designPath, "babel.config.js"));
26
- })
27
-
28
- test("loadBabelConfig test", function () {
29
-
30
- let staticPath = path.join(projectPath, "src", "static");
31
- let designPath = path.join(staticPath, "design");
32
- let babelConfigPath = ProjectCompiler.findBabelConfigPath(projectPath, designPath);
33
- expect(babelConfigPath).not.toBe(null);
34
- let babelConfig = ProjectCompiler.loadBabelConfig(babelConfigPath as string);
35
- expect(babelConfig).not.toBe(undefined);
36
- expect(babelConfig.presets).not.toBe(undefined);
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
+ });