maishu-scripts 1.2.0 → 1.3.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.
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.run = void 0;
4
- const nodemon = require("nodemon");
5
- function run(args) {
6
- nodemon({
6
+ exports.run = run;
7
+ const nodemon_1 = __importDefault(require("nodemon"));
8
+ function run() {
9
+ (0, nodemon_1.default)({
7
10
  script: "./out/main.js", //!args ? "./out/main.js" : "./out/main.js " + args,
8
11
  watch: ["./out/"],
9
- args: args
12
+ ignoreRoot: ['./out/static/'],
10
13
  });
11
14
  }
12
- exports.run = run;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maishu-scripts",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "用于对 node 项目进行代码生成,打包,运行",
5
5
  "dependencies": {
6
6
  "@babel/core": "^7.24.3",
@@ -9,9 +9,11 @@
9
9
  "@babel/plugin-transform-typescript": "^7.24.1",
10
10
  "@types/node": "^20.12.2",
11
11
  "babel-plugin-transform-typescript-metadata": "^0.3.2",
12
+ "less": "^4.5.1",
12
13
  "maishu-toolkit": "^1.12.6",
13
14
  "node-watch": "^0.7.4",
14
- "nodemon": "^3.1.0",
15
+ "nodemon": "^3.1.4",
16
+ "sass": "^1.97.1",
15
17
  "typescript": "^5.4.5"
16
18
  },
17
19
  "devDependencies": {
@@ -19,11 +21,15 @@
19
21
  "@babel/preset-typescript": "^7.24.1",
20
22
  "@types/babel__core": "^7.20.5",
21
23
  "@types/jest": "^29.5.12",
24
+ "@types/less": "^3.0.8",
22
25
  "jest": "^29.7.0"
23
26
  },
24
27
  "main": "./out/index.js",
25
28
  "files": [
26
29
  "out",
27
30
  "src"
28
- ]
29
- }
31
+ ],
32
+ "scripts": {
33
+ "build": "tsc"
34
+ }
35
+ }
@@ -146,3 +146,5 @@ class ImportPathRewrite {
146
146
  }
147
147
 
148
148
  }
