@dazhicheng/common 1.0.7 → 1.0.9
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.development +1 -1
- package/.gitlab-ci.yml +74 -74
- package/Dockerfile +1 -1
- package/eslint.config.mjs.txt +3 -0
- package/nginx_dev.conf +2 -2
- package/nginx_test.conf +2 -2
- package/package.json +1 -1
- package/sync-common.mjs +337 -305
package/.env.development
CHANGED
|
@@ -9,11 +9,11 @@ VITE_MOCK_ENABLED = true
|
|
|
9
9
|
|
|
10
10
|
# 代理目标地址(开发环境通过 Vite 代理转发请求到此地址,解决跨域问题)
|
|
11
11
|
VITE_API_PROXY_URL = https://m1.apifoxmock.com/m1/6400575-6097373-default
|
|
12
|
+
|
|
12
13
|
VITE_API_PROXY_URL_dev = http://192.168.128.215:11000
|
|
13
14
|
VITE_API_MOCK = http://192.168.129.158:9998/mock/
|
|
14
15
|
VITE_API_PROXY_URL_test = http://192.168.127.72:11000/
|
|
15
16
|
|
|
16
|
-
|
|
17
17
|
VITE_API_PROXY_URL_dev_yun = http://116.6.49.180:11000/
|
|
18
18
|
VITE_API_PROXY_URL_test_yun = http://116.6.49.180:11001/
|
|
19
19
|
|
package/.gitlab-ci.yml
CHANGED
|
@@ -1,74 +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
|
|
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/Dockerfile
CHANGED
package/eslint.config.mjs.txt
CHANGED
package/nginx_dev.conf
CHANGED
|
@@ -11,14 +11,14 @@ server {
|
|
|
11
11
|
try_files $uri $uri/ /index.html;
|
|
12
12
|
<<<CORS配置>>>
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
location /dev-api/ {
|
|
16
16
|
proxy_set_header Host $host;
|
|
17
17
|
proxy_set_header X-Real-Ip $remote_addr;
|
|
18
18
|
proxy_set_header X-Forwarded-For $remote_addr;
|
|
19
19
|
proxy_pass http://116.6.49.180:11000/;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
error_page 500 502 503 504 /50x.html;
|
|
23
23
|
location = /50x.html {
|
|
24
24
|
root html;
|
package/nginx_test.conf
CHANGED
|
@@ -11,14 +11,14 @@ server {
|
|
|
11
11
|
try_files $uri $uri/ /index.html;
|
|
12
12
|
<<<CORS配置>>>
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
location /test-api/ {
|
|
16
16
|
proxy_set_header Host $host;
|
|
17
17
|
proxy_set_header X-Real-Ip $remote_addr;
|
|
18
18
|
proxy_set_header X-Forwarded-For $remote_addr;
|
|
19
19
|
proxy_pass http://116.6.49.180:11001/;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
error_page 500 502 503 504 /50x.html;
|
|
23
23
|
location = /50x.html {
|
|
24
24
|
root html;
|
package/package.json
CHANGED
package/sync-common.mjs
CHANGED
|
@@ -1,305 +1,337 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
import prettier from "prettier";
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = path.dirname(__filename);
|
|
8
|
-
const commonDir = __dirname;
|
|
9
|
-
|
|
10
|
-
const localMarkerPattern = /^\s*<<<([^>]+)>>>\s*$/gm;
|
|
11
|
-
const commonMarkerPattern = /<<<([^>]+)>>>/g;
|
|
12
|
-
const defaultManagedFiles = [
|
|
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" },
|
|
35
|
-
];
|
|
36
|
-
|
|
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}`;
|
|
48
|
-
|
|
49
|
-
const ensureCommonFile = file => {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
const
|
|
262
|
-
if (!
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import prettier from "prettier";
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
const commonDir = __dirname;
|
|
9
|
+
|
|
10
|
+
const localMarkerPattern = /^\s*<<<([^>]+)>>>\s*$/gm;
|
|
11
|
+
const commonMarkerPattern = /<<<([^>]+)>>>/g;
|
|
12
|
+
const defaultManagedFiles = [
|
|
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.txt",
|
|
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" },
|
|
35
|
+
];
|
|
36
|
+
|
|
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}`;
|
|
48
|
+
|
|
49
|
+
const ensureCommonFile = file => {
|
|
50
|
+
const relativePath = getFileRelativePath(file);
|
|
51
|
+
const candidates = [relativePath];
|
|
52
|
+
|
|
53
|
+
if (relativePath.endsWith(".txt")) {
|
|
54
|
+
candidates.push(relativePath.slice(0, -4));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const filePath = candidates.map(candidate => path.join(commonDir, candidate)).find(fs.existsSync);
|
|
58
|
+
if (!filePath) {
|
|
59
|
+
console.error(
|
|
60
|
+
`\n[sync:common] {${getFileKey(file)}} missing common file: ${candidates
|
|
61
|
+
.map(candidate => path.join(commonDir, candidate))
|
|
62
|
+
.join(" / ")}`,
|
|
63
|
+
);
|
|
64
|
+
return "";
|
|
65
|
+
}
|
|
66
|
+
return filePath;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const normalizeLineEndings = content => content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
70
|
+
|
|
71
|
+
const parseLocalSections = filePaths => {
|
|
72
|
+
const candidates = [filePaths].flat().filter(Boolean);
|
|
73
|
+
const existingPath = candidates.find(filePath => fs.existsSync(filePath));
|
|
74
|
+
|
|
75
|
+
if (!existingPath) {
|
|
76
|
+
return { before: "", after: "", blocks: {}, hasMarkers: false, sourcePath: "" };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const rawContent = normalizeLineEndings(fs.readFileSync(existingPath, "utf8"));
|
|
80
|
+
if (!rawContent.trim()) {
|
|
81
|
+
return { before: "", after: "", blocks: {}, hasMarkers: false, sourcePath: existingPath };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const markers = [...rawContent.matchAll(localMarkerPattern)];
|
|
85
|
+
if (markers.length === 0) {
|
|
86
|
+
return { before: "", after: rawContent, blocks: {}, hasMarkers: false, sourcePath: existingPath };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const blocks = {};
|
|
90
|
+
|
|
91
|
+
for (let index = 0; index < markers.length; index += 1) {
|
|
92
|
+
const current = markers[index];
|
|
93
|
+
const next = markers[index + 1];
|
|
94
|
+
const blockName = current[1].trim();
|
|
95
|
+
const start = current.index + current[0].length;
|
|
96
|
+
const end = next ? next.index : rawContent.length;
|
|
97
|
+
const blockContent = rawContent.slice(start, end).replace(/^\n/, "");
|
|
98
|
+
blocks[blockName] = blockContent;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
before: blocks.before ?? "",
|
|
103
|
+
after: blocks.after ?? "",
|
|
104
|
+
blocks,
|
|
105
|
+
hasMarkers: true,
|
|
106
|
+
sourcePath: existingPath,
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const replaceNamedBlocks = (content, blocks = {}) =>
|
|
111
|
+
content.replace(commonMarkerPattern, (match, blockName, offset, source) => {
|
|
112
|
+
const replacement = blocks[blockName.trim()];
|
|
113
|
+
if (replacement === undefined) {
|
|
114
|
+
return "";
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const lineStart = source.lastIndexOf("\n", offset - 1) + 1;
|
|
118
|
+
const linePrefix = source.slice(lineStart, offset);
|
|
119
|
+
const indentation = (linePrefix.match(/^\s*/) ?? [""])[0];
|
|
120
|
+
|
|
121
|
+
if (replacement === "") {
|
|
122
|
+
return "";
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return replacement
|
|
126
|
+
.split("\n")
|
|
127
|
+
.map((line, index) => (index === 0 ? line.trimStart() : `${indentation}${line}`))
|
|
128
|
+
.join("\n");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const getDefaultHeader = () => "";
|
|
132
|
+
|
|
133
|
+
const getDefaultLocalFiles = file => {
|
|
134
|
+
const sourceRelativePath = getFileRelativePath(file);
|
|
135
|
+
const targetRelativePath = getTargetRelativePath(file);
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
merged: path.join("local", sourceRelativePath),
|
|
139
|
+
targetMerged: targetRelativePath !== sourceRelativePath ? path.join("local", targetRelativePath) : "",
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const getDefaultBlockHeaders = () => ({
|
|
144
|
+
before: "",
|
|
145
|
+
common: "",
|
|
146
|
+
after: "",
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const getDefaultFileConfig = file => ({
|
|
150
|
+
name: file.name,
|
|
151
|
+
dir: file.dir,
|
|
152
|
+
targetName: file.targetName,
|
|
153
|
+
header: getDefaultHeader(),
|
|
154
|
+
localFiles: getDefaultLocalFiles(file),
|
|
155
|
+
blockHeaders: getDefaultBlockHeaders(),
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const mergeFileConfig = (defaultFile, projectFile = {}) => ({
|
|
159
|
+
...defaultFile,
|
|
160
|
+
...projectFile,
|
|
161
|
+
localFiles: {
|
|
162
|
+
...(defaultFile.localFiles ?? {}),
|
|
163
|
+
...(projectFile.localFiles ?? {}),
|
|
164
|
+
},
|
|
165
|
+
blockHeaders: {
|
|
166
|
+
...(defaultFile.blockHeaders ?? {}),
|
|
167
|
+
...(projectFile.blockHeaders ?? {}),
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const normalizeFileEntry = file => {
|
|
172
|
+
if (typeof file === "string") {
|
|
173
|
+
return { name: file };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return file;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const normalizeFiles = (config = {}) => {
|
|
180
|
+
if (Array.isArray(config)) {
|
|
181
|
+
return config.map(normalizeFileEntry);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (Array.isArray(config.files)) {
|
|
185
|
+
return config.files.map(normalizeFileEntry);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return [
|
|
189
|
+
...(config.textFiles ?? []).map(file => ({ type: "textFiles", ...normalizeFileEntry(file) })),
|
|
190
|
+
...(config.directFiles ?? []).map(file => ({
|
|
191
|
+
type: "directFiles",
|
|
192
|
+
...normalizeFileEntry(file),
|
|
193
|
+
})),
|
|
194
|
+
];
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const mergeManagedFiles = (projectConfig = {}, runtimeConfig = {}) => {
|
|
198
|
+
const defaultFiles = normalizeFiles(defaultManagedFiles).map(file =>
|
|
199
|
+
mergeFileConfig(getDefaultFileConfig(file), file),
|
|
200
|
+
);
|
|
201
|
+
const projectFiles = normalizeFiles(projectConfig);
|
|
202
|
+
const runtimeFiles = normalizeFiles(runtimeConfig);
|
|
203
|
+
const mergedMap = new Map(defaultFiles.map(file => [getFileKey(file), { ...file }]));
|
|
204
|
+
|
|
205
|
+
for (const projectFile of projectFiles) {
|
|
206
|
+
const key = getFileKey(projectFile);
|
|
207
|
+
const current = mergedMap.get(key) ?? getDefaultFileConfig(projectFile);
|
|
208
|
+
mergedMap.set(key, mergeFileConfig(current, projectFile));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
for (const runtimeFile of runtimeFiles) {
|
|
212
|
+
const key = getFileKey(runtimeFile);
|
|
213
|
+
const current = mergedMap.get(key) ?? getDefaultFileConfig(runtimeFile);
|
|
214
|
+
mergedMap.set(key, mergeFileConfig(current, runtimeFile));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return [...mergedMap.values()].filter(file => file.enabled !== false);
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const logGenerated = ({ rootDir, targetPath, commonPath, localPaths, usedLocalPaths, generatedFile }) => {
|
|
221
|
+
const targetName = path.relative(rootDir, targetPath).replaceAll("\\", "/");
|
|
222
|
+
const commonName = `@dazhicheng/common/${path.relative(commonDir, commonPath).replaceAll("\\", "/")}`;
|
|
223
|
+
const sourceText = [commonName, ...usedLocalPaths].join(" + ");
|
|
224
|
+
|
|
225
|
+
generatedFile.push(`[sync:common] generated ${targetName} <- ${sourceText}`);
|
|
226
|
+
if (localPaths.length > 0) {
|
|
227
|
+
// console.log(`[sync:common] 如需项目增量,请修改 ${localPaths.join(" / ")}`);
|
|
228
|
+
// console.log("[sync:common] local 文件支持 <<<name>>> 任意命名块,占位将替换 common 中同名标记");
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const renderFile = ({ file, commonContent, localSections, usedLocalPaths }) => {
|
|
233
|
+
let output = file.header ?? "";
|
|
234
|
+
const renderedCommonContent = replaceNamedBlocks(commonContent, localSections.blocks);
|
|
235
|
+
|
|
236
|
+
if (localSections.before) {
|
|
237
|
+
if (localSections.sourcePath) {
|
|
238
|
+
usedLocalPaths.push(path.relative(process.cwd(), localSections.sourcePath).replaceAll("\\", "/"));
|
|
239
|
+
}
|
|
240
|
+
output += `${file.blockHeaders.before ?? ""}${localSections.before}\n`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
output += `${file.blockHeaders.common ?? ""}${renderedCommonContent}`;
|
|
244
|
+
|
|
245
|
+
if (localSections.after) {
|
|
246
|
+
if (localSections.sourcePath) {
|
|
247
|
+
const localPath = path.relative(process.cwd(), localSections.sourcePath).replaceAll("\\", "/");
|
|
248
|
+
if (!usedLocalPaths.includes(localPath)) {
|
|
249
|
+
usedLocalPaths.push(localPath);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
output += `${file.blockHeaders.after ?? ""}${localSections.after}`;
|
|
253
|
+
}
|
|
254
|
+
output = output.replace(/\n{3,}/g, "\n\n");
|
|
255
|
+
output = output.replace(/\n\s{1,}\n/g, "\n");
|
|
256
|
+
return output + "\n";
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const formatWithPrettier = async ({ targetPath, output, fmtError }) => {
|
|
260
|
+
try {
|
|
261
|
+
const fileInfo = await prettier.getFileInfo(targetPath);
|
|
262
|
+
if (fileInfo.ignored || !fileInfo.inferredParser) {
|
|
263
|
+
fmtError.push(`[sync:common] skipped prettier for ${targetPath}: parser unavailable`);
|
|
264
|
+
return output;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const config = (await prettier.resolveConfig(targetPath)) ?? {};
|
|
268
|
+
return normalizeLineEndings(
|
|
269
|
+
await prettier.format(output, {
|
|
270
|
+
...config,
|
|
271
|
+
filepath: targetPath,
|
|
272
|
+
}),
|
|
273
|
+
);
|
|
274
|
+
} catch (error) {
|
|
275
|
+
fmtError.push(`[sync:common] skipped prettier for ${targetPath}: ${error.message}`);
|
|
276
|
+
return output;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const syncFiles = async ({ files, rootDir }) => {
|
|
281
|
+
let fmtError = [];
|
|
282
|
+
let generatedFile = [];
|
|
283
|
+
for (const file of files) {
|
|
284
|
+
const commonPath = ensureCommonFile(file);
|
|
285
|
+
if (!commonPath) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const targetPath = path.join(rootDir, getTargetRelativePath(file));
|
|
289
|
+
const targetDir = path.dirname(targetPath);
|
|
290
|
+
if (!fs.existsSync(targetDir)) {
|
|
291
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
292
|
+
}
|
|
293
|
+
const localPaths = Object.values(file.localFiles ?? {}).filter(Boolean);
|
|
294
|
+
const resolvedLocalPaths = localPaths.map(localPath => path.join(rootDir, localPath));
|
|
295
|
+
const localSections = parseLocalSections(resolvedLocalPaths);
|
|
296
|
+
const commonContent = normalizeLineEndings(fs.readFileSync(commonPath, "utf8")).trimEnd();
|
|
297
|
+
const usedLocalPaths = [];
|
|
298
|
+
const output = renderFile({ file, commonContent, localSections, usedLocalPaths });
|
|
299
|
+
|
|
300
|
+
const formattedOutput = await formatWithPrettier({ targetPath, output, fmtError });
|
|
301
|
+
|
|
302
|
+
fs.writeFileSync(targetPath, formattedOutput);
|
|
303
|
+
logGenerated({
|
|
304
|
+
rootDir,
|
|
305
|
+
targetPath,
|
|
306
|
+
commonPath,
|
|
307
|
+
localPaths: Object.values(file.localFiles ?? {}).filter(Boolean),
|
|
308
|
+
usedLocalPaths,
|
|
309
|
+
generatedFile,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (generatedFile.length > 0) {
|
|
314
|
+
console.log(generatedFile.join("\n"));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (fmtError.length > 0) {
|
|
318
|
+
console.log("\n" + fmtError.join("\n"));
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
export const runSyncCommon = async ({ rootDir, files = [], config = {} }) => {
|
|
323
|
+
const runtimeConfig = {
|
|
324
|
+
...(config ?? {}),
|
|
325
|
+
files: [...normalizeFiles(config ?? {}), ...normalizeFiles(files)],
|
|
326
|
+
};
|
|
327
|
+
const managedFiles = mergeManagedFiles({}, runtimeConfig);
|
|
328
|
+
|
|
329
|
+
await syncFiles({ files: managedFiles, rootDir });
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const isDirectRun = process.argv[1] && path.resolve(process.argv[1]) === __filename;
|
|
333
|
+
|
|
334
|
+
if (isDirectRun) {
|
|
335
|
+
const cwd = process.cwd();
|
|
336
|
+
await runSyncCommon({ rootDir: cwd });
|
|
337
|
+
}
|