@qse/edu-scripts 0.0.0-beta.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 (81) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +107 -0
  3. package/app.d.ts +73 -0
  4. package/babel.config.json +3 -0
  5. package/docs/.vitepress/config.ts +35 -0
  6. package/docs/changelog.md +1 -0
  7. package/docs/debug.md +17 -0
  8. package/docs/deploy.md +54 -0
  9. package/docs/faq.md +144 -0
  10. package/docs/feat.md +167 -0
  11. package/docs/grayscale.md +31 -0
  12. package/docs/index.md +15 -0
  13. package/docs/install.md +1 -0
  14. package/docs/mode.md +42 -0
  15. package/docs/override.md +193 -0
  16. package/docs/refactor-react-16.md +37 -0
  17. package/docs/refactor.md +67 -0
  18. package/docs/static.md +24 -0
  19. package/es/asset/dll/libcommon3-manifest.json +181 -0
  20. package/es/asset/template/edu-app-env.d.ts.tpl +20 -0
  21. package/es/asset/template/edu-scripts.override.js.tpl +7 -0
  22. package/es/asset/template/tailwind.config.js.tpl +11 -0
  23. package/es/asset/template/tsconfig.json.tpl +24 -0
  24. package/es/auto-refactor.js +153 -0
  25. package/es/build.js +58 -0
  26. package/es/cli.js +65 -0
  27. package/es/commit-dist.js +83 -0
  28. package/es/config/paths.js +39 -0
  29. package/es/config/plugins/mock-server/defineMock.d.ts +6 -0
  30. package/es/config/plugins/mock-server/defineMock.js +7 -0
  31. package/es/config/plugins/mock-server/index.js +122 -0
  32. package/es/config/plugins/postcss-safe-area.js +22 -0
  33. package/es/config/plugins/ws-utils-createSocketURL.js +98 -0
  34. package/es/config/webpackConfig.js +418 -0
  35. package/es/config/webpackDevServerConfig.js +73 -0
  36. package/es/deploy.js +148 -0
  37. package/es/generator.js +52 -0
  38. package/es/index.d.ts +2 -0
  39. package/es/index.js +7 -0
  40. package/es/start.js +36 -0
  41. package/es/utils/FileSizeReporter.js +107 -0
  42. package/es/utils/appConfig.js +35 -0
  43. package/es/utils/beforeStart.js +51 -0
  44. package/es/utils/changeDeployVersion.js +85 -0
  45. package/es/utils/defineConfig.d.ts +76 -0
  46. package/es/utils/defineConfig.js +7 -0
  47. package/es/utils/exec.js +10 -0
  48. package/es/utils/getConfig.js +23 -0
  49. package/es/utils/getOverride.js +28 -0
  50. package/eslint.config.mjs +3 -0
  51. package/jest.config.mjs +199 -0
  52. package/package.json +95 -0
  53. package/src/asset/dll/libcommon3-manifest.json +181 -0
  54. package/src/asset/template/edu-app-env.d.ts.tpl +20 -0
  55. package/src/asset/template/edu-scripts.override.js.tpl +7 -0
  56. package/src/asset/template/tailwind.config.js.tpl +11 -0
  57. package/src/asset/template/tsconfig.json.tpl +24 -0
  58. package/src/auto-refactor.js +170 -0
  59. package/src/build.js +64 -0
  60. package/src/cli.js +88 -0
  61. package/src/commit-dist.js +103 -0
  62. package/src/config/paths.js +38 -0
  63. package/src/config/plugins/mock-server/defineMock.ts +12 -0
  64. package/src/config/plugins/mock-server/index.js +150 -0
  65. package/src/config/plugins/postcss-safe-area.js +21 -0
  66. package/src/config/plugins/ws-utils-createSocketURL.js +140 -0
  67. package/src/config/webpackConfig.js +444 -0
  68. package/src/config/webpackDevServerConfig.js +83 -0
  69. package/src/deploy.js +182 -0
  70. package/src/generator.js +67 -0
  71. package/src/index.ts +2 -0
  72. package/src/start.js +37 -0
  73. package/src/utils/FileSizeReporter.js +148 -0
  74. package/src/utils/appConfig.js +36 -0
  75. package/src/utils/beforeStart.js +55 -0
  76. package/src/utils/changeDeployVersion.js +119 -0
  77. package/src/utils/defineConfig.ts +81 -0
  78. package/src/utils/exec.js +7 -0
  79. package/src/utils/getConfig.js +26 -0
  80. package/src/utils/getOverride.js +33 -0
  81. package/tsconfig.json +21 -0