149
+
150
+
@@ -7,6 +7,10 @@ let copyFile: FileAction = (filePath: string, outPath: string, projectPath: stri
7
7
  if (!filePath) throw errors.argumentNull("filePath");
8
8
  if (!outPath) throw errors.argumentNull("outPath");
9
9
 
10
+ if (!fs.existsSync(filePath)) {
11
+ return;
12
+ }
13
+
10
14
  let out = filePath.replace(path.dirname(filePath), outPath);
11
15
  let outDirPath = path.resolve(out, "..");
12
16
 
@@ -0,0 +1,34 @@
1
+ import lessCompile from './less-compile';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+
5
+ describe('less-compile', () => {
6
+ it('should compile less files', async () => {
7
+ // generate a less test file
8
+ const lessTestFile = path.join(__dirname, 'test.less');
9
+ let lessTestFileContent = `
10
+ .test {
11
+ color: red;
12
+ }
13
+ `;
14
+ fs.writeFileSync(lessTestFile, lessTestFileContent);
15
+
16
+ // compile the less test file
17
+ await lessCompile(lessTestFile, 'dist', __dirname);
18
+
19
+ const lessTestCompiledFile = path.join(__dirname, 'dist', 'test.css');
20
+
21
+
22
+ // check if the compiled file exists
23
+ // 移除 lessTestFileContent 空格,换行符
24
+ lessTestFileContent = lessTestFileContent.replace(/\s/g, '').replace(/[\r\n]/g, '');
25
+ let compiledFileContent = fs.readFileSync(lessTestCompiledFile, 'utf-8');
26
+ compiledFileContent = compiledFileContent.replace(/\s/g, '').replace(/[\r\n]/g, '');
27
+ expect(compiledFileContent).toBe(lessTestFileContent);
28
+
29
+ // clean up
30
+ fs.unlinkSync(lessTestFile);
31
+ fs.unlinkSync(lessTestCompiledFile);
32
+
33
+ });
34
+ });
@@ -0,0 +1,35 @@
1
+ import less from 'less';
2
+ import { errors } from '../errors';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { FileAction } from '../../types';
6
+
7
+ /**
8
+ * 编译特定Less文件,并生成到指定目录
9
+ * @param filePath 源文件路径,绝对路径
10
+ * @param outDir 输出目录,相对于项目路径
11
+ * @param projectPath 项目路径,绝对路径
12
+ */
13
+ const compileFile = async (filePath: string, outDir: string, projectPath: string) => {
14
+ if (!filePath)
15
+ throw errors.argumentNull('filePath');
16
+ if (!outDir)
17
+ throw errors.argumentNull('outDir');
18
+ if (!projectPath)
19
+ throw errors.argumentNull('projectPath');
20
+
21
+ let content = fs.readFileSync(filePath, 'utf-8');
22
+ let result = await less.render(content, { filename: filePath });
23
+
24
+ let ext = path.extname(filePath);
25
+ let outExt = '.css';
26
+ let targetPath = path.join(projectPath, outDir, path.basename(filePath).replace(ext, outExt));
27
+ let outDirPath = path.resolve(targetPath, "..");
28
+
29
+ if (!fs.existsSync(outDirPath))
30
+ fs.mkdirSync(outDirPath, { recursive: true });
31
+
32
+ fs.writeFileSync(targetPath, result.css);
33
+ }
34
+
35
+ export default compileFile;
@@ -0,0 +1,38 @@
1
+ import scssCompile from './scss-compile';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+
5
+ describe('scss-compile', () => {
6
+
7
+ it('should compile scss files', () => {
8
+
9
+ // generate test file
10
+ const testFile = path.join(__dirname, 'test.scss');
11
+ const testContent = `$color: red;
12
+ .test {
13
+ background-color: $color;
14
+ }`;
15
+ fs.writeFileSync(testFile, testContent);
16
+
17
+ scssCompile(testFile, 'dist', __dirname);
18
+
19
+ const expectedFile = path.join(__dirname, 'dist', 'test.css');
20
+ let expectedContent = `.test {
21
+ background-color: red;
22
+ }
23
+ `;
24
+ // 移除 expectedContent 中空格和换行符
25
+ expectedContent = expectedContent.replace(/\s+/g, '').replace(/[\r\n]/g, '');
26
+ let fileContent = fs.readFileSync(expectedFile, 'utf-8');
27
+ fileContent = fileContent.replace(/\s+/g, '').replace(/[\r\n]/g, '');
28
+
29
+ expect(fileContent).toBe(expectedContent);
30
+
31
+ // clean up
32
+ fs.unlinkSync(testFile);
33
+ fs.unlinkSync(expectedFile);
34
+
35
+
36
+ })
37
+
38
+ })
@@ -0,0 +1,35 @@
1
+ import * as sass from 'sass';
2
+ import { errors } from '../errors';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import type { FileAction } from '../../types';
6
+
7
+ /**
8
+ * 编译特定SCSS文件,并生成到指定目录
9
+ * @param filePath 源文件路径,绝对路径
10
+ * @param outDir 输出目录,相对于项目路径
11
+ * @param projectPath 项目路径,绝对路径
12
+ */
13
+ export const compileFile: FileAction = (filePath: string, outDir: string, projectPath: string) => {
14
+ if (!filePath)
15
+ throw errors.argumentNull('filePath');
16
+ if (!outDir)
17
+ throw errors.argumentNull('outDir');
18
+ if (!projectPath)
19
+ throw errors.argumentNull('projectPath');
20
+
21
+ let content = fs.readFileSync(filePath, 'utf-8');
22
+ let result = sass.renderSync({ data: content });
23
+
24
+ let ext = path.extname(filePath);
25
+ let outExt = '.css';
26
+ let targetPath = path.join(projectPath, outDir, path.basename(filePath).replace(ext, outExt));
27
+ let outDirPath = path.resolve(targetPath, "..");
28
+
29
+ if (!fs.existsSync(outDirPath))
30
+ fs.mkdirSync(outDirPath, { recursive: true });
31
+
32
+ fs.writeFileSync(targetPath, result.css.toString());
33
+ }
34
+
35
+ export default compileFile;
@@ -30,19 +30,4 @@ describe("Compile Test", function () {
30
30
  expect(ignored).toBe(true);
31
31
  })
32
32
 
33
- test("temp", function () {
34
- let sourceFile = "D:\\startdard-process\\plm-projects\\tc-api-proxy\\src\\app.controller.ts";
35
- let sourceCode = fs.readFileSync(sourceFile, "utf8");
36
- let r = ts.transpileModule(sourceCode, {
37
- compilerOptions: {
38
- module: ts.ModuleKind.CommonJS,
39
- target: ts.ScriptTarget.ES2015,
40
- sourceMap: true
41
- }
42
- })
43
-
44
- console.log(r);
45
-
46
- })
47
-
48
33
  })
