@infly/libs 2.0.44 → 2.0.46

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 (43) hide show
  1. package/README.md +17 -5
  2. package/adapters/vue2/module/Permission.js +1 -1
  3. package/{module → adapters/vue2/module}/REST.js +3 -3
  4. package/{module → adapters/vue2/module}/TokenService.js +1 -1
  5. package/adapters/vue2/module/file-export.js +18 -0
  6. package/adapters/vue2/project-preview.js +6 -2
  7. package/adapters/vue2/script-config.js +1 -1
  8. package/adapters/vue2/store/modules/user.js +1 -1
  9. package/adapters/vue2/vite/index.js +95 -0
  10. package/adapters/vue2/vite/jest.config.js +11 -0
  11. package/adapters/vue2/{build/webpack5 → webpack5}/webpack.base.js +0 -55
  12. package/build/build-dist/index.js +2 -2
  13. package/{script/build → build/build-utils}/command.js +13 -4
  14. package/{script/build → build/build-utils}/git.js +6 -4
  15. package/{script/build → build/build-utils}/preview.js +4 -1
  16. package/module/Uts.js +47 -443
  17. package/package.json +18 -15
  18. package/script/git-automation/git-configure.js +29 -0
  19. package/script/git-automation/index.js +0 -14
  20. package/script/git-automation/submodule-status.js +113 -0
  21. package/script/git-automation/submodule-utils.js +18 -0
  22. package/tools/concurrency.js +30 -0
  23. package/tools/progress.js +63 -0
  24. package/tools/project-command.js +5 -1
  25. package/tools/workspace-config.js +145 -0
  26. package/adapters/vue2/build/webpack5/remove-legacy-assets-plugin.js +0 -84
  27. package/build/webpack5/inline-runtime-plugin.js +0 -1
  28. package/build/webpack5/remove-legacy-assets-plugin.js +0 -1
  29. package/build/webpack5/webpack.base.js +0 -1
  30. package/module/Permission.js +0 -1
  31. package/module/cjs/deep-merge.cjs +0 -38
  32. package/store/index.js +0 -1
  33. package/store/modules/user.js +0 -1
  34. package/tools/file-export.js +0 -167
  35. /package/{module → adapters/vue2/module}/Router.js +0 -0
  36. /package/adapters/vue2/{build/webpack5 → webpack5}/inline-runtime-plugin.js +0 -0
  37. /package/{script/build → build/build-utils}/deps.js +0 -0
  38. /package/{script/build → build/build-utils}/env.js +0 -0
  39. /package/{script/webhook/webhook.js → build/build-utils/webhook-single.js} +0 -0
  40. /package/{script/build → build/build-utils}/webhook.js +0 -0
  41. /package/module/cjs/{page-config.cjs → page-config.js} +0 -0
  42. /package/module/cjs/{request-url-rules.cjs → request-url-rules.js} +0 -0
  43. /package/module/cjs/{rest-error-rules.cjs → rest-error-rules.js} +0 -0
package/README.md CHANGED
@@ -4,11 +4,12 @@
4
4
 
5
5
  `@infly/libs` 是不受 Vue、React 等前端框架限制的独立 JavaScript 工具库。包根入口无副作用;HTTP、Token、文件处理、Docker/Compose、通用项目命令等能力可被不同技术栈使用。
6
6
 
7
- Vue 2 专属的 Permission、Vuex store、Vue CLI 预览和 webpack 配置集中在 `adapters/vue2/`,避免核心入口依赖 Vue 项目约定。
7
+ Vue 2 专属的 Permission、Vuex store、实例 mixin、Vue CLI 预览和 webpack 配置集中在 `adapters/vue2/`,避免核心入口依赖 Vue 项目约定。
8
8
 
9
9
  ## 注意事项
10
10
 
11
- 新代码应显式导入 Vue 2 适配路径。原有 `module/Permission.js`、`store/`、`tools/project-preview.js`、`script/index.js` 和 `build/webpack5/` 路径继续作为兼容转发保留。
11
+ 新代码应显式导入 Vue 2 适配路径。Webpack 适配器仅服务脱离
12
+ admin-monorepo 的子模块独立构建;Monorepo 根构建不会调用该实现。
12
13
 
