@dazhicheng/common 1.0.5 → 1.0.7
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/.env +5 -2
- package/.env.dev +16 -0
- package/.env.development +29 -0
- package/.env.production +10 -0
- package/.env.sit +10 -0
- package/.env.test +16 -0
- package/.gitlab-ci.yml +74 -0
- package/.prettierignore +2 -0
- package/{.prettierrc → .prettierrc.txt} +2 -1
- package/.stylelintignore +3 -0
- package/{.stylelintrc.cjs → .stylelintrc.cjs.txt} +13 -7
- package/Dockerfile +1 -1
- package/{commitlint.config.cjs → commitlint.config.cjs.txt} +1 -1
- package/{eslint.config.mjs → eslint.config.mjs.txt} +15 -11
- package/nginx_dev.conf +26 -26
- package/nginx_test.conf +26 -26
- package/package.json +13 -5
- package/pnpm-workspace.yaml +9 -0
- package/sync-common.mjs +150 -122
- package/tsconfig.json +29 -29
package/.env
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# 版本号
|
|
4
4
|
VITE_VERSION = 1.0.0
|
|
5
5
|
|
|
6
|
+
<<<VITE_PORT>>>
|
|
6
7
|
|
|
7
8
|
# 应用部署基础路径(如部署在子目录 /admin,则设置为 /admin/)
|
|
8
9
|
VITE_BASE_URL = /
|
|
@@ -10,11 +11,13 @@ VITE_BASE_URL = /
|
|
|
10
11
|
# 权限模式【 frontend 前端模式 / backend 后端模式 】
|
|
11
12
|
VITE_ACCESS_MODE = backend
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
VITE_WITH_CREDENTIALS = false
|
|
14
|
+
<<<VITE_WITH_CREDENTIALS>>>
|
|
15
15
|
|
|
16
16
|
# 是否打开路由信息
|
|
17
17
|
VITE_OPEN_ROUTE_INFO = false
|
|
18
18
|
|
|
19
19
|
# 锁屏加密密钥
|
|
20
20
|
VITE_LOCK_ENCRYPT_KEY = s3cur3k3y4adpro
|
|
21
|
+
|
|
22
|
+
# 飞书扫码登录回调地址
|
|
23
|
+
VITE_FEISHU_REDIRECT_URI = http://120.76.61.203:13000/feishuOAuth
|
package/.env.dev
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# 【开发】环境变量
|
|
2
|
+
|
|
3
|
+
# 应用部署基础路径(如部署在子目录 /admin,则设置为 /admin/)
|
|
4
|
+
VITE_BASE_URL = /
|
|
5
|
+
|
|
6
|
+
# API 地址前缀
|
|
7
|
+
VITE_API_URL = dev-api
|
|
8
|
+
|
|
9
|
+
# Delete console
|
|
10
|
+
VITE_DROP_CONSOLE = true
|
|
11
|
+
|
|
12
|
+
# 飞书扫码登录回调地址
|
|
13
|
+
# VITE_FEISHU_REDIRECT_URI = http://120.76.61.203:13006/feishuOAuth
|
|
14
|
+
|
|
15
|
+
# webSocket地址
|
|
16
|
+
VITE_WEBSOCKET_URL = ws://192.168.128.215:11000
|
package/.env.development
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# 【本地开发】环境变量
|
|
2
|
+
|
|
3
|
+
# 应用部署基础路径(如部署在子目录 /admin,则设置为 /admin/)
|
|
4
|
+
VITE_BASE_URL = /
|
|
5
|
+
|
|
6
|
+
# API 请求基础路径(开发环境设置为 / 使用代理,生产环境设置为完整后端地址)
|
|
7
|
+
VITE_API_URL = dev
|
|
8
|
+
VITE_MOCK_ENABLED = true
|
|
9
|
+
|
|
10
|
+
# 代理目标地址(开发环境通过 Vite 代理转发请求到此地址,解决跨域问题)
|
|
11
|
+
VITE_API_PROXY_URL = https://m1.apifoxmock.com/m1/6400575-6097373-default
|
|
12
|
+
VITE_API_PROXY_URL_dev = http://192.168.128.215:11000
|
|
13
|
+
VITE_API_MOCK = http://192.168.129.158:9998/mock/
|
|
14
|
+
VITE_API_PROXY_URL_test = http://192.168.127.72:11000/
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
VITE_API_PROXY_URL_dev_yun = http://116.6.49.180:11000/
|
|
18
|
+
VITE_API_PROXY_URL_test_yun = http://116.6.49.180:11001/
|
|
19
|
+
|
|
20
|
+
<<<VITE_API_PROXY_URL>>>
|
|
21
|
+
|
|
22
|
+
# Delete console
|
|
23
|
+
VITE_DROP_CONSOLE = false
|
|
24
|
+
|
|
25
|
+
# 飞书扫码登录回调地址
|
|
26
|
+
# VITE_FEISHU_REDIRECT_URI = http://120.76.61.203:13006/feishuOAuth
|
|
27
|
+
|
|
28
|
+
# webSocket地址
|
|
29
|
+
VITE_WEBSOCKET_URL = ws://192.168.128.215:11000
|
package/.env.production
ADDED
package/.env.sit
ADDED
package/.env.test
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# 【测试】环境变量
|
|
2
|
+
|
|
3
|
+
# 应用部署基础路径(如部署在子目录 /admin,则设置为 /admin/)
|
|
4
|
+
VITE_BASE_URL = /
|
|
5
|
+
|
|
6
|
+
# API 地址前缀
|
|
7
|
+
VITE_API_URL = test-api
|
|
8
|
+
|
|
9
|
+
# Delete console
|
|
10
|
+
VITE_DROP_CONSOLE = true
|
|
11
|
+
|
|
12
|
+
# 飞书扫码登录回调地址
|
|
13
|
+
VITE_FEISHU_REDIRECT_URI = http://120.76.61.203:23000/feishuOAuth
|
|
14
|
+
|
|
15
|
+
# webSocket地址
|
|
16
|
+
VITE_WEBSOCKET_URL = ws://116.6.49.180:11001
|
package/.gitlab-ci.yml
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
stages:
|
|
2
|
+
- MR_TEST
|
|
3
|
+
- develop
|
|
4
|
+
- test
|
|
5
|
+
- sit
|
|
6
|
+
|
|
7
|
+
variables:
|
|
8
|
+
DOCKER_BUILDKIT: 1
|
|
9
|
+
|
|
10
|
+
MR 构建测试:
|
|
11
|
+
stage: MR_TEST
|
|
12
|
+
image: docker:20.10.20
|
|
13
|
+
tags:
|
|
14
|
+
- MR_TEST
|
|
15
|
+
script:
|
|
16
|
+
# 构建镜像(不部署)
|
|
17
|
+
- docker build --build-arg NODE_ENV=dev --no-cache -t a-fulfillment-mr-test:mr-$CI_MERGE_REQUEST_IID .
|
|
18
|
+
# 验证镜像构建成功
|
|
19
|
+
- docker images | grep a-fulfillment-mr-test
|
|
20
|
+
rules:
|
|
21
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"
|
|
22
|
+
|
|
23
|
+
开发环境发版:
|
|
24
|
+
stage: develop
|
|
25
|
+
image: docker:20.10.20
|
|
26
|
+
tags:
|
|
27
|
+
- develop
|
|
28
|
+
resource_group: deploy-develop # 重点
|
|
29
|
+
script:
|
|
30
|
+
<<<script_开发环境发版>>>
|
|
31
|
+
# 清理悬空镜像
|
|
32
|
+
- docker image prune -f || true
|
|
33
|
+
only:
|
|
34
|
+
- develop
|
|
35
|
+
|
|
36
|
+
开发环境发版_107:
|
|
37
|
+
stage: develop
|
|
38
|
+
image: docker:20.10.20
|
|
39
|
+
tags:
|
|
40
|
+
- develop_107
|
|
41
|
+
resource_group: deploy-develop_107 # 重点
|
|
42
|
+
script:
|
|
43
|
+
<<<script_开发环境发版_107>>>
|
|
44
|
+
# 清理悬空镜像
|
|
45
|
+
- docker image prune -f || true
|
|
46
|
+
only:
|
|
47
|
+
- develop
|
|
48
|
+
|
|
49
|
+
# 测试环境 -----------------------------------------------------------------------------------------------
|
|
50
|
+
测试环境发版:
|
|
51
|
+
stage: test
|
|
52
|
+
image: docker:20.10.20
|
|
53
|
+
tags:
|
|
54
|
+
- test
|
|
55
|
+
resource_group: deploy-test # 重点
|
|
56
|
+
script:
|
|
57
|
+
<<<script_测试环境发版>>>
|
|
58
|
+
# 清理悬空镜像
|
|
59
|
+
- docker image prune -f || true
|
|
60
|
+
only:
|
|
61
|
+
- test
|
|
62
|
+
|
|
63
|
+
测试环境发版_107:
|
|
64
|
+
stage: test
|
|
65
|
+
image: docker:20.10.20
|
|
66
|
+
tags:
|
|
67
|
+
- test_107
|
|
68
|
+
resource_group: deploy-test_107 # 重点
|
|
69
|
+
script:
|
|
70
|
+
<<<script_测试环境发版_107>>>
|
|
71
|
+
# 清理悬空镜像
|
|
72
|
+
- docker image prune -f || true
|
|
73
|
+
only:
|
|
74
|
+
- test
|
package/.prettierignore
ADDED
package/.stylelintignore
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
+
// 继承推荐规范配置
|
|
2
3
|
extends: [
|
|
3
4
|
'stylelint-config-standard',
|
|
4
5
|
'stylelint-config-recommended-scss',
|
|
@@ -6,6 +7,7 @@ module.exports = {
|
|
|
6
7
|
'stylelint-config-html/vue',
|
|
7
8
|
'stylelint-config-recess-order',
|
|
8
9
|
],
|
|
10
|
+
// 指定不同文件对应的解析器
|
|
9
11
|
overrides: [
|
|
10
12
|
{
|
|
11
13
|
files: ['**/*.{vue,html}'],
|
|
@@ -16,26 +18,30 @@ module.exports = {
|
|
|
16
18
|
customSyntax: 'postcss-scss',
|
|
17
19
|
},
|
|
18
20
|
],
|
|
21
|
+
// 自定义规则
|
|
19
22
|
rules: {
|
|
20
|
-
'import-notation': 'string',
|
|
21
|
-
'selector-class-pattern': null,
|
|
22
|
-
'custom-property-pattern': null,
|
|
23
|
-
'keyframes-name-pattern': null,
|
|
24
|
-
'no-descending-specificity': null,
|
|
25
|
-
'no-empty-source': null,
|
|
26
|
-
'property-no-vendor-prefix': null,
|
|
23
|
+
'import-notation': 'string', // 指定导入CSS文件的方式("string"|"url")
|
|
24
|
+
'selector-class-pattern': null, // 选择器类名命名规则
|
|
25
|
+
'custom-property-pattern': null, // 自定义属性命名规则
|
|
26
|
+
'keyframes-name-pattern': null, // 动画帧节点样式命名规则
|
|
27
|
+
'no-descending-specificity': null, // 允许无降序特异性
|
|
28
|
+
'no-empty-source': null, // 允许空样式
|
|
29
|
+
'property-no-vendor-prefix': null, // 允许属性前缀
|
|
30
|
+
// 允许 global 、export 、deep伪类
|
|
27
31
|
'selector-pseudo-class-no-unknown': [
|
|
28
32
|
true,
|
|
29
33
|
{
|
|
30
34
|
ignorePseudoClasses: ['global', 'export', 'deep'],
|
|
31
35
|
},
|
|
32
36
|
],
|
|
37
|
+
// 允许未知属性
|
|
33
38
|
'property-no-unknown': [
|
|
34
39
|
true,
|
|
35
40
|
{
|
|
36
41
|
ignoreProperties: [],
|
|
37
42
|
},
|
|
38
43
|
],
|
|
44
|
+
// 允许未知规则
|
|
39
45
|
'at-rule-no-unknown': [
|
|
40
46
|
true,
|
|
41
47
|
{
|
package/Dockerfile
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
// 从 URL 和路径模块中导入必要的功能
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path, { dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
|
|
6
|
+
// 从 ESLint 插件中导入推荐配置
|
|
1
7
|
import pluginJs from '@eslint/js';
|
|
2
8
|
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
|
3
9
|
import pluginVue from 'eslint-plugin-vue';
|
|
4
10
|
import globals from 'globals';
|
|
5
11
|
import tseslint from 'typescript-eslint';
|
|
6
12
|
|
|
13
|
+
// 使用 import.meta.url 获取当前模块的路径
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
|
|
17
|
+
// 读取 .auto-import.json 文件的内容,并将其解析为 JSON 对象
|
|
18
|
+
const autoImportConfig = JSON.parse(
|
|
19
|
+
fs.readFileSync(path.resolve(__dirname, '.auto-import.json'), 'utf-8'),
|
|
20
|
+
);
|
|
21
|
+
|
|
7
22
|
export default [
|
|
8
23
|
// 指定文件匹配规则
|
|
9
24
|
{
|
|
@@ -46,17 +61,6 @@ export default [
|
|
|
46
61
|
'@typescript-eslint/no-unused-vars': 'off', // 禁用 TypeScript 未使用的变量检查
|
|
47
62
|
},
|
|
48
63
|
},
|
|
49
|
-
{
|
|
50
|
-
files: ['**/*.vue'],
|
|
51
|
-
languageOptions: {
|
|
52
|
-
parserOptions: {
|
|
53
|
-
parser: tseslint.parser,
|
|
54
|
-
ecmaFeatures: {
|
|
55
|
-
jsx: true,
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
64
|
// vue 规则
|
|
61
65
|
{
|
|
62
66
|
files: ['**/*.vue'],
|
package/nginx_dev.conf
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
# HTTP 服务器 - 保持原有配置
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
proxy_set_header
|
|
18
|
-
proxy_set_header X-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
# HTTP 服务器 - 保持原有配置
|
|
2
|
+
server {
|
|
3
|
+
<<<listen>>>
|
|
4
|
+
server_name localhost;
|
|
5
|
+
charset utf-8;
|
|
6
|
+
|
|
7
|
+
root /usr/share/nginx/html;
|
|
8
|
+
index index.html;
|
|
9
|
+
|
|
10
|
+
location / {
|
|
11
|
+
try_files $uri $uri/ /index.html;
|
|
12
|
+
<<<CORS配置>>>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
location /dev-api/ {
|
|
16
|
+
proxy_set_header Host $host;
|
|
17
|
+
proxy_set_header X-Real-Ip $remote_addr;
|
|
18
|
+
proxy_set_header X-Forwarded-For $remote_addr;
|
|
19
|
+
proxy_pass http://116.6.49.180:11000/;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
error_page 500 502 503 504 /50x.html;
|
|
23
|
+
location = /50x.html {
|
|
24
|
+
root html;
|
|
25
|
+
}
|
|
26
|
+
}
|
package/nginx_test.conf
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
# HTTP 服务器 - 保持原有配置
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
proxy_set_header
|
|
18
|
-
proxy_set_header X-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
# HTTP 服务器 - 保持原有配置
|
|
2
|
+
server {
|
|
3
|
+
<<<listen>>>
|
|
4
|
+
server_name localhost;
|
|
5
|
+
charset utf-8;
|
|
6
|
+
|
|
7
|
+
root /usr/share/nginx/html;
|
|
8
|
+
index index.html;
|
|
9
|
+
|
|
10
|
+
location / {
|
|
11
|
+
try_files $uri $uri/ /index.html;
|
|
12
|
+
<<<CORS配置>>>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
location /test-api/ {
|
|
16
|
+
proxy_set_header Host $host;
|
|
17
|
+
proxy_set_header X-Real-Ip $remote_addr;
|
|
18
|
+
proxy_set_header X-Forwarded-For $remote_addr;
|
|
19
|
+
proxy_pass http://116.6.49.180:11001/;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
error_page 500 502 503 504 /50x.html;
|
|
23
|
+
location = /50x.html {
|
|
24
|
+
root html;
|
|
25
|
+
}
|
|
26
|
+
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dazhicheng/common",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "共享配置文件",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./src/types/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
|
-
"commitlint.config.cjs",
|
|
8
|
+
"commitlint.config.cjs.txt",
|
|
9
9
|
".husky",
|
|
10
|
-
".
|
|
11
|
-
".
|
|
10
|
+
".prettierignore",
|
|
11
|
+
".prettierrc.txt",
|
|
12
|
+
".stylelintrc.cjs.txt",
|
|
12
13
|
".stylelintignore",
|
|
13
14
|
".gitignore",
|
|
14
15
|
".gitattributes",
|
|
15
16
|
".env",
|
|
16
|
-
"
|
|
17
|
+
".env.dev",
|
|
18
|
+
".env.development",
|
|
19
|
+
".env.production",
|
|
20
|
+
".env.sit",
|
|
21
|
+
".env.test",
|
|
22
|
+
".gitlab-ci.yml",
|
|
23
|
+
"pnpm-workspace.yaml",
|
|
24
|
+
"eslint.config.mjs.txt",
|
|
17
25
|
"tsconfig.json",
|
|
18
26
|
"Dockerfile",
|
|
19
27
|
"nginx_dev.conf",
|
package/sync-common.mjs
CHANGED
|
@@ -1,139 +1,140 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import path from
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import prettier from "prettier";
|
|
5
5
|
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = path.dirname(__filename);
|
|
8
|
-
const require = createRequire(import.meta.url);
|
|
9
8
|
const commonDir = __dirname;
|
|
10
9
|
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
'.gitignore',
|
|
14
|
-
'.stylelintignore',
|
|
15
|
-
'.gitattributes',
|
|
16
|
-
'.prettierrc',
|
|
17
|
-
'.env',
|
|
18
|
-
]);
|
|
19
|
-
const directLikeFiles = new Set([
|
|
20
|
-
'Dockerfile',
|
|
21
|
-
'nginx_dev.conf',
|
|
22
|
-
'nginx_test.conf',
|
|
23
|
-
'commit-msg',
|
|
24
|
-
'pre-commit',
|
|
25
|
-
'.stylelintrc.cjs',
|
|
26
|
-
'commitlint.config.cjs',
|
|
27
|
-
'eslint.config.mjs',
|
|
28
|
-
'tsconfig.json',
|
|
29
|
-
]);
|
|
10
|
+
const localMarkerPattern = /^\s*<<<([^>]+)>>>\s*$/gm;
|
|
11
|
+
const commonMarkerPattern = /<<<([^>]+)>>>/g;
|
|
30
12
|
const defaultManagedFiles = [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
{ name:
|
|
43
|
-
{ name:
|
|
44
|
-
|
|
13
|
+
".gitignore",
|
|
14
|
+
".stylelintignore",
|
|
15
|
+
".gitattributes",
|
|
16
|
+
".prettierignore",
|
|
17
|
+
{ name: ".prettierrc.txt" },
|
|
18
|
+
".env",
|
|
19
|
+
".env.dev",
|
|
20
|
+
".env.development",
|
|
21
|
+
".env.production",
|
|
22
|
+
".env.sit",
|
|
23
|
+
".env.test",
|
|
24
|
+
{ name: ".stylelintrc.cjs.txt" },
|
|
25
|
+
{ name: "commitlint.config.cjs.txt" },
|
|
26
|
+
".gitlab-ci.yml",
|
|
27
|
+
"pnpm-workspace.yaml",
|
|
28
|
+
"Dockerfile",
|
|
29
|
+
{ name: "eslint.config.mjs.txt" },
|
|
30
|
+
"tsconfig.json",
|
|
31
|
+
{ name: "nginx_dev.conf" },
|
|
32
|
+
{ name: "nginx_test.conf" },
|
|
33
|
+
{ name: "commit-msg", dir: ".husky" },
|
|
34
|
+
{ name: "pre-commit", dir: ".husky" },
|
|
45
35
|
];
|
|
46
36
|
|
|
47
|
-
const getFileRelativePath =
|
|
48
|
-
const
|
|
37
|
+
const getFileRelativePath = file => (file.dir ? path.join(file.dir, file.name) : file.name);
|
|
38
|
+
const getTargetFileName = file => {
|
|
39
|
+
if (file.targetName) {
|
|
40
|
+
return file.targetName;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return file.name.endsWith(".txt") ? file.name.slice(0, -4) : file.name;
|
|
44
|
+
};
|
|
45
|
+
const getTargetRelativePath = file =>
|
|
46
|
+
file.dir ? path.join(file.dir, getTargetFileName(file)) : getTargetFileName(file);
|
|
47
|
+
const getFileKey = file => `${file.dir ?? ""}::${file.name}`;
|
|
49
48
|
|
|
50
|
-
const ensureCommonFile =
|
|
49
|
+
const ensureCommonFile = file => {
|
|
51
50
|
const filePath = path.join(commonDir, getFileRelativePath(file));
|
|
52
51
|
if (!fs.existsSync(filePath)) {
|
|
53
|
-
|
|
52
|
+
console.error(`\n[sync:common] {${getFileKey(file)}} missing common file: ${filePath}`);
|
|
53
|
+
return "";
|
|
54
54
|
}
|
|
55
55
|
return filePath;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
const normalizeLineEndings = content => content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
59
|
+
|
|
60
|
+
const parseLocalSections = filePaths => {
|
|
61
|
+
const candidates = [filePaths].flat().filter(Boolean);
|
|
62
|
+
const existingPath = candidates.find(filePath => fs.existsSync(filePath));
|
|
63
|
+
|
|
64
|
+
if (!existingPath) {
|
|
65
|
+
return { before: "", after: "", blocks: {}, hasMarkers: false, sourcePath: "" };
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
const rawContent = fs.readFileSync(
|
|
64
|
-
if (!rawContent) {
|
|
65
|
-
return { before:
|
|
68
|
+
const rawContent = normalizeLineEndings(fs.readFileSync(existingPath, "utf8"));
|
|
69
|
+
if (!rawContent.trim()) {
|
|
70
|
+
return { before: "", after: "", blocks: {}, hasMarkers: false, sourcePath: existingPath };
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
const markers = [...rawContent.matchAll(
|
|
73
|
+
const markers = [...rawContent.matchAll(localMarkerPattern)];
|
|
69
74
|
if (markers.length === 0) {
|
|
70
|
-
return { before:
|
|
75
|
+
return { before: "", after: rawContent, blocks: {}, hasMarkers: false, sourcePath: existingPath };
|
|
71
76
|
}
|
|
72
77
|
|
|
73
|
-
const
|
|
74
|
-
before: '',
|
|
75
|
-
common: '',
|
|
76
|
-
after: '',
|
|
77
|
-
};
|
|
78
|
+
const blocks = {};
|
|
78
79
|
|
|
79
80
|
for (let index = 0; index < markers.length; index += 1) {
|
|
80
81
|
const current = markers[index];
|
|
81
82
|
const next = markers[index + 1];
|
|
82
|
-
const
|
|
83
|
+
const blockName = current[1].trim();
|
|
83
84
|
const start = current.index + current[0].length;
|
|
84
85
|
const end = next ? next.index : rawContent.length;
|
|
85
|
-
|
|
86
|
+
const blockContent = rawContent.slice(start, end).replace(/^\n/, "");
|
|
87
|
+
blocks[blockName] = blockContent;
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
return {
|
|
89
|
-
before:
|
|
90
|
-
after:
|
|
91
|
+
before: blocks.before ?? "",
|
|
92
|
+
after: blocks.after ?? "",
|
|
93
|
+
blocks,
|
|
91
94
|
hasMarkers: true,
|
|
95
|
+
sourcePath: existingPath,
|
|
92
96
|
};
|
|
93
97
|
};
|
|
94
98
|
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
const replaceNamedBlocks = (content, blocks = {}) =>
|
|
100
|
+
content.replace(commonMarkerPattern, (match, blockName, offset, source) => {
|
|
101
|
+
const replacement = blocks[blockName.trim()];
|
|
102
|
+
if (!replacement) {
|
|
103
|
+
return "";
|
|
104
|
+
}
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
|
|
106
|
+
const lineStart = source.lastIndexOf("\n", offset - 1) + 1;
|
|
107
|
+
const linePrefix = source.slice(lineStart, offset);
|
|
108
|
+
const indentation = (linePrefix.match(/^\s*/) ?? [""])[0];
|
|
102
109
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
});
|
|
110
|
+
return replacement.split("\n").map(line => `${indentation}${line}`).join("\n");
|
|
111
|
+
});
|
|
106
112
|
|
|
107
|
-
const
|
|
108
|
-
if (textLikeFiles.has(fileName)) {
|
|
109
|
-
return {
|
|
110
|
-
before: '# project specific\n',
|
|
111
|
-
common: '',
|
|
112
|
-
after: '\n\n# project specific\n',
|
|
113
|
-
};
|
|
114
|
-
}
|
|
113
|
+
const getDefaultHeader = () => "";
|
|
115
114
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
common: '# 这里是 common 的内容\n\n',
|
|
120
|
-
after: '\n\n# 这里还是增量\n\n',
|
|
121
|
-
};
|
|
122
|
-
}
|
|
115
|
+
const getDefaultLocalFiles = file => {
|
|
116
|
+
const sourceRelativePath = getFileRelativePath(file);
|
|
117
|
+
const targetRelativePath = getTargetRelativePath(file);
|
|
123
118
|
|
|
124
119
|
return {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
after: '',
|
|
120
|
+
merged: path.join("local", sourceRelativePath),
|
|
121
|
+
targetMerged: targetRelativePath !== sourceRelativePath ? path.join("local", targetRelativePath) : "",
|
|
128
122
|
};
|
|
129
123
|
};
|
|
130
124
|
|
|
131
|
-
const
|
|
125
|
+
const getDefaultBlockHeaders = () => ({
|
|
126
|
+
before: "",
|
|
127
|
+
common: "",
|
|
128
|
+
after: "",
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const getDefaultFileConfig = file => ({
|
|
132
132
|
name: file.name,
|
|
133
133
|
dir: file.dir,
|
|
134
|
-
|
|
134
|
+
targetName: file.targetName,
|
|
135
|
+
header: getDefaultHeader(),
|
|
135
136
|
localFiles: getDefaultLocalFiles(file),
|
|
136
|
-
blockHeaders: getDefaultBlockHeaders(
|
|
137
|
+
blockHeaders: getDefaultBlockHeaders(),
|
|
137
138
|
});
|
|
138
139
|
|
|
139
140
|
const mergeFileConfig = (defaultFile, projectFile = {}) => ({
|
|
@@ -149,8 +150,8 @@ const mergeFileConfig = (defaultFile, projectFile = {}) => ({
|
|
|
149
150
|
},
|
|
150
151
|
});
|
|
151
152
|
|
|
152
|
-
const normalizeFileEntry =
|
|
153
|
-
if (typeof file ===
|
|
153
|
+
const normalizeFileEntry = file => {
|
|
154
|
+
if (typeof file === "string") {
|
|
154
155
|
return { name: file };
|
|
155
156
|
}
|
|
156
157
|
|
|
@@ -167,21 +168,21 @@ const normalizeFiles = (config = {}) => {
|
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
return [
|
|
170
|
-
...(config.textFiles ?? []).map(
|
|
171
|
-
...(config.directFiles ?? []).map(
|
|
172
|
-
type:
|
|
171
|
+
...(config.textFiles ?? []).map(file => ({ type: "textFiles", ...normalizeFileEntry(file) })),
|
|
172
|
+
...(config.directFiles ?? []).map(file => ({
|
|
173
|
+
type: "directFiles",
|
|
173
174
|
...normalizeFileEntry(file),
|
|
174
175
|
})),
|
|
175
176
|
];
|
|
176
177
|
};
|
|
177
178
|
|
|
178
179
|
const mergeManagedFiles = (projectConfig = {}, runtimeConfig = {}) => {
|
|
179
|
-
const defaultFiles = normalizeFiles(defaultManagedFiles).map(
|
|
180
|
+
const defaultFiles = normalizeFiles(defaultManagedFiles).map(file =>
|
|
180
181
|
mergeFileConfig(getDefaultFileConfig(file), file),
|
|
181
182
|
);
|
|
182
183
|
const projectFiles = normalizeFiles(projectConfig);
|
|
183
184
|
const runtimeFiles = normalizeFiles(runtimeConfig);
|
|
184
|
-
const mergedMap = new Map(defaultFiles.map(
|
|
185
|
+
const mergedMap = new Map(defaultFiles.map(file => [getFileKey(file), { ...file }]));
|
|
185
186
|
|
|
186
187
|
for (const projectFile of projectFiles) {
|
|
187
188
|
const key = getFileKey(projectFile);
|
|
@@ -195,60 +196,87 @@ const mergeManagedFiles = (projectConfig = {}, runtimeConfig = {}) => {
|
|
|
195
196
|
mergedMap.set(key, mergeFileConfig(current, runtimeFile));
|
|
196
197
|
}
|
|
197
198
|
|
|
198
|
-
return [...mergedMap.values()].filter(
|
|
199
|
+
return [...mergedMap.values()].filter(file => file.enabled !== false);
|
|
199
200
|
};
|
|
200
201
|
|
|
201
202
|
const logGenerated = ({ rootDir, targetPath, commonPath, localPaths, usedLocalPaths }) => {
|
|
202
|
-
const targetName = path.relative(rootDir, targetPath).replaceAll(
|
|
203
|
-
const commonName = `@dazhicheng/common/${path.relative(commonDir, commonPath).replaceAll(
|
|
204
|
-
const sourceText = [commonName, ...usedLocalPaths].join(
|
|
203
|
+
const targetName = path.relative(rootDir, targetPath).replaceAll("\\", "/");
|
|
204
|
+
const commonName = `@dazhicheng/common/${path.relative(commonDir, commonPath).replaceAll("\\", "/")}`;
|
|
205
|
+
const sourceText = [commonName, ...usedLocalPaths].join(" + ");
|
|
205
206
|
|
|
206
|
-
console.log(
|
|
207
|
+
console.log(`\n[sync:common] generated ${targetName} <- ${sourceText}`);
|
|
207
208
|
if (localPaths.length > 0) {
|
|
208
|
-
console.log(`[sync:common] 如需项目增量,请修改 ${localPaths.join(
|
|
209
|
-
console.log(
|
|
210
|
-
'[sync:common] 单个 local 文件可使用 <<<before>>> / <<<common>>> / <<<after>>> 标记',
|
|
211
|
-
);
|
|
209
|
+
console.log(`[sync:common] 如需项目增量,请修改 ${localPaths.join(" / ")}`);
|
|
210
|
+
console.log("[sync:common] local 文件支持 <<<name>>> 任意命名块,占位将替换 common 中同名标记");
|
|
212
211
|
}
|
|
213
212
|
};
|
|
214
213
|
|
|
215
214
|
const renderFile = ({ file, commonContent, localSections, usedLocalPaths }) => {
|
|
216
|
-
let output = file.header ??
|
|
215
|
+
let output = file.header ?? "";
|
|
216
|
+
const renderedCommonContent = replaceNamedBlocks(commonContent, localSections.blocks);
|
|
217
217
|
|
|
218
218
|
if (localSections.before) {
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
if (localSections.sourcePath) {
|
|
220
|
+
usedLocalPaths.push(path.relative(process.cwd(), localSections.sourcePath).replaceAll("\\", "/"));
|
|
221
|
+
}
|
|
222
|
+
output += `${file.blockHeaders.before ?? ""}${localSections.before}\n\n`;
|
|
221
223
|
}
|
|
222
224
|
|
|
223
|
-
output += `${file.blockHeaders.common ??
|
|
225
|
+
output += `${file.blockHeaders.common ?? ""}${renderedCommonContent}`;
|
|
224
226
|
|
|
225
227
|
if (localSections.after) {
|
|
226
|
-
if (
|
|
227
|
-
|
|
228
|
+
if (localSections.sourcePath) {
|
|
229
|
+
const localPath = path.relative(process.cwd(), localSections.sourcePath).replaceAll("\\", "/");
|
|
230
|
+
if (!usedLocalPaths.includes(localPath)) {
|
|
231
|
+
usedLocalPaths.push(localPath);
|
|
232
|
+
}
|
|
228
233
|
}
|
|
229
|
-
output += `${file.blockHeaders.after ??
|
|
230
|
-
} else {
|
|
231
|
-
output += '\n';
|
|
234
|
+
output += `${file.blockHeaders.after ?? ""}${localSections.after}`;
|
|
232
235
|
}
|
|
233
236
|
|
|
234
|
-
return output
|
|
237
|
+
return output.endsWith("\n") ? output : `${output}\n`;
|
|
235
238
|
};
|
|
236
239
|
|
|
237
|
-
const
|
|
240
|
+
const formatWithPrettier = async ({ targetPath, output }) => {
|
|
241
|
+
try {
|
|
242
|
+
const fileInfo = await prettier.getFileInfo(targetPath);
|
|
243
|
+
if (fileInfo.ignored || !fileInfo.inferredParser) {
|
|
244
|
+
console.log(`[sync:common] skipped prettier for ${targetPath}: parser unavailable`);
|
|
245
|
+
return output;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const config = (await prettier.resolveConfig(targetPath)) ?? {};
|
|
249
|
+
return normalizeLineEndings(await prettier.format(output, {
|
|
250
|
+
...config,
|
|
251
|
+
filepath: targetPath,
|
|
252
|
+
}));
|
|
253
|
+
} catch (error) {
|
|
254
|
+
console.log(`[sync:common] skipped prettier for ${targetPath}: ${error.message}`);
|
|
255
|
+
return output;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const syncFiles = async ({ files, rootDir }) => {
|
|
238
260
|
for (const file of files) {
|
|
239
261
|
const commonPath = ensureCommonFile(file);
|
|
240
|
-
|
|
262
|
+
if (!commonPath) {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const targetPath = path.join(rootDir, getTargetRelativePath(file));
|
|
241
266
|
const targetDir = path.dirname(targetPath);
|
|
242
267
|
if (!fs.existsSync(targetDir)) {
|
|
243
268
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
244
269
|
}
|
|
245
|
-
const
|
|
246
|
-
const
|
|
247
|
-
const
|
|
270
|
+
const localPaths = Object.values(file.localFiles ?? {}).filter(Boolean);
|
|
271
|
+
const resolvedLocalPaths = localPaths.map(localPath => path.join(rootDir, localPath));
|
|
272
|
+
const localSections = parseLocalSections(resolvedLocalPaths);
|
|
273
|
+
const commonContent = normalizeLineEndings(fs.readFileSync(commonPath, "utf8")).trimEnd();
|
|
248
274
|
const usedLocalPaths = [];
|
|
249
275
|
const output = renderFile({ file, commonContent, localSections, usedLocalPaths });
|
|
250
276
|
|
|
251
|
-
|
|
277
|
+
const formattedOutput = await formatWithPrettier({ targetPath, output });
|
|
278
|
+
|
|
279
|
+
fs.writeFileSync(targetPath, formattedOutput);
|
|
252
280
|
logGenerated({
|
|
253
281
|
rootDir,
|
|
254
282
|
targetPath,
|
|
@@ -266,7 +294,7 @@ export const runSyncCommon = async ({ rootDir, files = [], config = {} }) => {
|
|
|
266
294
|
};
|
|
267
295
|
const managedFiles = mergeManagedFiles({}, runtimeConfig);
|
|
268
296
|
|
|
269
|
-
syncFiles({ files: managedFiles, rootDir });
|
|
297
|
+
await syncFiles({ files: managedFiles, rootDir });
|
|
270
298
|
};
|
|
271
299
|
|
|
272
300
|
const isDirectRun = process.argv[1] && path.resolve(process.argv[1]) === __filename;
|
package/tsconfig.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "esnext",
|
|
4
|
-
"module": "esnext",
|
|
5
|
-
"moduleResolution": "node",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"jsx": "preserve",
|
|
8
|
-
"jsxImportSource": "vue",
|
|
9
|
-
"sourceMap": true,
|
|
10
|
-
"resolveJsonModule": true,
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"lib": ["esnext", "dom"],
|
|
13
|
-
"types": ["vite/client", "node", "element-plus/global"],
|
|
14
|
-
"skipLibCheck": true,
|
|
15
|
-
"baseUrl": ".",
|
|
16
|
-
"paths": {
|
|
17
|
-
"@/*": ["src/*"],
|
|
18
|
-
"@views/*": ["src/views/*"],
|
|
19
|
-
"@imgs/*": ["src/assets/images/*"],
|
|
20
|
-
"@icons/*": ["src/assets/icons/*"],
|
|
21
|
-
"@utils/*": ["src/utils/*"],
|
|
22
|
-
"@stores/*": ["src/store/*"],
|
|
23
|
-
"@plugins/*": ["src/plugins/*"],
|
|
24
|
-
"@styles/*": ["src/assets/styles/*"]
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"include": ["src/**/*", "src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
|
|
28
|
-
"exclude": ["node_modules", "dist", "**/*.js"]
|
|
29
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "esnext",
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"jsx": "preserve",
|
|
8
|
+
"jsxImportSource": "vue",
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"lib": ["esnext", "dom"],
|
|
13
|
+
"types": ["vite/client", "node", "element-plus/global"],
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"baseUrl": ".",
|
|
16
|
+
"paths": {
|
|
17
|
+
"@/*": ["src/*"],
|
|
18
|
+
"@views/*": ["src/views/*"],
|
|
19
|
+
"@imgs/*": ["src/assets/images/*"],
|
|
20
|
+
"@icons/*": ["src/assets/icons/*"],
|
|
21
|
+
"@utils/*": ["src/utils/*"],
|
|
22
|
+
"@stores/*": ["src/store/*"],
|
|
23
|
+
"@plugins/*": ["src/plugins/*"],
|
|
24
|
+
"@styles/*": ["src/assets/styles/*"]
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"include": ["src/**/*", "src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
|
|
28
|
+
"exclude": ["node_modules", "dist", "**/*.js"]
|
|
29
|
+
}
|