@@ -5,19 +5,25 @@ import { errors } from "./errors";
5
5
  import { compileFile as bielCompileFile } from "./actions/biel-compile";
6
6
  import copyFile from "./actions/copy-file";
7
7
  import { FileAction } from "../types";
8
+ import scssCompile from "./actions/scss-compile";
9
+ import lessCompile from "./actions/less-compile";
8
10
 
9
11
  const skipFiles = ["\\S+\\.d\\.tsx?$", "\\S+\\.test\\.tsx?$", "\\S+\\.spec\\.tsx?$"]
10
- const extCopy = [".js", ".html", ".css", ".jpg", ".png", ".gif"];
12
+ const extCopy = [".js", ".html", ".css", ".jpg", ".png", ".gif", ".less"];
11
13
 
12
14
  let fileActions: { [ext: string]: FileAction } = {
13
15
  ".ts": bielCompileFile,
14
16
  ".tsx": bielCompileFile,
17
+ ".scss": scssCompile,
18
+ ".less": lessCompile,
15
19
  }
16
20
 
17
21
  extCopy.forEach(ext => fileActions[ext] = copyFile);
18
22
 
19
23
  /** 将 sourceDir 目录下所有文件生成到 outDir */
20
- export function generateCode(sourceDir: string, outDir: string, projectPath: string) {
24
+ export function generateCode(sourceDir: string, outDir: string, projectPath: string,
25
+ callback?: (filePath: string, outDir: string, projectPath: string) => void
26
+ ) {
21
27
 
22
28
  if (!sourceDir) throw errors.argumentNull("sourceDir");
23
29
  if (!outDir) throw errors.argumentNull("outDir");
@@ -43,6 +49,9 @@ export function generateCode(sourceDir: string, outDir: string, projectPath: str
43
49
  let action = fileActions[ext];
44
50
  if (action) {
45
51
  action(filePath, outDir, projectPath);
52
+ if (callback) {
53
+ callback(filePath, outDir, projectPath);
54
+ }
46
55
  }
47
56
  }
48
57
 
@@ -57,7 +66,7 @@ export function generateCode(sourceDir: string, outDir: string, projectPath: str
57
66
  }
58
67
 
59
68
  /** 监听 sourceRoot 目录下所有文件变化,并生成到 outRoot */
60
- export function watchDirectory(sourceRoot: string, outRoot: string, projectPath: string) {
69
+ export function watchDirectory(sourceRoot: string, outRoot: string, projectPath: string, callback?: (filePath: string, outDir: string, projectPath: string) => void) {
61
70
  if (!sourceRoot) throw errors.argumentNull("sourceRoot");
62
71
  if (!outRoot) throw errors.argumentNull("outRoot");
63
72
  if (!projectPath) throw errors.argumentNull("projectPath");
@@ -65,24 +74,21 @@ export function watchDirectory(sourceRoot: string, outRoot: string, projectPath:
65
74
  watch(sourceRoot, { recursive: true }, async (evt, name) => {
66
75
  let action = fileActions[extname(name)];
67
76
  let outPath = path.dirname(name).replace(sourceRoot, outRoot);
68
- if (action) {
77
+ if (!action) {
78
+ return;
79
+ }
80
+
81
+ try {
69
82
  action(name, outPath, projectPath);
83
+ if (callback)
84
+ callback(name, outPath, projectPath);
85
+ }
86
+ catch (e) {
87
+ console.error(e);
70
88
  }
71
89
  })
72
90
  }
73
91
 
74
- // export function copyFile(filePath: string, outDir: string) {
75
- // if (!filePath) throw errors.argumentNull("filePath");
76
- // if (!outDir) throw errors.argumentNull("outDir");
77
-
78
- // let out = filePath.replace(path.dirname(filePath), outDir);
79
- // let outDirPath = path.resolve(out, "..");
80
-
81
- // fs.mkdirSync(outDirPath, { recursive: true });
82
-
83
- // fs.copyFileSync(filePath, out);
84
- // }
85
-
86
92
  export function isIgnoredFile(filePath: string) {
87
93
  if (!filePath) throw errors.argumentNull("filePath");
88
94
 
@@ -1,4 +1,4 @@
1
- import * as nodemon from "nodemon";
1
+ import nodemon from "nodemon";
2
2
  import { errors } from "./errors";
3
3
  import * as fs from "fs";
4
4
  import * as path from "path";
@@ -12,96 +12,10 @@ type FileAction = (filePath: string, outDir: string) => void;
12
12
 
13
13
  export class ProjectCompiler {
14
14
 
15
- private fileActions: { [ext: string]: FileAction };
16
15
  private skipFiles = ["\\S+\\.d\\.tsx?$", "\\S+\\.test\\.tsx?$", "\\S+\\.spec\\.tsx?$"];
17
16
 
18
17
  static tsOutExt = tsOutExt;
19
18
 
20
- constructor(private projectPath: string, private sourceDirectoryNanme: string, private outputDirectoryName: string) {
21
- if (!projectPath) throw errors.argumentNull("projectPath");
22
- if (!sourceDirectoryNanme) throw errors.argumentNull("sourceDirectoryNanme");
23
- if (!outputDirectoryName) throw errors.argumentNull("outputDirectoryName");
24
-
25
- if (!path.isAbsolute(projectPath))
26
- throw errors.notAbsolutePath(projectPath);
27
-
28
- let sourcePath = path.join(projectPath, sourceDirectoryNanme);
29
- if (!fs.existsSync(sourcePath))
30
- throw errors.pathNotExists(sourcePath);
31
-
32
- this.fileActions = {
33
- ".ts": this.compileFile.bind(this),
34
- ".tsx": this.compileFile.bind(this),
35
- }
36
-
37
- }
38
-
39
- /**
40
- * 编译特定文件,并生成到制定目录
41
- * @param sourcePath 源文件路径
42
- * @param outDir 输出目录
43
- * */
44
- async compileFile(filePath: string, outDir: string) {
45
- this.compileTypeScriptFileByBabel(filePath, outDir);
46
- }
47
-
48
- private async compileTypeScriptFileByBabel(sourcePath: string, outDir: string) {
49
- if (!sourcePath) throw errors.argumentNull("sourcePath");
50
- if (!outDir) throw errors.argumentNull("outDir");
51
- if (!fs.existsSync(sourcePath)) throw errors.pathNotExists(sourcePath);
52
-
53
- let sourceDir = path.dirname(sourcePath);
54
- let babelConfig = ProjectCompiler.getBabelConfig(this.projectPath, sourceDir);
55
- let babelOptions = babelConfig.options;
56
- let babelPath = babelConfig.path;
57
- babelOptions.filename = sourcePath;
58
- babelOptions.code = false;
59
- babelOptions.ast = true;
60
-
61
- let fileResult = babel.transformFileSync(sourcePath, babelOptions);
62
- if (!fileResult)
63
- throw errors.compileError(sourcePath);
64
-
65
- let ast = fileResult.ast;
66
- if (!ast)
67
- throw errors.compileError(sourcePath);
68
-
69
- new ImportPathRewrite(sourcePath, ast, tsOutExt);
70
- let r = babel.transformFromAstSync(ast, undefined, {
71
- filename: sourcePath, plugins: babelOptions.plugins,
72
- presets: babelOptions.presets, sourceMaps: true
73
- });
74
- if (!r || r.code == null)
75
- throw errors.compileError(sourcePath);
76
-
77
- let ext = path.extname(sourcePath);
78
- let outExt = this.fileOutExt(sourcePath);
79
- let targetPath = path.join(outDir, path.basename(sourcePath).replace(ext, outExt));
80
- let outDirPath = path.resolve(targetPath, "..");
81
-
82
- if (r.map) {
83
- r.map.file = path.basename(targetPath);
84
- let sources = r.map.sources || [];
85
- let sourceDir = path.dirname(sourcePath);
86
- sources.forEach((s, i) => {
87
- sources[i] = path.relative(outDirPath, path.join(sourceDir, s));
88
- });
89
- r.map.sources = sources;
90
- let mapPath = targetPath + ".map";
91
- if (!fs.existsSync(outDirPath))
92
- fs.mkdirSync(outDirPath, { recursive: true });
93
-
94
- fs.writeFileSync(mapPath, JSON.stringify(r.map));
95
- r.code += `\n//babelPath:${babelPath}`;
96
- r.code += "\n//# sourceMappingURL=" + path.basename(sourcePath);
97
- }
98
-
99
- if (!fs.existsSync(outDirPath))
100
- fs.mkdirSync(outDirPath, { recursive: true });
101
-
102
- fs.writeFileSync(targetPath, r.code);
103
-
104
- }
105
19
 
106
20
  static loadBabelConfig(configPath: string): babel.TransformOptions {
107
21
  if (!configPath) throw errors.argumentNull("configPath");
@@ -179,90 +93,7 @@ export class ProjectCompiler {
179
93
  return babelOptions;
180
94
  }
181
95
 
182
- /**
183
- * 获取源文件所对应生成文件的扩展名
184
- * @param file 源文件名
185
- * */
186
- private fileOutExt(file: string) {
187
- let ext = path.extname(file);
188
- if (ext === ".ts")
189
- return tsOutExt;
190
-
191
- if (ext === ".tsx")
192
- return tsOutExt;
193
-
194
- return ext;
195
- }
196
-
197
- private isIgnoredFile(filePath: string) {
198
- if (!filePath) throw errors.argumentNull("filePath");
199
-
200
- let isSkip = this.skipFiles.some(pattern => new RegExp(pattern).test(filePath));
201
- return isSkip;
202
- }
203
-
204
- generateCode(): void;
205
- generateCode(sourceDir: string, outDir: string): void;
206
- generateCode(sourceDir?: string, outDir?: string): void {
207
-
208
- // if (!sourceDir) throw errors.argumentNull("sourceDir");
209
- // if (!outDir) throw errors.argumentNull("outDir");
210
- if (!sourceDir)
211
- sourceDir = path.join(this.projectPath, this.sourceDirectoryNanme);
212
-
213
- if (!outDir)
214
- outDir = path.join(this.projectPath, this.outputDirectoryName);
215
-
216
- let fileActions = this.fileActions;
217
-
218
- if (!fs.existsSync(sourceDir))
219
- throw errors.pathNotExists(sourceDir);
220
-
221
- let files = fs.readdirSync(sourceDir);
222
- for (let file of files) {
223
- let filePath = path.join(sourceDir, file);
224
- if (!fs.statSync(filePath).isFile()) {
225
- continue;
226
- }
227
-
228
- let isSkip = this.isIgnoredFile(filePath);//skipFiles.some(pattern => new RegExp(pattern).test(filePath));
229
- if (isSkip) {
230
- console.log(`Skip ${filePath}`);
231
- continue;
232
- }
233
-
234
- let ext = path.extname(file);
235
- let action = fileActions[ext];
236
- if (action) {
237
- action(filePath, outDir);
238
- }
239
- }
240
-
241
- let dirs = fs.readdirSync(sourceDir);
242
- for (let dir of dirs) {
243
- let fullPath = path.join(sourceDir, dir);
244
- let outDirPath = path.join(outDir, dir);
245
- if (fs.statSync(fullPath).isDirectory()) {
246
- this.generateCode(fullPath, outDirPath);
247
- }
248
- }
249
- }
250
-
251
- watchDirectory() {//sourceRoot: string, outRoot: string
252
- watch(this.sourceDirectoryNanme, { recursive: true }, async (evt, name) => {
253
- let action = this.fileActions[path.extname(name)];
254
- let outPath = path.dirname(name).replace(this.sourceDirectoryNanme, this.outputDirectoryName);
255
- if (action) {
256
- action(name, outPath);
257
- }
258
- })
259
- }
260
96
 
261
97
 
262
- run() {
263
- nodemon({
264
- script: `./${this.outputDirectoryName}/main.js`,
265
- watch: [`./${this.outputDirectoryName}/`],
266
- })
267
- }
98
+
268
99
  }
@@ -1,9 +1,9 @@
1
- import * as nodemon from "nodemon";
1
+ import nodemon from "nodemon";
2
2
 
3
- export function run(args?: string[]) {
3
+ export function run() {
4
4
  nodemon({
5
5
  script: "./out/main.js",//!args ? "./out/main.js" : "./out/main.js " + args,
6
6
  watch: ["./out/"],
7
- args: args
7
+ ignoreRoot: ['./out/static/'],
8
8
  })
9
9
  }
package/out/main.js DELETED
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const core_1 = require("@nestjs/core");
4
- const app_module_1 = require("./app.module");
5
- async function bootstrap() {
6
- const app = await core_1.NestFactory.create(app_module_1.AppModule);
7
- await app.listen(3000);
8
- }
9
- bootstrap();
@@ -1,7 +0,0 @@
1
- /**
2
- * 编译特定文件,并生成到制定目录
3
- * @param sourcePath 源文件路径
4
- * @param outDir 输出目录
5
- * @param projectPath 项目路径
6
- * */
7
- export declare function compileFile(sourcePath: string, outDir: string, projectPath: string): Promise<void>;