13
14
  ## 软件架构
14
15
 
@@ -19,19 +20,30 @@ Vue 2 专属的 Permission、Vuex store、Vue CLI 预览和 webpack 配置集中
19
20
  ├── tools/ # 文件与项目命令等通用工具
20
21
  ├── build/
21
22
  │ ├── docker/ # Docker/Compose 工具
22
- ├── build-dist/ # 构建产物处理
23
- │ ├── build/webpack5/ # Vue 2 webpack 真实实现
24
- │ └── webpack5/ # 原路径兼容转发
23
+ └── build-dist/ # 构建产物处理
25
24
  ├── adapters/vue2/
25
+ │ ├── module/file-export.js # 注入请求与 Element UI 能力的 Vue2 导出 mixin
26
26
  │ ├── module/Permission.js # Vue Router/Vuex 权限适配
27
27
  │ ├── store/ # Vuex 模块
28
28
  │ ├── project-preview.js # Vue CLI 预览
29
29
  │ ├── script-config.js # Vue CLI 脚本模板
30
+ │ ├── vite/ # Monorepo Vite 定位与兼容入口
31
+ │ ├── webpack5/ # 独立子仓 Webpack 兼容适配器
30
32
  │ └── postinstall.js # 仅 Vue 2 项目执行初始化
31
33
  ├── bin/cli.js # 命令行入口
32
34
  └── dataInit/ # 公共枚举
33
35
  ```
34
36
 
37
+ Vue2 文件导出适配:
38
+
39
+ ```javascript
40
+ import { fileExportMixin } from "@infly/libs/adapters/vue2/module/file-export.js";
41
+
42
+ Vue.mixin(fileExportMixin);
43
+ ```
44
+
45
+ 适配器只负责从 Vue 实例注入 `$axios`、`$message`、`$msgbox` 和 `$loading`;确认、请求与下载流程由 `@infly/ts-libs` 的 `exportFile` 实现。`@infly/ui` 不公开该 mixin。
46
+
35
47
  根入口加载示例:
36
48
 
37
49
  ```javascript
@@ -1,5 +1,5 @@
1
1
  import Uts from "../../../module/Uts";
2
- import TokenService from "../../../module/TokenService";
2
+ import TokenService from "./TokenService.js";
3
3
 
4
4
  /**
5
5
  * 路由拦截器
@@ -8,16 +8,16 @@
8
8
  * 新项目(React/非 Vue 生态)请使用 @infly/ts-libs createHttpClient。
9
9
  */
10
10
  import axios from "axios";
11
- import Uts from "./Uts.js";
11
+ import Uts from "../../../module/Uts.js";
12
12
  import TokenService from "./TokenService.js";
13
13
  import {
14
14
  matchesConfiguredBaseURL,
15
15
  resolveInternalServiceURL
16
- } from "./cjs/request-url-rules.cjs";
16
+ } from "../../../module/cjs/request-url-rules.js";
17
17
  import {
18
18
  normalizeErrorPayload,
19
19
  resolveStatusErrorMessage
20
- } from "./cjs/rest-error-rules.cjs";
20
+ } from "../../../module/cjs/rest-error-rules.js";
21
21
 
22
22
  const baseURL = process.env.VUE_APP_BASE_API;
23
23
  const { env } = Uts.getEnv() || {};
@@ -8,7 +8,7 @@
8
8
  * 新项目(React/非 Vue 生态)请使用 @infly/ts-libs createStorageTokenStore。
9
9
  */
10
10
  // TokenService.js
11
- import Uts from "./Uts"; // 假设Uts工具类在同级目录或可访问路径
11
+ import Uts from "../../../module/Uts.js"; // 假设Uts工具类在同级目录或可访问路径
12
12
 
13
13
  let TOKEN_KEY = "accessToken"; // 默认的token键名
14
14
  let CHAT_TOKEN_KEY = "chatAccessToken"; // 默认的聊天token键名
