done-coding-template 0.7.12-alpha.0 → 0.8.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.
package/es/cli.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { d as m } from "./main-3e20cca2.js";
3
- import "@done-coding/cli-utils";
2
+ import { e as m } from "./main-85d64057.js";
4
3
  import "node:path";
5
4
  import "node:fs";
5
+ import "@done-coding/cli-utils";
6
6
  import "lodash.template";
7
7
  import "lodash.assign";
8
8
  m();
package/es/index.mjs CHANGED
@@ -1,28 +1,28 @@
1
1
  #!/usr/bin/env node
2
- import { M as r } from "./main-3e20cca2.js";
3
- import { O as E, S as h, T as b, b as T, c as A, a as H, h as O, i as S } from "./main-3e20cca2.js";
2
+ import { M as r } from "./main-85d64057.js";
3
+ import { d as f, O as T, S as _, T as h, b as A, a as O, c as b, h as L } from "./main-85d64057.js";
4
4
  import t from "node:path";
5
- import { existsSync as n } from "node:fs";
5
+ import { existsSync as m } from "node:fs";
6
6
  import "@done-coding/cli-utils";
7
7
  import "lodash.template";
8
8
  import "lodash.assign";
9
- const u = ({
10
- rootDir: e,
11
- configPath: o = r
9
+ const E = ({
10
+ rootDir: a,
11
+ configPath: e = r
12
12
  }) => {
13
- const a = t.resolve(e, o);
14
- if (n(a))
15
- return a;
13
+ const o = t.resolve(a, e);
14
+ if (m(o))
15
+ return o;
16
16
  };
17
17
  export {
18
+ f as MODULE_CONFIG_RELATIVE_PATH,
18
19
  r as MODULE_DEFAULT_CONFIG_RELATIVE_PATH,
19
- E as OutputModeEnum,
20
- h as SubcommandEnum,
21
- b as TemplateBindKeyEnum,
22
- T as batchCompileHandler,
23
- A as compileHandler,
24
- H as crateAsSubcommand,
25
- u as getConfigPath,
26
- O as handler,
27
- S as initHandler
20
+ T as OutputModeEnum,
21
+ _ as SubcommandEnum,
22
+ h as TemplateBindKeyEnum,
23
+ A as batchCompileHandler,
24
+ O as compileHandler,
25
+ b as crateAsSubcommand,
26
+ E as getConfigPath,
27
+ L as handler
28
28
  };
@@ -0,0 +1,482 @@
1
+ #!/usr/bin/env node
2
+ import y from "node:path";
3
+ import p from "node:fs";
4
+ import { log as a, xPrompts as A, getConfigFileCommonOptions as P, getUseDefaultConfig as V, initHandlerCommon as W, readConfigFile as G, createSubcommand as S, getRootScriptName as J, createMainCommand as K } from "@done-coding/cli-utils";
5
+ import L from "lodash.template";
6
+ import q from "lodash.assign";
7
+ const h = {
8
+ name: "@done-coding/cli-template",
9
+ version: "0.8.0",
10
+ description: "预编译命令行工具",
11
+ bin: {
12
+ "dc-template": "es/cli.mjs"
13
+ },
14
+ cliConfig: {
15
+ namespaceDir: ".done-coding",
16
+ moduleName: "template"
17
+ }
18
+ }, {
19
+ cliConfig: { namespaceDir: z, moduleName: Z }
20
+ } = h, Q = `./${z}/${Z}`, _ = `${Q}.json`, w = (t, n) => {
21
+ if (!n)
22
+ return a.error(`${t}模式下output不能为空`), process.exit(1);
23
+ }, k = (t, n) => {
24
+ if (n && t === n)
25
+ return a.error("output与input不能相同"), process.exit(1);
26
+ }, X = (t, n) => {
27
+ if (!n)
28
+ return a.error(`${t}模式下input不能为空`), process.exit(1);
29
+ }, F = ({
30
+ rootDir: t,
31
+ filePath: n,
32
+ dataInit: s,
33
+ limitJson: u,
34
+ filePathKey: c,
35
+ dataInitKey: r,
36
+ dealMarkdown: i = !1
37
+ }) => {
38
+ if (n) {
39
+ if (u && !n.endsWith(".json"))
40
+ return a.error(`${c}必须是json文件,请检查文件后缀名`), process.exit(1);
41
+ const o = p.readFileSync(
42
+ y.resolve(t, n),
43
+ "utf-8"
44
+ );
45
+ let $ = o;
46
+ return i && n.endsWith(".md") && ($ = o.replace(
47
+ /^\s*```[a-zA-Z0-9]+\s*[\r\n]+([\s\S]+?)```\s*$/,
48
+ "$1"
49
+ )), u ? JSON.parse($) : $;
50
+ } else
51
+ return s ? (a.info(`${c} 为空,将使用${r}作为数据`), u ? JSON.parse(s) : s) : (a.error(`${c}与${r}不能同时为空`), process.exit(1));
52
+ };
53
+ var R = /* @__PURE__ */ ((t) => (t.INIT = "init", t.COMPILE = "compile", t.BATCH = "batch", t))(R || {}), ee = /* @__PURE__ */ ((t) => (t.REPOSITORY_URL = "REPOSITORY_URL", t))(ee || {}), d = /* @__PURE__ */ ((t) => (t.OVERWRITE = "overwrite", t.APPEND = "append", t.REPLACE = "replace", t.RETURN = "return", t))(d || {});
54
+ const x = async (t, { rootDir: n, rollback: s }) => {
55
+ const {
56
+ env: u,
57
+ input: c,
58
+ inputData: r,
59
+ output: i,
60
+ mode: o,
61
+ rollbackDelNullFile: $,
62
+ rollbackDelAskAsYes: C,
63
+ dealMarkdown: D,
64
+ envData: E
65
+ } = t;
66
+ if (s)
67
+ switch (o) {
68
+ case d.REPLACE:
69
+ case d.RETURN: {
70
+ a.error(`${o}模式不支持回滚`);
71
+ return;
72
+ }
73
+ }
74
+ a.stage(`开始处理模板
75
+ mode: ${o}
76
+ rollback: ${s}
77
+ `);
78
+ const N = F({
79
+ rootDir: n,
80
+ filePath: c,
81
+ dataInit: r,
82
+ limitJson: !1,
83
+ filePathKey: "input",
84
+ dataInitKey: "inputData",
85
+ dealMarkdown: D
86
+ }), g = L(N), v = typeof E == "function" ? E() : E, l = g(v);
87
+ switch (o) {
88
+ case d.OVERWRITE: {
89
+ w(o, i), k(i, c);
90
+ const e = y.resolve(n, i);
91
+ if (p.mkdirSync(y.dirname(e), { recursive: !0 }), p.existsSync(e)) {
92
+ if (s)
93
+ if (C || (await A({
94
+ type: "confirm",
95
+ name: "remove",
96
+ message: `${o}模式下回滚将删除${e},是否继续?`
97
+ })).remove) {
98
+ p.rmSync(e, { force: !0 }), a.success(`${o}模式下${e}已删除`);
99
+ return;
100
+ } else {
101
+ a.warn(`${o}模式下${e}回滚取消`);
102
+ return;
103
+ }
104
+ a.info(`output:${e} 已存在,将覆盖`);
105
+ } else {
106
+ if (s) {
107
+ a.warn(`${o}模式下${e}不存在,无需回滚`);
108
+ return;
109
+ }
110
+ a.stage(`output:${e} 不存在,将创建`);
111
+ }
112
+ p.writeFileSync(e, l, "utf-8"), a.success(`模板处理完成,输出到 ${e}`);
113
+ break;
114
+ }
115
+ case d.APPEND: {
116
+ w(o, i), k(i, c);
117
+ const e = y.resolve(n, i);
118
+ if (p.mkdirSync(y.dirname(e), { recursive: !0 }), p.existsSync(e)) {
119
+ const m = p.readFileSync(e, "utf-8");
120
+ if (s) {
121
+ const b = m.replace(l, "");
122
+ b || !$ ? p.writeFileSync(e, b, "utf-8") : (a.stage(`${o}模式下 文件为空 删除`), p.unlinkSync(e)), a.success(`${o}模式下${e}回滚完成`);
123
+ return;
124
+ }
125
+ const f = m + l;
126
+ p.writeFileSync(e, f, "utf-8"), a.success(`模板处理完成,追加到 ${e}`);
127
+ } else {
128
+ if (s) {
129
+ a.warn(`${o}模式下${e}不存在,无需回滚`);
130
+ return;
131
+ }
132
+ a.stage(`output:${e} 不存在,将创建`), p.writeFileSync(e, l, "utf-8"), a.success(`模板处理完成,输出到 ${e}`);
133
+ }
134
+ break;
135
+ }
136
+ case d.REPLACE: {
137
+ if (i && a.warn(`output ${i} 将被忽略`), X(o, c), u && u === c)
138
+ return a.error("env 与 input 不能相同"), process.exit(1);
139
+ const e = y.resolve(n, c);
140
+ let m = e;
141
+ const f = L(e)(v);
142
+ f !== e && (a.success(`检测输入文件名也需要替换
143
+ ${e} => ${f}`), p.rmSync(e), m = f), p.mkdirSync(y.dirname(m), { recursive: !0 }), p.writeFileSync(m, l, "utf-8"), a.success(`模板处理完成,输出到 ${m}`);
144
+ break;
145
+ }
146
+ case d.RETURN:
147
+ return a.success("模板处理完成,返回结果(函数调用才会拿到返回值)"), l;
148
+ default:
149
+ return a.error(`mode ${o} 不支持`), process.exit(1);
150
+ }
151
+ return l;
152
+ }, te = {
153
+ globalEnvData: {},
154
+ collectEnvDataForm: [
155
+ {
156
+ key: "name",
157
+ label: "项目名"
158
+ },
159
+ {
160
+ key: "chineseName",
161
+ label: "项目中文名"
162
+ },
163
+ {
164
+ key: "description",
165
+ label: "描述",
166
+ initial: "这是一个描述"
167
+ },
168
+ {
169
+ key: "repositoryUrl",
170
+ label: "仓库地址",
171
+ initial: "",
172
+ bindKey: "REPOSITORY_URL"
173
+ }
174
+ ],
175
+ list: [
176
+ {
177
+ input: "./package.json",
178
+ output: "./package.json",
179
+ mode: "replace"
180
+ },
181
+ {
182
+ input: "./README.md",
183
+ output: "./README.md",
184
+ mode: "replace"
185
+ }
186
+ ]
187
+ }, ne = () => P({
188
+ configPathDefault: _
189
+ }), ae = async (t) => {
190
+ let n = {};
191
+ if (t)
192
+ n = te;
193
+ else {
194
+ const { globalEnvCount: s, collectEnvCount: u, compileFileCount: c } = await A([
195
+ {
196
+ name: "globalEnvCount",
197
+ type: "number",
198
+ message: "全局固定变量数量",
199
+ initial: 1,
200
+ format: (r) => Number(r) || 0,
201
+ validate: (r) => r >= 0
202
+ },
203
+ {
204
+ name: "collectEnvCount",
205
+ type: "number",
206
+ message: "采集变量数量",
207
+ initial: 1,
208
+ format: (r) => Number(r) || 0,
209
+ validate: (r) => r >= 0
210
+ },
211
+ {
212
+ name: "compileFileCount",
213
+ type: "number",
214
+ message: "预编译文件数量",
215
+ initial: 1,
216
+ format: (r) => Number(r) || 0,
217
+ validate: (r) => r >= 0
218
+ }
219
+ ]);
220
+ s && (n.globalEnvData = Array.from({
221
+ length: s
222
+ }).reduce((r, i, o) => (r[`GLOBAL_${o}`] = "", r), {})), u && (n.collectEnvDataForm = Array.from({
223
+ length: u
224
+ }).map((r, i) => ({
225
+ key: `COLLECT_KEY_${i}`,
226
+ label: `COLLECT_LABEL_${i}`,
227
+ initial: void 0
228
+ }))), c && (n.list = Array.from({
229
+ length: c
230
+ }).map((r, i) => ({
231
+ input: `(相对于命令运行目录)需要编译的模板文件路径${i}`,
232
+ output: `(相对于命令运行目录)编译后输出的文件路径${i}`,
233
+ mode: d.REPLACE
234
+ })));
235
+ }
236
+ return n;
237
+ }, U = async (t) => {
238
+ const n = await V(), s = await ae(n);
239
+ await W(s, t, {
240
+ edit: !0,
241
+ onFileGenerated(u) {
242
+ n || a.success(`配置文件已生成:${u}
243
+ 请具体需要替换
244
+ globalEnvData中的 GLOBAL_\${index}及其对应值
245
+ collectEnvDataForm各项中 COLLECT_KEY_\${index} COLLECT_LABEL_\${index}
246
+ list各项中的 input值 output值
247
+ `);
248
+ }
249
+ });
250
+ }, oe = {
251
+ command: R.INIT,
252
+ describe: "初始化配置文件",
253
+ options: ne(),
254
+ handler: U
255
+ }, I = () => ({
256
+ ...P({
257
+ configPathDefault: _
258
+ }),
259
+ rollbackDelAskAsYes: {
260
+ describe: "回滚删除询问默认yes(即不再额外询问,直接认为同意)",
261
+ type: "boolean",
262
+ default: !1
263
+ },
264
+ rollbackDelNullFile: {
265
+ describe: "回滚时是否删除空文件",
266
+ type: "boolean",
267
+ default: !1
268
+ },
269
+ dealMarkdown: {
270
+ alias: "d",
271
+ describe: "(检测是markdown)是否处理(单个)代码块包裹",
272
+ type: "boolean",
273
+ default: !1
274
+ },
275
+ rollback: {
276
+ alias: "r",
277
+ describe: "是否回滚",
278
+ type: "boolean",
279
+ default: !1
280
+ }
281
+ }), O = async ({
282
+ extraEnvData: t = {},
283
+ ...n
284
+ }, s) => {
285
+ var v;
286
+ const u = I(), {
287
+ rootDir: c = u.rootDir.default,
288
+ configPath: r = (v = u.configPath) == null ? void 0 : v.default,
289
+ rollback: i
290
+ } = n;
291
+ let o;
292
+ if (s ? o = s : o = await G({
293
+ rootDir: c,
294
+ configPath: r
295
+ }), !o)
296
+ return a.error("读取配置文件失败"), process.exit(1);
297
+ const {
298
+ list: $ = [],
299
+ globalEnvData: C = {},
300
+ collectEnvDataForm: D = []
301
+ } = o, E = {};
302
+ for (const l of D) {
303
+ let e, m, f;
304
+ typeof l == "string" ? (e = l, m = l, f = void 0) : (e = l.key, m = l.label, f = l.initial), E[e] = (await A({
305
+ type: "text",
306
+ name: e,
307
+ message: `请输入${m}`,
308
+ initial: f,
309
+ format: (b) => b.trim(),
310
+ validate: (b) => b.length > 0 || `${m}不能为空`
311
+ }))[e];
312
+ }
313
+ const N = $.map((l) => {
314
+ const { envData: e, env: m, input: f, output: b, ...H } = l;
315
+ return m && a.warn(`批量处理中 env:${m} 将被忽略, 只读envData`), {
316
+ ...H,
317
+ env: m,
318
+ input: f,
319
+ output: b,
320
+ envData: q(
321
+ {},
322
+ t,
323
+ C,
324
+ E,
325
+ e
326
+ ),
327
+ rollback: i
328
+ };
329
+ }), g = [];
330
+ for (const l of N) {
331
+ const e = await x(l, {
332
+ rootDir: c,
333
+ rollback: i
334
+ });
335
+ g.push(e);
336
+ }
337
+ return g;
338
+ }, re = {
339
+ command: R.BATCH,
340
+ describe: "批量编译模板",
341
+ options: I(),
342
+ handler: O
343
+ }, M = () => ({
344
+ env: {
345
+ alias: "e",
346
+ describe: "环境数据文件JSON文件相对路径(优先级高于envData)",
347
+ type: "string"
348
+ },
349
+ envData: {
350
+ alias: "E",
351
+ describe: "环境变量数据(JSON字符串)",
352
+ type: "string"
353
+ },
354
+ input: {
355
+ alias: "i",
356
+ describe: "模板文件相对路径(优先级高于inputTemplate)",
357
+ type: "string"
358
+ },
359
+ inputData: {
360
+ alias: "I",
361
+ describe: "模板数据",
362
+ type: "string"
363
+ },
364
+ output: {
365
+ alias: "o",
366
+ describe: "输出文件路径",
367
+ type: "string"
368
+ },
369
+ mode: {
370
+ alias: "m",
371
+ describe: "输出模式",
372
+ type: "string",
373
+ choices: [
374
+ d.OVERWRITE,
375
+ d.APPEND,
376
+ d.REPLACE,
377
+ d.RETURN
378
+ ],
379
+ default: d.OVERWRITE
380
+ },
381
+ batch: {
382
+ alias: "b",
383
+ describe: "是否批量处理",
384
+ type: "boolean",
385
+ default: !1
386
+ },
387
+ ...I()
388
+ }), Y = async (t) => {
389
+ const n = M(), {
390
+ envData: s,
391
+ env: u,
392
+ input: c,
393
+ inputData: r,
394
+ output: i,
395
+ mode: o = n.mode.default,
396
+ batch: $,
397
+ ...C
398
+ } = t, {
399
+ rootDir: D = n.rootDir.default,
400
+ rollbackDelNullFile: E,
401
+ rollbackDelAskAsYes: N,
402
+ dealMarkdown: g,
403
+ rollback: v
404
+ } = C;
405
+ if ($)
406
+ return a.stage("开始批量处理"), O(C);
407
+ a.stage("开始单个处理");
408
+ const l = F({
409
+ rootDir: D,
410
+ filePath: u,
411
+ dataInit: s,
412
+ limitJson: !0,
413
+ filePathKey: "env",
414
+ dataInitKey: "envData",
415
+ dealMarkdown: g
416
+ });
417
+ return x(
418
+ {
419
+ input: c,
420
+ inputData: r,
421
+ output: i,
422
+ mode: o,
423
+ rollbackDelNullFile: E,
424
+ rollbackDelAskAsYes: N,
425
+ dealMarkdown: g,
426
+ envData: l
427
+ },
428
+ {
429
+ rootDir: D,
430
+ rollback: v
431
+ }
432
+ );
433
+ }, se = {
434
+ command: "$0",
435
+ describe: "编译模板",
436
+ options: M(),
437
+ handler: Y
438
+ }, fe = async (t, n) => {
439
+ switch (t) {
440
+ case R.INIT:
441
+ return U(n);
442
+ case R.COMPILE:
443
+ return Y(n);
444
+ case R.BATCH:
445
+ return O(n);
446
+ default:
447
+ throw new Error(`不支持的命令 ${t}`);
448
+ }
449
+ }, { version: ie, description: le } = h, j = {
450
+ describe: le,
451
+ version: ie,
452
+ subcommands: [
453
+ oe,
454
+ se,
455
+ re
456
+ ].map(S),
457
+ demandCommandCount: 1,
458
+ rootScriptName: J({ packageJson: h })
459
+ }, {
460
+ cliConfig: { moduleName: T }
461
+ } = h, B = (t = !1) => {
462
+ const n = t ? T : void 0, s = `$0${t ? ` ${T}` : ""} <command> [options]`;
463
+ return { command: n, usage: s };
464
+ }, $e = async () => K({
465
+ ...j,
466
+ ...B()
467
+ }), Ee = () => S({
468
+ ...j,
469
+ ...B(!0)
470
+ });
471
+ export {
472
+ _ as M,
473
+ d as O,
474
+ R as S,
475
+ ee as T,
476
+ Y as a,
477
+ O as b,
478
+ Ee as c,
479
+ Q as d,
480
+ $e as e,
481
+ fe as h
482
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "done-coding-template",
3
- "version": "0.7.12-alpha.0",
3
+ "version": "0.8.0",
4
4
  "description": "预编译命令行工具",
5
5
  "private": false,
6
6
  "module": "es/index.mjs",
@@ -30,7 +30,7 @@
30
30
  "license": "MIT",
31
31
  "sideEffects": false,
32
32
  "devDependencies": {
33
- "@done-coding/cli-inject": "^0.5.12-alpha.0",
33
+ "@done-coding/cli-inject": "^0.5.13",
34
34
  "@types/lodash.assign": "^4.2.9",
35
35
  "@types/lodash.template": "^4.5.3",
36
36
  "@types/node": "^18.0.0",
@@ -44,10 +44,10 @@
44
44
  "node": ">=18.0.0"
45
45
  },
46
46
  "dependencies": {
47
- "@done-coding/cli-utils": "^0.7.3-alpha.0",
47
+ "@done-coding/cli-utils": "^0.7.4",
48
48
  "lodash.assign": "^4.2.0",
49
49
  "lodash.template": "^4.5.0"
50
50
  },
51
- "gitHead": "9d9a2e60f255038a0f065e3a4e6d6d35488408ae",
51
+ "gitHead": "9b52d0d18f2b0f7e0498a8ef4dbd4a4c5fcd1ddf",
52
52
  "scripts": {}
53
53
  }
package/types/index.d.ts CHANGED
@@ -4,16 +4,10 @@ import type { InitConfigFileOptions } from '@done-coding/cli-utils';
4
4
  import type { ReadConfigFileOptions } from '@done-coding/cli-utils';
5
5
 
6
6
  /** 批量编译模板 */
7
- export declare const batchCompileHandler: ({ rootDir, configPath, itemDefaultRollback, extraEnvData, }: {
8
- /** 项目更目录 */
9
- rootDir: string;
10
- /** 配置文件路径 */
11
- configPath?: string | undefined;
12
- /** item默认回滚? */
13
- itemDefaultRollback?: boolean | undefined;
14
- /** 额外环境变量 */
7
+ export declare const batchCompileHandler: ({ extraEnvData, ...args }: CliHandlerArgv<CompileBatchOptions & {
8
+ /** 额外的环境变量 */
15
9
  extraEnvData?: object | undefined;
16
- }, paramsConfig?: CompileTemplateConfig) => Promise<(string | undefined)[]>;
10
+ }>, paramsConfig?: CompileTemplateConfig) => Promise<(string | undefined)[]>;
17
11
 
18
12
  /** 采集环境变量配置 */
19
13
  export declare interface CollectFormItem {
@@ -27,38 +21,45 @@ export declare interface CollectFormItem {
27
21
  bindKey?: TemplateBindKeyEnum;
28
22
  }
29
23
 
24
+ /** 批量模板编译配置项 */
25
+ export declare interface CompileBatchOptions extends CompilePublicConfig {
26
+ }
27
+
30
28
  /** 编译模板 */
31
29
  export declare const compileHandler: (argv: CliHandlerArgv<CompileOptions>) => Promise<string | (string | undefined)[] | undefined>;
32
30
 
33
- export declare interface CompileOptions {
31
+ /** 编译模板配置项 */
32
+ export declare interface CompileOptions extends CompilePublicConfig, CompileTemplateConfigListItemRaw {
33
+ /**
34
+ * 是否批量处理
35
+ * --
36
+ * 为true 走批量编译,此时configPath为批量编译配置文件路径 且必须
37
+ */
38
+ batch?: boolean;
39
+ }
40
+
41
+ /** 编译公共选项 */
42
+ export declare interface CompilePublicConfig {
34
43
  /** 项目根目录 */
35
44
  rootDir: string;
36
- /** 配置文件路径 */
45
+ /**
46
+ * 配置文件路径
47
+ * ---
48
+ * 不传拿默认值
49
+ */
37
50
  configPath?: string;
38
- /** 环境数据(json)文件(优先级高于 envData ) */
39
- env?: string;
40
- /** 环境变量数据(JSON字符串) */
41
- envData?: string;
42
- /** 模板文件相对路径(优先级高于 inputData ) */
43
- input?: string;
44
- /** 模板数据 */
45
- inputData?: string;
46
- /** 输出文件相对路径 */
47
- output?: string;
48
- /** 输出模式 @default OutputModeEnum.OVERWRITE */
49
- mode: OutputModeEnum;
50
- /** 是否回滚 @default false */
51
- rollback?: boolean;
52
51
  /**
53
52
  * 回滚删除空文件
54
53
  * ---
55
54
  * 只限 OutputModeEnum.APPEND 模式下生效
56
55
  */
57
56
  rollbackDelNullFile?: boolean;
57
+ /** 回滚删除询问默认yes(即不再额外询问,直接认为同意) */
58
+ rollbackDelAskAsYes?: boolean;
58
59
  /** (检测是markdown)是否处理(单个)代码块包裹 */
59
60
  dealMarkdown?: boolean;
60
- /** 是否批量处理 */
61
- batch?: boolean;
61
+ /** 是否回滚 */
62
+ rollback?: boolean;
62
63
  }
63
64
 
64
65
  /** 编译模板配置 */
@@ -68,31 +69,46 @@ export declare interface CompileTemplateConfig {
68
69
  /** 采集环境变量表单配置 */
69
70
  collectEnvDataForm?: (CollectFormItem | string)[];
70
71
  /** 配置列表 */
71
- list?: Omit<CompileOptions, keyof ReadConfigFileOptions>[];
72
+ list?: CompileTemplateConfigListItemRaw[];
72
73
  }
73
74
 
74
75
  /**
75
76
  * 编译模板配置选项
76
77
  */
77
- export declare type CompileTemplateConfigListItem = Omit<CompileOptions, "envData" | keyof ReadConfigFileOptions> & {
78
+ export declare type CompileTemplateConfigListItem = Omit<CompileTemplateConfigListItemRaw & Omit<CompilePublicConfig, keyof ReadConfigFileOptions>, "envData" | "rollback"> & {
78
79
  /** 已经解析为对象的envData */
79
80
  envData: Record<string, any>;
80
81
  };
81
82
 
83
+ /** 编译模板配置项(原始的) */
84
+ export declare interface CompileTemplateConfigListItemRaw {
85
+ /** 环境数据(json)文件(优先级高于 envData ) */
86
+ env?: string;
87
+ /** 环境变量数据(JSON字符串) */
88
+ envData?: string;
89
+ /** 模板文件相对路径(优先级高于 inputData ) */
90
+ input?: string;
91
+ /** 模板数据(JSON字符串) */
92
+ inputData?: string;
93
+ /** 输出文件相对路径 */
94
+ output?: string;
95
+ /** 输出模式 @default OutputModeEnum.OVERWRITE */
96
+ mode: OutputModeEnum;
97
+ }
98
+
82
99
  /** 作为子命令创建 */
83
100
  export declare const crateAsSubcommand: () => CommandModule<{}, {}>;
84
101
 
85
102
  /** 获取配置文件路径 */
86
103
  export declare const getConfigPath: ({ rootDir, configPath, }: ReadConfigFileOptions) => string | undefined;
87
104
 
88
- /** 命令处理函数 */
89
- export declare const handler: (command: SubcommandEnum, argv: CliHandlerArgv<InitOptions | CompileOptions>) => Promise<string | void | (string | undefined)[]>;
90
-
91
- /** 初始化模板 */
92
- export declare const initHandler: (argv: CliHandlerArgv<InitOptions>) => Promise<void>;
105
+ export declare const handler: (command: SubcommandEnum, argv: CliHandlerArgv<any>) => Promise<string | void | (string | undefined)[]>;
93
106
 
94
107
  export declare type InitOptions = InitConfigFileOptions;
95
108
 
109
+ /** 模块配置相对路径 */
110
+ export declare const MODULE_CONFIG_RELATIVE_PATH: string;
111
+
96
112
  /** 模块默认配置文件相对路径 */
97
113
  export declare const MODULE_DEFAULT_CONFIG_RELATIVE_PATH: string;
98
114
 
@@ -113,7 +129,9 @@ export declare enum SubcommandEnum {
113
129
  /** 初始化模板 */
114
130
  INIT = "init",
115
131
  /** 编译模板 */
116
- COMPILE = "compile"
132
+ COMPILE = "compile",
133
+ /** 批量编译模板 */
134
+ BATCH = "batch"
117
135
  }
118
136
 
119
137
  /** 绑定的关键变量枚举 */
@@ -1,493 +0,0 @@
1
- #!/usr/bin/env node
2
- import { getConfigFileCommonOptions as I, getUseDefaultConfig as V, initHandlerCommon as W, log as a, xPrompts as R, readConfigFile as G, _curry as A, createSubcommand as S, getRootScriptName as J, createMainCommand as Y } from "@done-coding/cli-utils";
3
- import k from "node:path";
4
- import f from "node:fs";
5
- import P from "lodash.template";
6
- import B from "lodash.assign";
7
- var N = /* @__PURE__ */ ((e) => (e.INIT = "init", e.COMPILE = "compile", e))(N || {}), K = /* @__PURE__ */ ((e) => (e.REPOSITORY_URL = "REPOSITORY_URL", e))(K || {}), b = /* @__PURE__ */ ((e) => (e.OVERWRITE = "overwrite", e.APPEND = "append", e.REPLACE = "replace", e.RETURN = "return", e))(b || {});
8
- const L = {
9
- name: "@done-coding/cli-template",
10
- version: "0.7.12-alpha.0",
11
- description: "预编译命令行工具",
12
- bin: {
13
- "dc-template": "es/cli.mjs"
14
- },
15
- cliConfig: {
16
- namespaceDir: ".done-coding",
17
- moduleName: "template"
18
- }
19
- }, {
20
- cliConfig: { namespaceDir: q, moduleName: z }
21
- } = L, Z = `./${q}/${z}`, h = `${Z}.json`, v = {
22
- rollback: !1,
23
- dealMarkdown: !1,
24
- mode: b.OVERWRITE,
25
- batch: !1,
26
- rollbackDelNullFile: !1
27
- }, _ = (e) => {
28
- const {
29
- rollback: t,
30
- dealMarkdown: l,
31
- mode: c,
32
- batch: s,
33
- rootDir: o,
34
- configPath: i,
35
- rollbackDelNullFile: r,
36
- ...u
37
- } = e, { rootDir: g, configPath: D } = I({
38
- configPathDefault: h
39
- });
40
- return {
41
- rollback: t ?? v.rollback,
42
- rollbackDelNullFile: r ?? v.rollbackDelNullFile,
43
- dealMarkdown: l ?? v.dealMarkdown,
44
- mode: c ?? v.mode,
45
- batch: s ?? v.batch,
46
- rootDir: o ?? g.default,
47
- configPath: i ?? D.default,
48
- ...u
49
- };
50
- }, Q = () => ({
51
- env: {
52
- alias: "e",
53
- describe: "环境数据文件JSON文件相对路径(优先级高于envData)",
54
- type: "string"
55
- },
56
- envData: {
57
- alias: "E",
58
- describe: "环境变量数据(JSON字符串)",
59
- type: "string"
60
- },
61
- input: {
62
- alias: "i",
63
- describe: "模板文件相对路径(优先级高于inputTemplate)",
64
- type: "string"
65
- },
66
- inputData: {
67
- alias: "I",
68
- describe: "模板数据",
69
- type: "string"
70
- },
71
- mode: {
72
- alias: "m",
73
- describe: "输出模式",
74
- type: "string",
75
- choices: [
76
- b.OVERWRITE,
77
- b.APPEND,
78
- b.REPLACE,
79
- b.RETURN
80
- ],
81
- default: v.mode
82
- },
83
- output: {
84
- alias: "o",
85
- describe: "输出文件路径",
86
- type: "string"
87
- },
88
- rollback: {
89
- alias: "r",
90
- describe: "是否回滚",
91
- type: "boolean",
92
- default: v.rollback
93
- },
94
- dealMarkdown: {
95
- alias: "d",
96
- describe: "(检测是markdown)是否处理(单个)代码块包裹",
97
- type: "boolean",
98
- default: v.dealMarkdown
99
- },
100
- batch: {
101
- alias: "b",
102
- describe: "是否批量处理",
103
- type: "boolean",
104
- default: v.batch
105
- },
106
- ...I({
107
- configPathDefault: h
108
- })
109
- }), X = {
110
- globalEnvData: {},
111
- collectEnvDataForm: [
112
- {
113
- key: "name",
114
- label: "项目名"
115
- },
116
- {
117
- key: "chineseName",
118
- label: "项目中文名"
119
- },
120
- {
121
- key: "description",
122
- label: "描述",
123
- initial: "这是一个描述"
124
- },
125
- {
126
- key: "repositoryUrl",
127
- label: "仓库地址",
128
- initial: "",
129
- bindKey: "REPOSITORY_URL"
130
- }
131
- ],
132
- list: [
133
- {
134
- input: "./package.json",
135
- output: "./package.json",
136
- mode: "replace"
137
- },
138
- {
139
- input: "./README.md",
140
- output: "./README.md",
141
- mode: "replace"
142
- }
143
- ]
144
- }, ee = () => I({
145
- configPathDefault: h
146
- }), te = async (e) => {
147
- let t = {};
148
- if (e)
149
- t = X;
150
- else {
151
- const { globalEnvCount: l, collectEnvCount: c, compileFileCount: s } = await R([
152
- {
153
- name: "globalEnvCount",
154
- type: "number",
155
- message: "全局固定变量数量",
156
- initial: 1,
157
- format: (o) => Number(o) || 0,
158
- validate: (o) => o >= 0
159
- },
160
- {
161
- name: "collectEnvCount",
162
- type: "number",
163
- message: "采集变量数量",
164
- initial: 1,
165
- format: (o) => Number(o) || 0,
166
- validate: (o) => o >= 0
167
- },
168
- {
169
- name: "compileFileCount",
170
- type: "number",
171
- message: "预编译文件数量",
172
- initial: 1,
173
- format: (o) => Number(o) || 0,
174
- validate: (o) => o >= 0
175
- }
176
- ]);
177
- l && (t.globalEnvData = Array.from({
178
- length: l
179
- }).reduce((o, i, r) => (o[`GLOBAL_${r}`] = "", o), {})), c && (t.collectEnvDataForm = Array.from({
180
- length: c
181
- }).map((o, i) => ({
182
- key: `COLLECT_KEY_${i}`,
183
- label: `COLLECT_LABEL_${i}`,
184
- initial: void 0
185
- }))), s && (t.list = Array.from({
186
- length: s
187
- }).map((o, i) => ({
188
- input: `(相对于命令运行目录)需要编译的模板文件路径${i}`,
189
- output: `(相对于命令运行目录)编译后输出的文件路径${i}`,
190
- mode: b.REPLACE
191
- })));
192
- }
193
- return t;
194
- }, ne = async (e) => {
195
- const t = await V(), l = await te(t);
196
- await W(l, e, {
197
- edit: !0,
198
- onFileGenerated(c) {
199
- t || a.success(`配置文件已生成:${c}
200
- 请具体需要替换
201
- globalEnvData中的 GLOBAL_\${index}及其对应值
202
- collectEnvDataForm各项中 COLLECT_KEY_\${index} COLLECT_LABEL_\${index}
203
- list各项中的 input值 output值
204
- `);
205
- }
206
- });
207
- }, x = ({
208
- rootDir: e,
209
- filePath: t,
210
- dataInit: l,
211
- limitJson: c,
212
- filePathKey: s,
213
- dataInitKey: o,
214
- dealMarkdown: i = !1
215
- }) => {
216
- if (t) {
217
- if (c && !t.endsWith(".json"))
218
- return a.error(`${s}必须是json文件,请检查文件后缀名`), process.exit(1);
219
- const r = f.readFileSync(
220
- k.resolve(e, t),
221
- "utf-8"
222
- );
223
- let u = r;
224
- return i && t.endsWith(".md") && (u = r.replace(
225
- /^\s*```[a-zA-Z0-9]+\s*[\r\n]+([\s\S]+?)```\s*$/,
226
- "$1"
227
- )), c ? JSON.parse(u) : u;
228
- } else
229
- return l ? (a.info(`${s} 为空,将使用${o}作为数据`), c ? JSON.parse(l) : l) : (a.error(`${s}与${o}不能同时为空`), process.exit(1));
230
- }, w = (e, t) => {
231
- if (!t)
232
- return a.error(`${e}模式下output不能为空`), process.exit(1);
233
- }, F = (e, t) => {
234
- if (t && e === t)
235
- return a.error("output与input不能相同"), process.exit(1);
236
- }, ae = (e, t) => {
237
- if (!t)
238
- return a.error(`${e}模式下input不能为空`), process.exit(1);
239
- }, M = async (e, {
240
- rootDir: t,
241
- rollbackDelFileAgree: l = !1
242
- }) => {
243
- const {
244
- env: c,
245
- input: s,
246
- inputData: o,
247
- output: i,
248
- mode: r,
249
- rollback: u,
250
- rollbackDelNullFile: g,
251
- dealMarkdown: D,
252
- envData: E
253
- } = e;
254
- if (u)
255
- switch (r) {
256
- case b.REPLACE:
257
- case b.RETURN: {
258
- a.error(`${r}模式不支持回滚`);
259
- return;
260
- }
261
- }
262
- a.stage(`开始处理模板
263
- mode: ${r}
264
- rollback: ${u}
265
- `);
266
- const m = x({
267
- rootDir: t,
268
- filePath: s,
269
- dataInit: o,
270
- limitJson: !1,
271
- filePathKey: "input",
272
- dataInitKey: "inputData",
273
- dealMarkdown: D
274
- }), d = P(m), C = typeof E == "function" ? E() : E, p = d(C);
275
- switch (r) {
276
- case b.OVERWRITE: {
277
- w(r, i), F(i, s);
278
- const n = k.resolve(t, i);
279
- if (f.mkdirSync(k.dirname(n), { recursive: !0 }), f.existsSync(n)) {
280
- if (u)
281
- if (l || (await R({
282
- type: "confirm",
283
- name: "remove",
284
- message: `${r}模式下回滚将删除${n},是否继续?`
285
- })).remove) {
286
- f.rmSync(n, { force: !0 }), a.success(`${r}模式下${n}已删除`);
287
- return;
288
- } else {
289
- a.warn(`${r}模式下${n}回滚取消`);
290
- return;
291
- }
292
- a.info(`output:${n} 已存在,将覆盖`);
293
- } else {
294
- if (u) {
295
- a.warn(`${r}模式下${n}不存在,无需回滚`);
296
- return;
297
- }
298
- a.stage(`output:${n} 不存在,将创建`);
299
- }
300
- f.writeFileSync(n, p, "utf-8"), a.success(`模板处理完成,输出到 ${n}`);
301
- break;
302
- }
303
- case b.APPEND: {
304
- w(r, i), F(i, s);
305
- const n = k.resolve(t, i);
306
- if (f.mkdirSync(k.dirname(n), { recursive: !0 }), f.existsSync(n)) {
307
- const $ = f.readFileSync(n, "utf-8");
308
- if (u) {
309
- const O = $.replace(p, "");
310
- O || !g ? f.writeFileSync(n, O, "utf-8") : (a.stage(`${r}模式下 文件为空 删除`), f.unlinkSync(n)), a.success(`${r}模式下${n}回滚完成`);
311
- return;
312
- }
313
- const y = $ + p;
314
- f.writeFileSync(n, y, "utf-8"), a.success(`模板处理完成,追加到 ${n}`);
315
- } else {
316
- if (u) {
317
- a.warn(`${r}模式下${n}不存在,无需回滚`);
318
- return;
319
- }
320
- a.stage(`output:${n} 不存在,将创建`), f.writeFileSync(n, p, "utf-8"), a.success(`模板处理完成,输出到 ${n}`);
321
- }
322
- break;
323
- }
324
- case b.REPLACE: {
325
- if (i && a.warn(`output ${i} 将被忽略`), ae(r, s), c && c === s)
326
- return a.error("env 与 input 不能相同"), process.exit(1);
327
- const n = k.resolve(t, s);
328
- let $ = n;
329
- const y = P(n)(C);
330
- y !== n && (a.success(`检测输入文件名也需要替换
331
- ${n} => ${y}`), f.rmSync(n), $ = y), f.mkdirSync(k.dirname($), { recursive: !0 }), f.writeFileSync($, p, "utf-8"), a.success(`模板处理完成,输出到 ${$}`);
332
- break;
333
- }
334
- case b.RETURN:
335
- return a.success("模板处理完成,返回结果(函数调用才会拿到返回值)"), p;
336
- default:
337
- return a.error(`mode ${r} 不支持`), process.exit(1);
338
- }
339
- return p;
340
- }, oe = async ({
341
- rootDir: e,
342
- configPath: t = h,
343
- itemDefaultRollback: l = !1,
344
- extraEnvData: c = {}
345
- }, s) => {
346
- let o;
347
- if (s ? o = s : o = await G({
348
- rootDir: e,
349
- configPath: t
350
- }), !o)
351
- return a.error("读取配置文件失败"), process.exit(1);
352
- const {
353
- list: i = [],
354
- globalEnvData: r = {},
355
- collectEnvDataForm: u = []
356
- } = o, g = {};
357
- for (const m of u) {
358
- let d, C, p;
359
- typeof m == "string" ? (d = m, C = m, p = void 0) : (d = m.key, C = m.label, p = m.initial), g[d] = (await R({
360
- type: "text",
361
- name: d,
362
- message: `请输入${C}`,
363
- initial: p,
364
- format: (n) => n.trim(),
365
- validate: (n) => n.length > 0 || `${C}不能为空`
366
- }))[d];
367
- }
368
- const D = i.map((m) => {
369
- const { rollback: d = l } = m, {
370
- envData: C,
371
- env: p,
372
- input: n,
373
- output: $,
374
- ...y
375
- } = _(m);
376
- return p && a.warn(`批量处理中 env:${p} 将被忽略, 只读envData`), {
377
- ...y,
378
- env: p,
379
- input: n,
380
- output: $,
381
- envData: B(
382
- {},
383
- c,
384
- r,
385
- g,
386
- C
387
- ),
388
- rollback: d
389
- };
390
- }), E = [];
391
- for (const m of D) {
392
- const d = await M(m, {
393
- rollbackDelFileAgree: !0,
394
- rootDir: e
395
- });
396
- E.push(d);
397
- }
398
- return E;
399
- }, re = async (e) => {
400
- const {
401
- envData: t,
402
- env: l,
403
- input: c,
404
- inputData: s,
405
- output: o,
406
- mode: i,
407
- rollback: r,
408
- rollbackDelNullFile: u,
409
- dealMarkdown: g,
410
- batch: D,
411
- rootDir: E,
412
- configPath: m
413
- } = _(e);
414
- if (D)
415
- return a.stage("开始批量处理"), oe({
416
- // 回滚默认值 基于全局
417
- itemDefaultRollback: r,
418
- rootDir: E,
419
- configPath: m
420
- });
421
- a.stage("开始单个处理");
422
- const d = x({
423
- rootDir: E,
424
- filePath: l,
425
- dataInit: t,
426
- limitJson: !0,
427
- filePathKey: "env",
428
- dataInitKey: "envData",
429
- dealMarkdown: g
430
- });
431
- return M(
432
- {
433
- input: c,
434
- inputData: s,
435
- output: o,
436
- mode: i,
437
- rollback: r,
438
- rollbackDelNullFile: u,
439
- dealMarkdown: g,
440
- envData: d
441
- },
442
- {
443
- rootDir: E
444
- }
445
- );
446
- }, U = async (e, t) => e === N.INIT ? ne(t) : e === N.COMPILE ? re(t) : (a.error(`无效的命令: ${e}`), process.exit(1)), {
447
- version: ie,
448
- description: se,
449
- cliConfig: { moduleName: T }
450
- } = L, le = {
451
- command: N.INIT,
452
- describe: "初始化模板配置文件",
453
- options: ee(),
454
- handler: A(U)(
455
- N.INIT
456
- )
457
- }, ce = {
458
- command: N.COMPILE,
459
- describe: "编译模板",
460
- options: Q(),
461
- handler: A(U)(
462
- N.COMPILE
463
- )
464
- }, j = {
465
- describe: se,
466
- version: ie,
467
- subcommands: [le, ce].map(
468
- S
469
- ),
470
- demandCommandCount: 1,
471
- rootScriptName: J({ packageJson: L })
472
- }, H = (e = !1) => {
473
- const t = e ? T : void 0, l = `$0${e ? ` ${T}` : ""} <command> [options]`;
474
- return { command: t, usage: l };
475
- }, be = async () => Y({
476
- ...j,
477
- ...H()
478
- }), Ee = () => S({
479
- ...j,
480
- ...H(!0)
481
- });
482
- export {
483
- h as M,
484
- b as O,
485
- N as S,
486
- K as T,
487
- Ee as a,
488
- oe as b,
489
- re as c,
490
- be as d,
491
- U as h,
492
- ne as i
493
- };