@@ -0,0 +1,153 @@
1
+ // src/auto-refactor.js
2
+ import fs from "fs-extra";
3
+ import paths from "./config/paths.js";
4
+ import path from "path";
5
+ import chalk from "chalk";
6
+ import { globby } from "globby";
7
+ import ora from "ora";
8
+ import { fileURLToPath } from "node:url";
9
+ import inquirer from "inquirer";
10
+ var pkg = fs.readJsonSync(fileURLToPath(import.meta.resolve("../package.json")));
11
+ async function step(msg, callback) {
12
+ const spinner = ora(msg).start();
13
+ try {
14
+ await callback(spinner);
15
+ spinner.succeed();
16
+ } catch (error) {
17
+ spinner.fail();
18
+ throw error;
19
+ }
20
+ }
21
+ async function autoRefactor() {
22
+ if (await fs.pathExists(paths.public)) {
23
+ console.log(chalk.green("已完成改造,不需要重复执行,如果运行报错请查看文档"));
24
+ console.log(`文档: ${chalk.underline(pkg.homepage)}`);
25
+ process.exit(0);
26
+ }
27
+ const appPkg = fs.readJsonSync(paths.package);
28
+ const answers = await inquirer.prompt([
29
+ {
30
+ type: "input",
31
+ name: "name",
32
+ message: "请输入模块名称,要求唯一,不能与其他工程相同",
33
+ default: appPkg.name,
34
+ validate: (v) => /^[a-z][a-z0-9_-]+$/.test(v) || "请按格式输入 /^[a-z][a-z0-9_-]+$/ 只能使用小写字母、连字符、下划线"
35
+ },
36
+ {
37
+ type: "input",
38
+ name: "version",
39
+ message: "版本号",
40
+ default: "1.0.0",
41
+ validate: (v) => /^\d+\.\d+\.\d+$/.test(v) || "请按格式输入 /^\\d+\\.\\d+\\.\\d+$/ 例如: 1.0.0"
42
+ },
43
+ {
44
+ type: "list",
45
+ name: "mode",
46
+ message: "项目使用的哪种模式",
47
+ choices: [
48
+ { name: "教育子工程模式", value: "" },
49
+ { name: "教育主工程模式", value: "main" },
50
+ { name: "独立模式", value: "single" }
51
+ ]
52
+ },
53
+ {
54
+ type: "checkbox",
55
+ name: "deploy",
56
+ message: "项目需要部署到哪里",
57
+ when: (ans) => ans.mode !== "single",
58
+ choices: [
59
+ { name: "校端", value: "-s" },
60
+ { name: "局端", value: "-b" },
61
+ { name: "公文端", value: "-d" }
62
+ ],
63
+ validate: (v) => !!v && v.length > 0 || "必须选一个"
64
+ }
65
+ ]);
66
+ appPkg.name = answers.name;
67
+ appPkg.version = answers.version;
68
+ await step("创建 public 文件夹", async () => {
69
+ await fs.mkdir(paths.public);
70
+ });
71
+ await step("移动 js 文件夹", async () => {
72
+ if (await fs.pathExists(path.resolve(paths.src, "js"))) {
73
+ await fs.move(path.resolve(paths.src, "js"), path.resolve(paths.public, "js"));
74
+ }
75
+ });
76
+ await step("移动 html 文件", async () => {
77
+ const HTMLFiles = await globby("*.html", { cwd: paths.src });
78
+ for (const file of HTMLFiles) {
79
+ await fs.move(path.resolve(paths.src, file), path.resolve(paths.public, file));
80
+ }
81
+ });
82
+ await step("删除 dll 文件夹", async () => {
83
+ if (await fs.pathExists(path.resolve(paths.src, "dll"))) {
84
+ await fs.remove(path.resolve(paths.src, "dll"));
85
+ }
86
+ });
87
+ await step("删除没用的 babel 和 webpack 配置", async () => {
88
+ const deleteFiles = [
89
+ ...await globby("{.,*}babel*"),
90
+ ...await globby("*webpack*"),
91
+ ...await globby("package-lock.json"),
92
+ paths.nodeModules,
93
+ paths.sshSftp
94
+ ];
95
+ for (const filePath of deleteFiles) {
96
+ await fs.remove(filePath);
97
+ }
98
+ });
99
+ await step("设置项目模式", () => {
100
+ if (answers.mode) {
101
+ appPkg.edu = { mode: answers.mode };
102
+ }
103
+ });
104
+ await step("修改 package.json 的 scripts", () => {
105
+ const scripts = appPkg.scripts;
106
+ scripts.start = "edu-scripts start";
107
+ scripts.build = "edu-scripts build";
108
+ scripts.analyze = "edu-scripts build --analyze";
109
+ if (answers.mode !== "single") {
110
+ scripts.deploy = `edu-scripts deploy ${answers.deploy.join(" ")}`;
111
+ } else {
112
+ scripts.deploy = `edu-scripts deploy`;
113
+ scripts["commit-dist"] = "edu-scripts commit-dist --rm-local";
114
+ }
115
+ scripts["one-key-deploy"] = "npm version patch";
116
+ scripts.postversion = "npm run build && npm run deploy";
117
+ });
118
+ await step("删除 babel/webpack 相关依赖", (spinner) => {
119
+ const deleteRe = /(babel|autoprefixer|webpack|loader|less|css|sass|hmr|ssh-sftp|regenerator-runtime|nowa|prettier)/i;
120
+ const deletePkgs = {
121
+ dependencies: [],
122
+ devDependencies: []
123
+ };
124
+ Object.entries(deletePkgs).forEach(([scope, pkgs]) => {
125
+ for (const key in appPkg[scope]) {
126
+ if (Object.hasOwnProperty.call(appPkg[scope], key)) {
127
+ if (deleteRe.test(key)) {
128
+ pkgs.push(key);
129
+ delete appPkg[scope][key];
130
+ }
131
+ }
132
+ }
133
+ });
134
+ spinner.clear();
135
+ console.log(`删除的pkgs
136
+ ${chalk.green(JSON.stringify(deletePkgs, null, 2))}
137
+ `);
138
+ appPkg.devDependencies["@qse/edu-scripts"] = "^" + pkg.version;
139
+ });
140
+ await fs.writeFile(paths.package, JSON.stringify(appPkg, null, 2), "utf-8");
141
+ console.log(
142
+ chalk.green(`
143
+ 改造还未完成,剩余步骤请查看文档
144
+ ${pkg.homepage}#/refactor
145
+
146
+ 运行 npm i 安装依赖
147
+ 运行 edu-scripts start 启动服务
148
+ `)
149
+ );
150
+ }
151
+ export {
152
+ autoRefactor as default
153
+ };
package/es/build.js ADDED
@@ -0,0 +1,58 @@
1
+ // src/build.js
2
+ import { rspack } from "@rspack/core";
3
+ import chalk from "chalk";
4
+ import getConfig from "./utils/getConfig.js";
5
+ import { measureFileSizesBeforeBuild, printFileSizesAfterBuild } from "./utils/FileSizeReporter.js";
6
+ import paths from "./config/paths.js";
7
+ import fs from "fs-extra";
8
+ import appConfig from "./utils/appConfig.js";
9
+ var WARN_AFTER_BUNDLE_GZIP_SIZE = appConfig.single ? 1024 * 1024 : 30 * 1024;
10
+ var WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
11
+ async function build(args) {
12
+ process.env.NODE_ENV = "production";
13
+ process.env.BABEL_ENV = "production";
14
+ process.env.BROWSERSLIST = ">0.2%, iOS>=9, ie 11, chrome>=49, not op_mini all";
15
+ if (args.analyze) {
16
+ process.env.ANALYZE = "1";
17
+ }
18
+ if (args.outputHtml) {
19
+ process.env.OUTPUT_HTML = "1";
20
+ }
21
+ const previousSizeMap = await measureFileSizesBeforeBuild(paths.dist);
22
+ fs.emptyDirSync(paths.dist);
23
+ if (appConfig.single) {
24
+ fs.copySync(paths.public, paths.resolveApp("dist"));
25
+ }
26
+ if (appConfig.mainProject && fs.existsSync(paths.static)) {
27
+ fs.copySync(paths.static, paths.resolveApp("dist", "static"));
28
+ }
29
+ rspack(getConfig(args), (error, stats) => {
30
+ if (error) {
31
+ console.log(chalk.red("编译失败"));
32
+ console.log(chalk.red(error.message || error));
33
+ process.exit(1);
34
+ }
35
+ if (stats.compilation.errors.length) {
36
+ console.log(chalk.red("编译失败"));
37
+ console.log(stats.toString({ all: false, errors: true, colors: true }));
38
+ process.exit(1);
39
+ }
40
+ console.log(stats.toString({ colors: true, preset: "errors-warnings", timings: true }));
41
+ printFileSizesAfterBuild(
42
+ stats,
43
+ previousSizeMap,
44
+ paths.dist,
45
+ WARN_AFTER_BUNDLE_GZIP_SIZE,
46
+ WARN_AFTER_CHUNK_GZIP_SIZE
47
+ );
48
+ if (appConfig.single) {
49
+ console.log(`打包完成,可以使用 ${chalk.green("@qse/ssh-sftp")} 自动部署代码到 v1`);
50
+ } else {
51
+ console.log(`打包完成,可以运行 ${chalk.green("npx edu-scripts deploy")} 部署代码到 v1`);
52
+ }
53
+ console.log();
54
+ });
55
+ }
56
+ export {
57
+ build as default
58
+ };
package/es/cli.js ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.js
4
+ import "./utils/beforeStart.js";
5
+ import fs from "fs-extra";
6
+ import yargs from "yargs";
7
+ import { fileURLToPath } from "node:url";
8
+ import start from "./start.js";
9
+ import build from "./build.js";
10
+ import deploy from "./deploy.js";
11
+ import autoRefactor from "./auto-refactor.js";
12
+ import commitDist from "./commit-dist.js";
13
+ import * as generator from "./generator.js";
14
+ var pkg = fs.readJsonSync(fileURLToPath(import.meta.resolve("../package.json")));
15
+ yargs(process.argv.slice(2)).usage(`教育工程化 webpack5 基础框架
16
+ 文档: ${pkg.homepage}`).command(
17
+ "start",
18
+ "开发",
19
+ (yargs2) => yargs2.option("port", { alias: "p", desc: "指定端口" }),
20
+ (args) => start(args)
21
+ ).command(
22
+ "build",
23
+ "打包",
24
+ (yargs2) => yargs2.option("analyze", {
25
+ alias: "a",
26
+ desc: "分析代码",
27
+ default: false,
28
+ boolean: true
29
+ }).option("output-html", {
30
+ alias: "o",
31
+ desc: "输出 html 文件",
32
+ default: false,
33
+ boolean: true
34
+ }),
35
+ (args) => build(args)
36
+ ).command(
37
+ "deploy",
38
+ "自动部署 dist 到 v1 服务器",
39
+ (yargs2) => yargs2.option("school", { alias: "s", desc: "上传到校端", default: false, boolean: true }).option("bureau", { alias: "b", desc: "上传到局端", default: false, boolean: true }).option("documentshelves", {
40
+ alias: "d",
41
+ desc: "上传到公文",
42
+ default: false,
43
+ boolean: true
44
+ }).option("compositionshelves", {
45
+ alias: "c",
46
+ desc: "上传到文曲智阅",
47
+ default: false,
48
+ boolean: true
49
+ }).option("compositionshelves-dingtalk", {
50
+ alias: "cd",
51
+ desc: "上传到文曲智阅(钉钉一方化)",
52
+ default: false,
53
+ boolean: true
54
+ }),
55
+ (args) => deploy(args)
56
+ ).command(
57
+ ["generator", "g"],
58
+ "自动生成代码",
59
+ (yargs2) => yargs2.command("override", "创建 override 文件", {}, (args) => generator.override(args)).command("tailwind", "创建 tailwind 文件", {}, (args) => generator.tailwind(args)).command("ts", "创建 tsconfig 文件", {}, (args) => generator.ts(args)).showHelpOnFail(true).demandCommand(1, "")
60
+ ).command("auto-refactor", "自动改造项目", {}, () => autoRefactor()).command(
61
+ "commit-dist",
62
+ "提交 dist 目录到 dist 分支",
63
+ (yargs2) => yargs2.option("rm-local", { desc: "提交完后删除本地 dist", type: "boolean" }),
64
+ (args) => commitDist(args)
65
+ ).showHelpOnFail(true).demandCommand(1, "").alias({ v: "version", h: "help" }).argv;
@@ -0,0 +1,83 @@
1
+ // src/commit-dist.js
2
+ import chalk from "chalk";
3
+ import paths from "./config/paths.js";
4
+ import fs from "fs-extra";
5
+ import cp from "child_process";
6
+ import tmp from "tmp";
7
+ var exec = (cmd, opts) => cp.execSync(cmd, { encoding: "utf-8", stdio: "pipe", ...opts });
8
+ function validateSVNRoot(root) {
9
+ const ls = exec(`svn ls ${root}`);
10
+ return ["trunk", "branches"].every((s) => ls.includes(s));
11
+ }
12
+ function getWorkingCopyInfo() {
13
+ exec(`svn up`);
14
+ const url = exec(`svn info --show-item url`).trim();
15
+ const revision = exec(`svn info --show-item last-changed-revision`).trim();
16
+ const author = exec(`svn info --show-item last-changed-author`).trim();
17
+ let branch = "trunk";
18
+ let root = url.replace(/\/trunk$/, "");
19
+ if (url.includes("/branches/")) {
20
+ branch = url.split("/").pop();
21
+ root = url.replace(/\/branches\/[^/]+$/, "");
22
+ }
23
+ let distBranchURL = root + "/branches/dist";
24
+ let distBranchDirURL = distBranchURL + "/" + branch;
25
+ if (!validateSVNRoot(root)) {
26
+ console.log(chalk.red("SVN目录不符合规则,必须包含 trunk branches"));
27
+ process.exit(1);
28
+ }
29
+ return { url, branch, revision, author, distBranchURL, distBranchDirURL, root };
30
+ }
31
+ function copyDistToRepo(info) {
32
+ const tmpdir = tmp.dirSync().name;
33
+ try {
34
+ exec(`svn ls ${info.distBranchDirURL} --depth empty`);
35
+ } catch (error) {
36
+ if (error.message.includes("non-existent")) {
37
+ exec(
38
+ `svn mkdir ${info.distBranchDirURL} --parents -m "[edu-scripts] create ${info.branch} dist"`
39
+ );
40
+ } else {
41
+ throw error;
42
+ }
43
+ }
44
+ exec(`svn co ${info.distBranchDirURL} ${tmpdir}`);
45
+ try {
46
+ exec(`svn rm * --force -q`, { cwd: tmpdir });
47
+ } catch (error) {
48
+ }
49
+ fs.copySync(paths.dist, tmpdir);
50
+ exec(`svn add * --force --auto-props --parents --depth infinity -q`, { cwd: tmpdir });
51
+ const msg = `[edu-scripts] commit ${info.branch} dist #${info.revision} @${info.author}`;
52
+ exec(`svn ci -m "${msg}"`, { cwd: tmpdir });
53
+ fs.removeSync(tmpdir);
54
+ }
55
+ async function commitDist(args) {
56
+ if (!fs.existsSync(paths.dist)) {
57
+ console.log(chalk.red("未找到 dist 文件夹,请先 edu-scpirts build"));
58
+ process.exit(1);
59
+ }
60
+ if (exec("svn st").trim().length) {
61
+ console.log(chalk.red("似乎存在未提交的代码,请提交后重试。运行 svn st 查看具体信息"));
62
+ process.exit(1);
63
+ }
64
+ const info = getWorkingCopyInfo();
65
+ console.log(
66
+ chalk.green(
67
+ [
68
+ `分支: ${info.branch}`,
69
+ `版本: ${info.revision}`,
70
+ `作者: ${info.author}`,
71
+ `地址: ${info.distBranchDirURL}`
72
+ ].join("\n")
73
+ )
74
+ );
75
+ copyDistToRepo(info);
76
+ if (args.rmLocal) {
77
+ fs.removeSync(paths.dist);
78
+ }
79
+ console.log(chalk.green("提交完成"));
80
+ }
81
+ export {
82
+ commitDist as default
83
+ };
@@ -0,0 +1,39 @@
1
+ // src/config/paths.js
2
+ import path from "path";
3
+ import fs from "fs-extra";
4
+ import { globbySync } from "globby";
5
+ function resolveApp(...filePath) {
6
+ return path.resolve(process.cwd(), ...filePath);
7
+ }
8
+ function getExistPath(...paths2) {
9
+ for (const path2 of paths2) {
10
+ if (fs.existsSync(path2)) {
11
+ return path2;
12
+ }
13
+ }
14
+ return paths2[0];
15
+ }
16
+ var paths = {
17
+ resolveApp,
18
+ eduAppEnv: resolveApp("src", "edu-app-env.d.ts"),
19
+ dist: resolveApp("dist"),
20
+ sshSftp: resolveApp(".sftprc.json"),
21
+ nodeModules: resolveApp("node_modules"),
22
+ tsconfig: resolveApp("tsconfig.json"),
23
+ jsconfig: resolveApp("jsconfig.json"),
24
+ package: resolveApp("package.json"),
25
+ tailwind: resolveApp("tailwind.config.js"),
26
+ indexJS: resolveApp("src", "index.js"),
27
+ pages: resolveApp("src", "pages"),
28
+ override: resolveApp("edu-scripts.override.js"),
29
+ indexHTML: globbySync("./public/*.html", { absolute: true }),
30
+ src: resolveApp("src"),
31
+ public: resolveApp("public"),
32
+ static: resolveApp("public", "static"),
33
+ theme: getExistPath(resolveApp("theme.json"), resolveApp("theme.js")),
34
+ mock: resolveApp("mock")
35
+ };
36
+ var paths_default = paths;
37
+ export {
38
+ paths_default as default
39
+ };
@@ -0,0 +1,6 @@
1
+ import type { RequestHandler } from 'express';
2
+ type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE';
3
+ type API = string;
4
+ export type MockConfig = Record<`${Method} ${API}`, string | number | null | undefined | boolean | Record<string, any> | RequestHandler>;
5
+ export declare function defineMock(config: MockConfig): MockConfig;
6
+ export {};
@@ -0,0 +1,7 @@
1
+ // src/config/plugins/mock-server/defineMock.ts
2
+ function defineMock(config) {
3
+ return config;
4
+ }
5
+ export {
6
+ defineMock
7
+ };
@@ -0,0 +1,122 @@
1
+ // src/config/plugins/mock-server/index.js
2
+ import paths from "../../paths.js";
3
+ import { globbySync } from "globby";
4
+ import chokidar from "chokidar";
5
+ import { debounce, memoize } from "lodash-es";
6
+ import chalk from "chalk";
7
+ import fs from "fs-extra";
8
+ import express from "express";
9
+ import cookieParser from "cookie-parser";
10
+ import multer from "multer";
11
+ import { pathToRegexp } from "path-to-regexp";
12
+ import { createRequire } from "node:module";
13
+ var require2 = createRequire(import.meta.url);
14
+ var { register } = require2("@swc-node/register/register");
15
+ var mockCache = {};
16
+ var isSetup = false;
17
+ var setupMock = debounce(function setupMock2() {
18
+ mockCache = {};
19
+ const files = globbySync(paths.mock, { expandDirectories: { extensions: ["js", "ts"] } });
20
+ if (isSetup) {
21
+ console.log(chalk.green("Mock files changed, reloaded"));
22
+ } else {
23
+ isSetup = true;
24
+ }
25
+ for (const file of files) {
26
+ delete require2.cache[require2.resolve(file)];
27
+ try {
28
+ let mock = require2(file);
29
+ mock = mock.default || mock;
30
+ for (const key in mock) {
31
+ const [method, path] = key.split(" ");
32
+ mockCache[key] = { method, path, handler: mock[key] };
33
+ }
34
+ } catch (e) {
35
+ console.error(chalk.red(`Mock file ${file} error: ${e.message}`));
36
+ }
37
+ }
38
+ }, 100);
39
+ var getPathReAndKeys = memoize((path) => {
40
+ const keys = [];
41
+ const re = pathToRegexp(path, keys);
42
+ return { re, keys };
43
+ });
44
+ function decodeParam(val) {
45
+ if (typeof val !== "string" || val.length === 0) {
46
+ return val;
47
+ }
48
+ try {
49
+ return decodeURIComponent(val);
50
+ } catch (err) {
51
+ if (err instanceof URIError) {
52
+ err.message = `Failed to decode param ' ${val} '`;
53
+ err.status = 400;
54
+ err.statusCode = 400;
55
+ }
56
+ throw err;
57
+ }
58
+ }
59
+ function mockMiddlewave(req, res, next) {
60
+ const { method, path } = req;
61
+ for (const key in mockCache) {
62
+ const mock = mockCache[key];
63
+ if (mock.method !== method)
64
+ continue;
65
+ const { keys, re } = getPathReAndKeys(mock.path);
66
+ const m = re.exec(path);
67
+ if (m) {
68
+ console.log(chalk.green(`Mock: ${key}`));
69
+ res.setHeader("X-Mock", key);
70
+ if (typeof mock.handler === "function") {
71
+ const params = {};
72
+ for (let i = 1; i < m.length; i += 1) {
73
+ const key2 = keys[i - 1];
74
+ const prop = key2.name;
75
+ const val = decodeParam(m[i]);
76
+ if (val !== void 0) {
77
+ params[prop] = val;
78
+ }
79
+ }
80
+ req.params = params;
81
+ const middelwaves = [
82
+ express.urlencoded({ limit: "5mb", extended: true }),
83
+ express.json({ limit: "5mb", strict: false }),
84
+ multer().any(),
85
+ cookieParser(),
86
+ mock.handler
87
+ ];
88
+ const throwNext = () => {
89
+ console.log(chalk.red(`Mock: ${key} don't use next()`));
90
+ res.sendStatus(500);
91
+ };
92
+ const mwNext = () => {
93
+ const middelwave = middelwaves.shift();
94
+ middelwave(req, res, middelwaves.length ? mwNext : throwNext);
95
+ };
96
+ mwNext();
97
+ } else {
98
+ res.json(mock.handler);
99
+ }
100
+ return;
101
+ }
102
+ }
103
+ next();
104
+ }
105
+ function setupMockServer(middelwaves, devServer) {
106
+ if (!fs.existsSync(paths.mock))
107
+ return;
108
+ register();
109
+ middelwaves.unshift({
110
+ name: "edu-scripts-mock-middelwave",
111
+ middleware: mockMiddlewave
112
+ });
113
+ console.log(
114
+ `<i> ${chalk.green.bold("[edu-scripts] Mock server created:")} ${chalk.cyan.bold(paths.mock)}`
115
+ );
116
+ chokidar.watch(paths.mock).on("all", setupMock);
117
+ return middelwaves;
118
+ }
119
+ var mock_server_default = setupMockServer;
120
+ export {
121
+ mock_server_default as default
122
+ };
@@ -0,0 +1,22 @@
1
+ // src/config/plugins/postcss-safe-area.js
2
+ var vars = [
3
+ "safe-area-inset-top",
4
+ "safe-area-inset-bottom",
5
+ "safe-area-inset-left",
6
+ "safe-area-inset-right"
7
+ ];
8
+ var expr = new RegExp(`env\\(\\s*(${vars.join("|")})\\s*,?\\s*([^)]+)?\\s*\\)`, "g");
9
+ var postcss_safe_area_default = () => {
10
+ return {
11
+ postcssPlugin: "postcss-safe-area",
12
+ Declaration(decl) {
13
+ const fallback = decl.value.replace(expr, (match, param, defaultValue) => defaultValue || "0");
14
+ if (fallback !== decl.value) {
15
+ decl.cloneBefore({ value: fallback });
16
+ }
17
+ }
18
+ };
19
+ };
20
+ export {
21
+ postcss_safe_area_default as default
22
+ };
@@ -0,0 +1,98 @@
1
+ // src/config/plugins/ws-utils-createSocketURL.js
2
+ function format(objURL) {
3
+ var protocol = objURL.protocol || "";
4
+ if (protocol && protocol.substr(-1) !== ":") {
5
+ protocol += ":";
6
+ }
7
+ var auth = objURL.auth || "";
8
+ if (auth) {
9
+ auth = encodeURIComponent(auth);
10
+ auth = auth.replace(/%3A/i, ":");
11
+ auth += "@";
12
+ }
13
+ var host = "";
14
+ if (objURL.hostname) {
15
+ host = auth + (objURL.hostname.indexOf(":") === -1 ? objURL.hostname : "[".concat(objURL.hostname, "]"));
16
+ if (objURL.port) {
17
+ host += ":".concat(objURL.port);
18
+ }
19
+ }
20
+ var pathname = objURL.pathname || "";
21
+ if (objURL.slashes) {
22
+ host = "//".concat(host || "");
23
+ if (pathname && pathname.charAt(0) !== "/") {
24
+ pathname = "/".concat(pathname);
25
+ }
26
+ } else if (!host) {
27
+ host = "";
28
+ }
29
+ var search = objURL.search || "";
30
+ if (search && search.charAt(0) !== "?") {
31
+ search = "?".concat(search);
32
+ }
33
+ var hash = objURL.hash || "";
34
+ if (hash && hash.charAt(0) !== "#") {
35
+ hash = "#".concat(hash);
36
+ }
37
+ pathname = pathname.replace(
38
+ /[?#]/g,
39
+ /**
40
+ * @param {string} match
41
+ * @returns {string}
42
+ */
43
+ function(match) {
44
+ return encodeURIComponent(match);
45
+ }
46
+ );
47
+ search = search.replace("#", "%23");
48
+ return "".concat(protocol).concat(host).concat(pathname).concat(search).concat(hash);
49
+ }
50
+ function createSocketURL(parsedURL) {
51
+ var hostname = parsedURL.hostname;
52
+ var isInAddrAny = hostname === "0.0.0.0" || hostname === "::" || hostname === "[::]";
53
+ if (isInAddrAny && self.location.hostname && self.location.protocol.indexOf("http") === 0) {
54
+ hostname = self.location.hostname;
55
+ }
56
+ var socketURLProtocol = parsedURL.protocol || self.location.protocol;
57
+ if (socketURLProtocol === "auto:" || hostname && isInAddrAny && self.location.protocol === "https:") {
58
+ socketURLProtocol = self.location.protocol;
59
+ }
60
+ socketURLProtocol = socketURLProtocol.replace(/^(?:http|.+-extension|file)/i, "ws");
61
+ var socketURLAuth = "";
62
+ if (parsedURL.username) {
63
+ socketURLAuth = parsedURL.username;
64
+ if (parsedURL.password) {
65
+ socketURLAuth = socketURLAuth.concat(":", parsedURL.password);
66
+ }
67
+ }
68
+ var socketURLHostname = (hostname || self.location.hostname || "localhost").replace(
69
+ /^\[(.*)\]$/,
70
+ "$1"
71
+ );
72
+ var socketURLPort = parsedURL.port;
73
+ if (!socketURLPort || socketURLPort === "0") {
74
+ socketURLPort = self.location.port;
75
+ }
76
+ var socketURLPathname = "/ws";
77
+ if (parsedURL.pathname && !parsedURL.fromCurrentScript) {
78
+ socketURLPathname = parsedURL.pathname;
79
+ if (hostname.indexOf("zhidianbao.cn") > -1 || hostname.indexOf("qsban.cn") > -1) {
80
+ var ctx = self.location.pathname.split("/")[1];
81
+ if (ctx) {
82
+ socketURLPathname = "/" + ctx + socketURLPathname;
83
+ }
84
+ }
85
+ }
86
+ return format({
87
+ protocol: socketURLProtocol,
88
+ auth: socketURLAuth,
89
+ hostname: socketURLHostname,
90
+ port: socketURLPort,
91
+ pathname: socketURLPathname,
92
+ slashes: true
93
+ });
94
+ }
95
+ var ws_utils_createSocketURL_default = createSocketURL;
96
+ export {
97
+ ws_utils_createSocketURL_default as default
98
+ };