@@ -0,0 +1,18 @@
1
+ import { exportFile } from "@infly/ts-libs";
2
+
3
+ const fileExportMixin = {
4
+ methods: {
5
+ async $exportFile(config = {}) {
6
+ return exportFile({
7
+ ...config,
8
+ message: this.$message || config.message || config.Message || {},
9
+ messageBox:
10
+ this.$msgbox || config.messageBox || config.MessageBox || {},
11
+ loading: this.$loading || config.loading || config.Loading || {},
12
+ request: config.request || this.$axios,
13
+ });
14
+ },
15
+ },
16
+ };
17
+
18
+ export { fileExportMixin };
@@ -84,6 +84,8 @@ async function init(skipBuild = false) {
84
84
  const serveStatic = require("serve-static");
85
85
  const app = connect();
86
86
  const noBuild = skipBuild || rawArgv.includes("--no-build");
87
+ // Vite 构建:使用 workspace runner 传入的 target 输出目录
88
+ const useViteOutput = buildContext.outputDir && fs.existsSync(buildContext.outputDir);
87
89
  const { devServer } = projectConfig || {};
88
90
  const { port: devServerPort } = devServer || {};
89
91
  projectConfig.port = devServerPort || DEFAULT_CONFIG.port;
@@ -91,6 +93,7 @@ async function init(skipBuild = false) {
91
93
  ...DEFAULT_CONFIG,
92
94
  ...projectConfig
93
95
  };
96
+ const serveDir = useViteOutput ? buildContext.outputDir : outputDir;
94
97
  const baseListenPort = port - 1000;
95
98
 
96
99
  if (!noBuild) {
@@ -101,16 +104,17 @@ async function init(skipBuild = false) {
101
104
 
102
105
  app.use(
103
106
  publicPath,
104
- serveStatic(outputDir, {
107
+ serveStatic(serveDir, {
105
108
  index: ["index.html", "/"]
106
109
  })
107
110
  );
108
111
 
109
112
  const server = app.listen(listenPort, function () {
110
113
  const previewUrl = `http://localhost:${listenPort}${publicPath}`;
114
+ const targetSuffix = buildContext.targetLabel ? ` (${buildContext.targetLabel})` : '';
111
115
 
112
116
  if (buildContext.batchPreview === true || process.env.INFLY_BATCH_PREVIEW === "1") {
113
- console.log(global.logColor.link, `${projectPackage.name || path.basename(projectRoot)}: ${previewUrl}`);
117
+ console.log(global.logColor.link, `${projectPackage.name || path.basename(projectRoot)}${targetSuffix}: ${previewUrl}`);
114
118
  return;
115
119
  }
116
120
 
@@ -16,7 +16,7 @@ module.exports = {
16
16
  },
17
17
  {
18
18
  key: "build:stage",
19
- value: "infly-libs beforeBuild && vue-cli-service build --mode staging && infly-libs afterBuild"
19
+ value: "infly-libs beforeBuild && vue-cli-service build --mode staging --no-module && infly-libs afterBuild"
20
20
  },
21
21
  {
22
22
  key: "build:test",
@@ -1,5 +1,5 @@
1
1
  import Uts from "../../../../module/Uts.js";
2
- import TokenService from "../../../../module/TokenService.js";
2
+ import TokenService from "../../module/TokenService.js";
3
3
 
4
4
  const CONFIG = {
5
5
  router: {},
@@ -0,0 +1,95 @@
1
+ const fs = require("node:fs");
2
+ const path = require("node:path");
3
+
4
+ function findAdminMonorepoRoot(startDir = process.cwd()) {
5
+ let directory = path.resolve(startDir);
6
+ for (;;) {
7
+ if (
8
+ fs.existsSync(path.join(directory, "pnpm-workspace.yaml"))
9
+ && fs.existsSync(path.join(directory, "configs/vite-configs/registry.js"))
10
+ ) return directory;
11
+ const parent = path.dirname(directory);
12
+ if (parent === directory) return null;
13
+ directory = parent;
14
+ }
15
+ }
16
+
17
+ function resolveAppScssImport(importPath, importer, appRoot) {
18
+ const cleanImporter = importer.replace(/[?#].*$/, "");
19
+ if (importPath.startsWith("@/")) {
20
+ return path.resolve(appRoot, "src", importPath.slice(2));
21
+ }
22
+ if (importPath.startsWith("./") || importPath.startsWith("../")) {
23
+ return path.resolve(path.dirname(cleanImporter), importPath);
24
+ }
25
+ if (path.isAbsolute(importPath)) return path.resolve(importPath);
26
+ return null;
27
+ }
28
+
29
+ function transformScssExportImports(code, importer, options) {
30
+ const { appRoot, readFile = (file) => fs.readFileSync(file, "utf8") } = options;
31
+ return code.replace(
32
+ /import\s+([\w$]+)\s+from\s+(["'])([^"'?]+\.scss)\2\s*;?/g,
33
+ (statement, binding, quote, importPath) => {
34
+ const resolved = resolveAppScssImport(importPath, importer, appRoot);
35
+ if (!resolved) return statement;
36
+ let scss;
37
+ try {
38
+ scss = readFile(resolved);
39
+ } catch (_) {
40
+ return statement;
41
+ }
42
+ if (typeof scss !== "string") return statement;
43
+ const exportBlock = scss.match(/:export\s*\{([\s\S]*?)\}/);
44
+ if (!exportBlock) return statement;
45
+
46
+ const variables = new Map();
47
+ for (const match of scss.matchAll(/^\s*\$([\w-]+)\s*:\s*([^;]+);/gm)) {
48
+ variables.set(match[1], match[2].trim());
49
+ }
50
+ const exported = {};
51
+ for (const match of exportBlock[1].matchAll(/([\w-]+)\s*:\s*([^;]+);/g)) {
52
+ const rawValue = match[2].trim();
53
+ const variableName = rawValue.match(/^\$([\w-]+)$/);
54
+ exported[match[1]] = variableName && variables.has(variableName[1])
55
+ ? variables.get(variableName[1])
56
+ : rawValue;
57
+ }
58
+ return `import ${quote}${importPath}${quote};\nconst ${binding} = ${JSON.stringify(exported)};`;
59
+ },
60
+ );
61
+ }
62
+
63
+ function createScssExportCompatPlugin(appRoot) {
64
+ return {
65
+ name: "infly-vue2:scss-export-compat",
66
+ enforce: "pre",
67
+ transform(code, id) {
68
+ if (
69
+ id.includes("node_modules")
70
+ || (!id.includes(".vue") && !/\.[cm]?[jt]sx?(?:[?#].*)?$/.test(id))
71
+ || !/import\s+[\w$]+\s+from\s+["'][^"']+\.scss["']/.test(code)
72
+ ) return null;
73
+ const transformed = transformScssExportImports(code, id, { appRoot });
74
+ return transformed === code ? null : { code: transformed, map: null };
75
+ },
76
+ };
77
+ }
78
+
79
+ function addAppRootSassLoadPath(css, appRoot) {
80
+ if (!css.preprocessorOptions) css.preprocessorOptions = {};
81
+ if (!css.preprocessorOptions.scss) css.preprocessorOptions.scss = {};
82
+ const loadPaths = css.preprocessorOptions.scss.loadPaths || [];
83
+ const resolvedAppRoot = path.resolve(appRoot);
84
+ css.preprocessorOptions.scss.loadPaths = loadPaths.includes(resolvedAppRoot)
85
+ ? loadPaths
86
+ : [...loadPaths, resolvedAppRoot];
87
+ return css;
88
+ }
89
+
90
+ module.exports = {
91
+ addAppRootSassLoadPath,
92
+ findAdminMonorepoRoot,
93
+ transformScssExportImports,
94
+ createScssExportCompatPlugin,
95
+ };
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ moduleFileExtensions: ["js", "json", "vue"],
3
+ moduleNameMapper: {
4
+ "^@/(.*)$": "<rootDir>/src/$1",
5
+ },
6
+ testEnvironment: "jsdom",
7
+ transform: {
8
+ "^.+\\.js$": "babel-jest",
9
+ ".*\\.(vue)$": "@vue/vue2-jest",
10
+ },
11
+ };
@@ -2,8 +2,6 @@
2
2
 
3
3
  const path = require("path");
4
4
  const InlineRuntimePlugin = require("./inline-runtime-plugin");
5
- const RemoveLegacyAssetsPlugin = require("./remove-legacy-assets-plugin");
6
-
7
5
  // 环境变量与常量配置
8
6
  const ENV = {
9
7
  IS_PROD: ["production", "staging"].includes(process.env.NODE_ENV),
@@ -11,13 +9,6 @@ const ENV = {
11
9
  IS_DEV: process.env.ENV === "development"
12
10
  };
13
11
 
14
- // 强制禁用 modern mode(staging 环境)
15
- if (ENV.IS_STAGING) {
16
- process.env.VUE_CLI_MODERN_MODE = "false";
17
- process.env.VUE_CLI_MODERN_BUILD = "false";
18
- console.log("\n\x1b[36m⚡ Building for STAGING with Modern Bundle only (仅现代浏览器)...\x1b[0m");
19
- }
20
-
21
12
  /**
22
13
  * 解析项目路径(兼容monorepo)
23
14
  * @param {string} dir 相对路径
@@ -151,52 +142,6 @@ function chainWebpack(config, options = {}) {
151
142
  });
152
143
  }
153
144
 
154
- // 强制禁用 modern mode(staging 环境)
155
- if (ENV.IS_STAGING) {
156
- // 删除 @vue/cli-service 的 modern mode 相关插件
157
- config.plugins.delete("modern-mode-plugin");
158
-
159
- // 强制修改 HTML 插件配置
160
- config.plugin("html").tap((args) => {
161
- args[0] = args[0] || {};
162
-
163
- // 彻底禁用 modern mode
164
- args[0].modern = false;
165
- args[0].modulePreload = false;
166
- args[0].scriptLoading = "defer";
167
-
168
- // 删除所有 modern/legacy 相关的钩子和回调
169
- delete args[0].modernBuild;
170
- delete args[0].legacyBuild;
171
- delete args[0].modernManifest;
172
- delete args[0].legacyManifest;
173
-
174
- // 关键:重写 templateParameters 来阻止 modern mode 注入
175
- const originalTemplateParameters = args[0].templateParameters || {};
176
- args[0].templateParameters = (compilation, assets, assetTags, options) => {
177
- const params =
178
- typeof originalTemplateParameters === "function"
179
- ? originalTemplateParameters(compilation, assets, assetTags, options)
180
- : originalTemplateParameters;
181
-
182
- // 移除 modern/legacy 相关的参数
183
- if (params) {
184
- delete params.modernBuild;
185
- delete params.legacyBuild;
186
- delete params.modernManifest;
187
- delete params.legacyManifest;
188
- }
189
-
190
- return params;
191
- };
192
-
193
- return args;
194
- });
195
-
196
- // 添加自定义插件来处理 legacy 文件问题
197
- config.plugin("remove-legacy-assets").use(RemoveLegacyAssetsPlugin);
198
- }
199
-
200
145
  // Babel 配置:只转译现代浏览器 + TypeScript(支持 @infly/ts-libs)
201
146
  config.module
202
147
  .rule("js")
@@ -21,7 +21,7 @@ global.logColor = {
21
21
  const { zipSync } = require("./zip.js");
22
22
  const { buildList } = require("../../script");
23
23
  const { init: previewInit } = require("../../tools/project-preview.js");
24
- const { postVersionFileAndMsg } = require("../../script/webhook/webhook.js");
24
+ const { postVersionFileAndMsg } = require("../build-utils/webhook-single.js");
25
25
  const { scriptWrite, targetProjectFileResolve, currentProjectFileResolve } = require("../../tools/file-process.js");
26
26
  const { shouldManageBuildScripts } = require("./script-management.js");
27
27
  const {
@@ -34,7 +34,7 @@ const {
34
34
  checkSingleDirGitStatus,
35
35
  pullSingleDirFromBranch
36
36
  } = require("../../script/git-automation");
37
- const { resolveSiblingAppDeps } = require("../../script/build/deps");
37
+ const { resolveSiblingAppDeps } = require("../build-utils/deps");
38
38
 
39
39
  const scriptEvent = process.env.npm_lifecycle_event;
40
40
  const isBuilZipScript = process.env.npm_lifecycle_event;
@@ -2,14 +2,19 @@ const { spawn } = require("child_process");
2
2
 
3
3
  function run(command, args, options = {}) {
4
4
  return new Promise((resolve, reject) => {
5
- const child = spawn(command, args, {
5
+ const useShell = options.shell !== undefined ? options.shell : process.platform === "win32";
6
+ // Avoid DEP0190: when shell=true, pass command+args as single string
7
+ const [cmd, cmdArgs] = useShell
8
+ ? [[command, ...args].join(" "), []]
9
+ : [command, args];
10
+ const child = spawn(cmd, cmdArgs, {
6
11
  cwd: options.cwd || process.cwd(),
7
12
  env: {
8
13
  ...process.env,
9
14
  ...(options.env || {})
10
15
  },
11
16
  stdio: options.stdio || "inherit",
12
- shell: process.platform === "win32"
17
+ shell: useShell
13
18
  });
14
19
 
15
20
  child.on("close", (code) => {
@@ -25,14 +30,18 @@ function run(command, args, options = {}) {
25
30
  }
26
31
 
27
32
  function spawnBackground(command, args, options = {}) {
28
- const child = spawn(command, args, {
33
+ const useShell = options.shell !== undefined ? options.shell : process.platform === "win32";
34
+ const [cmd, cmdArgs] = useShell
35
+ ? [[command, ...args].join(" "), []]
36
+ : [command, args];
37
+ const child = spawn(cmd, cmdArgs, {
29
38
  cwd: options.cwd || process.cwd(),
30
39
  env: {
31
40
  ...process.env,
32
41
  ...(options.env || {})
33
42
  },
34
43
  stdio: options.stdio || "inherit",
35
- shell: process.platform === "win32"
44
+ shell: useShell
36
45
  });
37
46
 
38
47
  child.on("error", (error) => {
@@ -1,7 +1,7 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
- const { checkAndUpdatePackages } = require("../git-automation");
4
- const { gitOutput, findGitRepo, getGitCommonDir } = require("../git-automation/git-utils");
3
+ const { checkAndUpdatePackages } = require("../../script/git-automation");
4
+ const { gitOutput, findGitRepo, getGitCommonDir } = require("../../script/git-automation/git-utils");
5
5
  const { run } = require("./command");
6
6
 
7
7
  function getTargetBranch(rootPackageJson, mode) {
@@ -77,9 +77,11 @@ function getDistRepoInfo(rootDir, pkg, targetBranch, options = {}) {
77
77
  fs.existsSync(nextConfigTs)
78
78
  );
79
79
 
80
- let outputDir;
80
+ let outputDir = pkg.viteOutputDir;
81
81
 
82
- if (hasVueConfig) {
82
+ if (outputDir) {
83
+ // Vite 注册表已经提供经过校验的 dist 根,禁止再执行历史 vue.config.js。
84
+ } else if (hasVueConfig) {
83
85
  outputDir = require(vueConfigPath).outputDir;
84
86
  } else if (hasNextConfig) {
85
87
  outputDir = pkg.packageJson.infly?.buildConfigs?.outputPath;
@@ -34,7 +34,10 @@ function startBatchPreviews(rootDir, packages) {
34
34
  const child = spawnBackground("infly-libs", ["preview", "--no-build"], {
35
35
  cwd: path.join(rootDir, pkg.dir),
36
36
  env: createBuildContext({
37
- batchPreview: true
37
+ batchPreview: true,
38
+ outputDir: pkg.targetOutputDir || undefined,
39
+ target: pkg.targetKey || undefined,
40
+ targetLabel: pkg.targetLabel || undefined,
38
41
  })
39
42
  });
40
43