@vc-shell/create-vc-app 1.1.98-rc.4 → 1.1.99-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +552 -26
  2. package/dist/cli/argv.d.ts +4 -0
  3. package/dist/cli/argv.d.ts.map +1 -0
  4. package/dist/cli/constants.d.ts +4 -0
  5. package/dist/cli/constants.d.ts.map +1 -0
  6. package/dist/cli/errors.d.ts +12 -0
  7. package/dist/cli/errors.d.ts.map +1 -0
  8. package/dist/cli/help.d.ts +3 -0
  9. package/dist/cli/help.d.ts.map +1 -0
  10. package/dist/cli/run.d.ts +2 -0
  11. package/dist/cli/run.d.ts.map +1 -0
  12. package/dist/cli/runtime.d.ts +7 -0
  13. package/dist/cli/runtime.d.ts.map +1 -0
  14. package/dist/cli/types.d.ts +30 -0
  15. package/dist/cli/types.d.ts.map +1 -0
  16. package/dist/cli/utils.d.ts +4 -0
  17. package/dist/cli/utils.d.ts.map +1 -0
  18. package/dist/cli/validation.d.ts +5 -0
  19. package/dist/cli/validation.d.ts.map +1 -0
  20. package/dist/commands/generate-blade.d.ts +16 -0
  21. package/dist/commands/generate-blade.d.ts.map +1 -0
  22. package/dist/index.js +1900 -530
  23. package/dist/templates/base/_package.json +5 -5
  24. package/dist/templates/base/ai-guides/.cursorrules-vc-shell +529 -0
  25. package/dist/templates/base/ai-guides/README.md +360 -0
  26. package/dist/templates/base/ai-guides/guides/AI_GUIDE.md +195 -0
  27. package/dist/templates/base/ai-guides/guides/blade-patterns.md +384 -0
  28. package/dist/templates/base/ai-guides/guides/complete-workflow.md +781 -0
  29. package/dist/templates/base/ai-guides/guides/composables-reference.md +338 -0
  30. package/dist/templates/base/ai-guides/guides/troubleshooting.md +529 -0
  31. package/dist/templates/base/ai-guides/guides/ui-components-reference.md +903 -0
  32. package/dist/templates/base/ai-guides/prompts/adapt-existing-module.md +1026 -0
  33. package/dist/templates/base/ai-guides/prompts/advanced-scenarios.md +852 -0
  34. package/dist/templates/base/ai-guides/prompts/api-client-generation.md +877 -0
  35. package/dist/templates/base/ai-guides/prompts/cli-usage.md +640 -0
  36. package/dist/templates/base/ai-guides/prompts/quick-start-scenarios.md +773 -0
  37. package/dist/templates/base/ai-guides/prompts/simple-modifications.md +987 -0
  38. package/dist/templates/base/src/main.ts +0 -4
  39. package/dist/templates/blades/details/blade.vue +175 -0
  40. package/dist/templates/blades/grid/blade.vue +340 -0
  41. package/dist/templates/composables/details-composable.ts +101 -0
  42. package/dist/templates/composables/grid-composable.ts +244 -0
  43. package/dist/templates/module/components/index.ts +2 -0
  44. package/dist/templates/module/components/widgets/index.ts +2 -0
  45. package/dist/templates/module/composables/index.ts +3 -0
  46. package/dist/templates/module/index.ts +13 -0
  47. package/dist/templates/module/locales/en.json +65 -0
  48. package/dist/templates/module/locales/index.ts +4 -0
  49. package/dist/templates/module/pages/index.ts +3 -0
  50. package/dist/templates/widgets/widget.vue +113 -0
  51. package/dist/utils/form-builder.d.ts +69 -0
  52. package/dist/utils/form-builder.d.ts.map +1 -0
  53. package/dist/utils/format.d.ts +24 -0
  54. package/dist/utils/format.d.ts.map +1 -0
  55. package/dist/utils/naming.d.ts +44 -0
  56. package/dist/utils/naming.d.ts.map +1 -0
  57. package/dist/utils/register-module.d.ts +21 -0
  58. package/dist/utils/register-module.d.ts.map +1 -0
  59. package/dist/workflows/create-app.d.ts +14 -0
  60. package/dist/workflows/create-app.d.ts.map +1 -0
  61. package/package.json +12 -7
  62. package/dist/templates/mocks/sample-data/constants.ts +0 -89
  63. package/dist/templates/mocks/sample-data/index.ts +0 -2
  64. package/dist/templates/mocks/sample-data/methods.ts +0 -65
  65. package/dist/templates/modules/classic-module/composables/index.ts +0 -2
  66. package/dist/templates/modules/classic-module/composables/use{{ModuleNamePascalCase}}Details/index.ts +0 -24
  67. package/dist/templates/modules/classic-module/composables/use{{ModuleNamePascalCase}}List/index.ts +0 -47
  68. package/dist/templates/modules/classic-module/index.ts +0 -8
  69. package/dist/templates/modules/classic-module/locales/en.json +0 -37
  70. package/dist/templates/modules/classic-module/locales/index.ts +0 -2
  71. package/dist/templates/modules/classic-module/pages/details.vue +0 -87
  72. package/dist/templates/modules/classic-module/pages/index.ts +0 -2
  73. package/dist/templates/modules/classic-module/pages/list.vue +0 -257
  74. package/dist/templates/sample/classic-module/composables/index.ts +0 -2
  75. package/dist/templates/sample/classic-module/composables/useDetails/index.ts +0 -54
  76. package/dist/templates/sample/classic-module/composables/useList/index.ts +0 -62
  77. package/dist/templates/sample/classic-module/index.ts +0 -8
  78. package/dist/templates/sample/classic-module/locales/en.json +0 -67
  79. package/dist/templates/sample/classic-module/locales/index.ts +0 -2
  80. package/dist/templates/sample/classic-module/pages/details.vue +0 -238
  81. package/dist/templates/sample/classic-module/pages/index.ts +0 -2
  82. package/dist/templates/sample/classic-module/pages/list.vue +0 -300
  83. package/dist/templates/sample/overrides/main.ts +0 -52
package/dist/index.js CHANGED
@@ -1,340 +1,122 @@
1
1
  #!/usr/bin/env node
2
- import Ae from "prompts";
3
- import Ne from "mri";
4
- import t from "chalk";
5
- import c from "node:path";
6
- import s from "node:fs";
7
- import { fileURLToPath as Oe } from "node:url";
8
- import { cwd as Me, exit as Ee, argv as Te } from "node:process";
9
- const Ue = "1.1.98-rc.4", I = {
10
- version: Ue
11
- };
12
- var Pe = typeof global == "object" && global && global.Object === Object && global, Le = typeof self == "object" && self && self.Object === Object && self, _e = Pe || Le || Function("return this")(), b = _e.Symbol, K = Object.prototype, ze = K.hasOwnProperty, De = K.toString, $ = b ? b.toStringTag : void 0;
13
- function Ie(e) {
14
- var r = ze.call(e, $), a = e[$];
15
- try {
16
- e[$] = void 0;
17
- var o = !0;
18
- } catch {
19
- }
20
- var i = De.call(e);
21
- return o && (r ? e[$] = a : delete e[$]), i;
22
- }
23
- var Ze = Object.prototype, Fe = Ze.toString;
24
- function Ve(e) {
25
- return Fe.call(e);
26
- }
27
- var He = "[object Null]", We = "[object Undefined]", Z = b ? b.toStringTag : void 0;
28
- function Be(e) {
29
- return e == null ? e === void 0 ? We : He : Z && Z in Object(e) ? Ie(e) : Ve(e);
30
- }
31
- function Je(e) {
32
- return e != null && typeof e == "object";
33
- }
34
- var Ge = "[object Symbol]";
35
- function Ye(e) {
36
- return typeof e == "symbol" || Je(e) && Be(e) == Ge;
37
- }
38
- function qe(e, r) {
39
- for (var a = -1, o = e == null ? 0 : e.length, i = Array(o); ++a < o; )
40
- i[a] = r(e[a], a, e);
41
- return i;
42
- }
43
- var Ke = Array.isArray, F = b ? b.prototype : void 0, V = F ? F.toString : void 0;
44
- function Q(e) {
45
- if (typeof e == "string")
46
- return e;
47
- if (Ke(e))
48
- return qe(e, Q) + "";
49
- if (Ye(e))
50
- return V ? V.call(e) : "";
51
- var r = e + "";
52
- return r == "0" && 1 / e == -1 / 0 ? "-0" : r;
53
- }
54
- function R(e) {
55
- return e == null ? "" : Q(e);
56
- }
57
- function Qe(e, r, a) {
58
- var o = -1, i = e.length;
59
- r < 0 && (r = -r > i ? 0 : i + r), a = a > i ? i : a, a < 0 && (a += i), i = r > a ? 0 : a - r >>> 0, r >>>= 0;
60
- for (var u = Array(i); ++o < i; )
61
- u[o] = e[o + r];
62
- return u;
63
- }
64
- function Xe(e, r, a) {
65
- var o = e.length;
66
- return a = a === void 0 ? o : a, !r && a >= o ? e : Qe(e, r, a);
67
- }
68
- var er = "\\ud800-\\udfff", rr = "\\u0300-\\u036f", ar = "\\ufe20-\\ufe2f", nr = "\\u20d0-\\u20ff", or = rr + ar + nr, tr = "\\ufe0e\\ufe0f", ir = "\\u200d", sr = RegExp("[" + ir + er + or + tr + "]");
69
- function X(e) {
70
- return sr.test(e);
71
- }
72
- function ur(e) {
73
- return e.split("");
74
- }
75
- var ee = "\\ud800-\\udfff", cr = "\\u0300-\\u036f", lr = "\\ufe20-\\ufe2f", fr = "\\u20d0-\\u20ff", pr = cr + lr + fr, mr = "\\ufe0e\\ufe0f", dr = "[" + ee + "]", U = "[" + pr + "]", P = "\\ud83c[\\udffb-\\udfff]", gr = "(?:" + U + "|" + P + ")", re = "[^" + ee + "]", ae = "(?:\\ud83c[\\udde6-\\uddff]){2}", ne = "[\\ud800-\\udbff][\\udc00-\\udfff]", xr = "\\u200d", oe = gr + "?", te = "[" + mr + "]?", br = "(?:" + xr + "(?:" + [re, ae, ne].join("|") + ")" + te + oe + ")*", vr = te + oe + br, yr = "(?:" + [re + U + "?", U, ae, ne, dr].join("|") + ")", hr = RegExp(P + "(?=" + P + ")|" + yr + vr, "g");
76
- function $r(e) {
77
- return e.match(hr) || [];
78
- }
79
- function Sr(e) {
80
- return X(e) ? $r(e) : ur(e);
81
- }
82
- function ie(e) {
83
- return function(r) {
84
- r = R(r);
85
- var a = X(r) ? Sr(r) : void 0, o = a ? a[0] : r.charAt(0), i = a ? Xe(a, 1).join("") : r.slice(1);
86
- return o[e]() + i;
87
- };
2
+ import o from "chalk";
3
+ import m from "node:path";
4
+ import { argv as me, cwd as _ } from "node:process";
5
+ import ue from "mri";
6
+ import x from "prompts";
7
+ import r from "node:fs";
8
+ import { fileURLToPath as X } from "node:url";
9
+ import Y from "prettier";
10
+ import { camelCase as F, snakeCase as v, upperFirst as T, kebabCase as N } from "lodash-es";
11
+ import pe from "pluralize";
12
+ function ge(t = me.slice(2)) {
13
+ return ue(t, {
14
+ alias: {
15
+ h: "help",
16
+ v: "version"
17
+ },
18
+ boolean: [
19
+ "help",
20
+ "version",
21
+ "overwrite",
22
+ "composable",
23
+ "locales",
24
+ "widget",
25
+ "is-workspace",
26
+ "skip-form-editor",
27
+ "skip-module-gen"
28
+ ],
29
+ string: ["name", "app-name", "package-name", "module-name", "base-path", "type", "module", "path", "form-fields"]
30
+ });
88
31
  }
89
- var L = ie("toUpperCase");
90
- function kr(e) {
91
- return L(R(e).toLowerCase());
32
+ function L(t) {
33
+ return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(t);
92
34
  }
93
- function Cr(e, r, a, o) {
94
- for (var i = -1, u = e == null ? 0 : e.length; ++i < u; )
95
- a = r(a, e[i], i, e);
96
- return a;
35
+ function A(t) {
36
+ return t.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
97
37
  }
98
- function wr(e) {
99
- return function(r) {
100
- return e?.[r];
101
- };
38
+ function ee(t) {
39
+ return t.trim().toLowerCase().replace(/\/+/g, "/").replace(/[^a-z0-9/-]+/g, "/").replace(/\/?$/, "/");
102
40
  }
103
- var jr = {
104
- // Latin-1 Supplement block.
105
- À: "A",
106
- Á: "A",
107
- Â: "A",
108
- Ã: "A",
109
- Ä: "A",
110
- Å: "A",
111
- à: "a",
112
- á: "a",
113
- â: "a",
114
- ã: "a",
115
- ä: "a",
116
- å: "a",
117
- Ç: "C",
118
- ç: "c",
119
- Ð: "D",
120
- ð: "d",
121
- È: "E",
122
- É: "E",
123
- Ê: "E",
124
- Ë: "E",
125
- è: "e",
126
- é: "e",
127
- ê: "e",
128
- ë: "e",
129
- Ì: "I",
130
- Í: "I",
131
- Î: "I",
132
- Ï: "I",
133
- ì: "i",
134
- í: "i",
135
- î: "i",
136
- ï: "i",
137
- Ñ: "N",
138
- ñ: "n",
139
- Ò: "O",
140
- Ó: "O",
141
- Ô: "O",
142
- Õ: "O",
143
- Ö: "O",
144
- Ø: "O",
145
- ò: "o",
146
- ó: "o",
147
- ô: "o",
148
- õ: "o",
149
- ö: "o",
150
- ø: "o",
151
- Ù: "U",
152
- Ú: "U",
153
- Û: "U",
154
- Ü: "U",
155
- ù: "u",
156
- ú: "u",
157
- û: "u",
158
- ü: "u",
159
- Ý: "Y",
160
- ý: "y",
161
- ÿ: "y",
162
- Æ: "Ae",
163
- æ: "ae",
164
- Þ: "Th",
165
- þ: "th",
166
- ß: "ss",
167
- // Latin Extended-A block.
168
- Ā: "A",
169
- Ă: "A",
170
- Ą: "A",
171
- ā: "a",
172
- ă: "a",
173
- ą: "a",
174
- Ć: "C",
175
- Ĉ: "C",
176
- Ċ: "C",
177
- Č: "C",
178
- ć: "c",
179
- ĉ: "c",
180
- ċ: "c",
181
- č: "c",
182
- Ď: "D",
183
- Đ: "D",
184
- ď: "d",
185
- đ: "d",
186
- Ē: "E",
187
- Ĕ: "E",
188
- Ė: "E",
189
- Ę: "E",
190
- Ě: "E",
191
- ē: "e",
192
- ĕ: "e",
193
- ė: "e",
194
- ę: "e",
195
- ě: "e",
196
- Ĝ: "G",
197
- Ğ: "G",
198
- Ġ: "G",
199
- Ģ: "G",
200
- ĝ: "g",
201
- ğ: "g",
202
- ġ: "g",
203
- ģ: "g",
204
- Ĥ: "H",
205
- Ħ: "H",
206
- ĥ: "h",
207
- ħ: "h",
208
- Ĩ: "I",
209
- Ī: "I",
210
- Ĭ: "I",
211
- Į: "I",
212
- İ: "I",
213
- ĩ: "i",
214
- ī: "i",
215
- ĭ: "i",
216
- į: "i",
217
- ı: "i",
218
- Ĵ: "J",
219
- ĵ: "j",
220
- Ķ: "K",
221
- ķ: "k",
222
- ĸ: "k",
223
- Ĺ: "L",
224
- Ļ: "L",
225
- Ľ: "L",
226
- Ŀ: "L",
227
- Ł: "L",
228
- ĺ: "l",
229
- ļ: "l",
230
- ľ: "l",
231
- ŀ: "l",
232
- ł: "l",
233
- Ń: "N",
234
- Ņ: "N",
235
- Ň: "N",
236
- Ŋ: "N",
237
- ń: "n",
238
- ņ: "n",
239
- ň: "n",
240
- ŋ: "n",
241
- Ō: "O",
242
- Ŏ: "O",
243
- Ő: "O",
244
- ō: "o",
245
- ŏ: "o",
246
- ő: "o",
247
- Ŕ: "R",
248
- Ŗ: "R",
249
- Ř: "R",
250
- ŕ: "r",
251
- ŗ: "r",
252
- ř: "r",
253
- Ś: "S",
254
- Ŝ: "S",
255
- Ş: "S",
256
- Š: "S",
257
- ś: "s",
258
- ŝ: "s",
259
- ş: "s",
260
- š: "s",
261
- Ţ: "T",
262
- Ť: "T",
263
- Ŧ: "T",
264
- ţ: "t",
265
- ť: "t",
266
- ŧ: "t",
267
- Ũ: "U",
268
- Ū: "U",
269
- Ŭ: "U",
270
- Ů: "U",
271
- Ű: "U",
272
- Ų: "U",
273
- ũ: "u",
274
- ū: "u",
275
- ŭ: "u",
276
- ů: "u",
277
- ű: "u",
278
- ų: "u",
279
- Ŵ: "W",
280
- ŵ: "w",
281
- Ŷ: "Y",
282
- ŷ: "y",
283
- Ÿ: "Y",
284
- Ź: "Z",
285
- Ż: "Z",
286
- Ž: "Z",
287
- ź: "z",
288
- ż: "z",
289
- ž: "z",
290
- IJ: "IJ",
291
- ij: "ij",
292
- Œ: "Oe",
293
- œ: "oe",
294
- ʼn: "'n",
295
- ſ: "s"
296
- }, Rr = wr(jr), Ar = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g, Nr = "\\u0300-\\u036f", Or = "\\ufe20-\\ufe2f", Mr = "\\u20d0-\\u20ff", Er = Nr + Or + Mr, Tr = "[" + Er + "]", Ur = RegExp(Tr, "g");
297
- function Pr(e) {
298
- return e = R(e), e && e.replace(Ar, Rr).replace(Ur, "");
299
- }
300
- var Lr = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
301
- function _r(e) {
302
- return e.match(Lr) || [];
303
- }
304
- var zr = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
305
- function Dr(e) {
306
- return zr.test(e);
307
- }
308
- var se = "\\ud800-\\udfff", Ir = "\\u0300-\\u036f", Zr = "\\ufe20-\\ufe2f", Fr = "\\u20d0-\\u20ff", Vr = Ir + Zr + Fr, ue = "\\u2700-\\u27bf", ce = "a-z\\xdf-\\xf6\\xf8-\\xff", Hr = "\\xac\\xb1\\xd7\\xf7", Wr = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", Br = "\\u2000-\\u206f", Jr = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", le = "A-Z\\xc0-\\xd6\\xd8-\\xde", Gr = "\\ufe0e\\ufe0f", fe = Hr + Wr + Br + Jr, pe = "['’]", H = "[" + fe + "]", Yr = "[" + Vr + "]", me = "\\d+", qr = "[" + ue + "]", de = "[" + ce + "]", ge = "[^" + se + fe + me + ue + ce + le + "]", Kr = "\\ud83c[\\udffb-\\udfff]", Qr = "(?:" + Yr + "|" + Kr + ")", Xr = "[^" + se + "]", xe = "(?:\\ud83c[\\udde6-\\uddff]){2}", be = "[\\ud800-\\udbff][\\udc00-\\udfff]", x = "[" + le + "]", ea = "\\u200d", W = "(?:" + de + "|" + ge + ")", ra = "(?:" + x + "|" + ge + ")", B = "(?:" + pe + "(?:d|ll|m|re|s|t|ve))?", J = "(?:" + pe + "(?:D|LL|M|RE|S|T|VE))?", ve = Qr + "?", ye = "[" + Gr + "]?", aa = "(?:" + ea + "(?:" + [Xr, xe, be].join("|") + ")" + ye + ve + ")*", na = "\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])", oa = "\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])", ta = ye + ve + aa, ia = "(?:" + [qr, xe, be].join("|") + ")" + ta, sa = RegExp([
309
- x + "?" + de + "+" + B + "(?=" + [H, x, "$"].join("|") + ")",
310
- ra + "+" + J + "(?=" + [H, x + W, "$"].join("|") + ")",
311
- x + "?" + W + "+" + B,
312
- x + "+" + J,
313
- oa,
314
- na,
315
- me,
316
- ia
317
- ].join("|"), "g");
318
- function ua(e) {
319
- return e.match(sa) || [];
320
- }
321
- function ca(e, r, a) {
322
- return e = R(e), r = r, r === void 0 ? Dr(e) ? ua(e) : _r(e) : e.match(r) || [];
323
- }
324
- var la = "['’]", fa = RegExp(la, "g");
325
- function _(e) {
326
- return function(r) {
327
- return Cr(ca(Pr(r).replace(fa, "")), e, "");
328
- };
41
+ function fe(t) {
42
+ return t.startsWith("/") && t.endsWith("/");
329
43
  }
330
- var G = _(function(e, r, a) {
331
- return r = r.toLowerCase(), e + (a ? kr(r) : r);
332
- }), pa = ie("toLowerCase"), ma = _(function(e, r, a) {
333
- return e + (a ? "_" : "") + r.toLowerCase();
334
- }), C = _(function(e, r, a) {
335
- return e + (a ? " " : "") + L(r);
336
- });
337
- const da = {
44
+ function ye(t) {
45
+ const e = [];
46
+ return t["package-name"] && !L(t["package-name"]) && e.push(`Invalid package name: ${t["package-name"]}`), t["base-path"] && !fe(t["base-path"]) && e.push(`Invalid base path: ${t["base-path"]}. Must start and end with "/"`), e;
47
+ }
48
+ const he = "1.1.99-alpha.0", U = {
49
+ version: he
50
+ };
51
+ function we() {
52
+ console.log(`
53
+ ${o.bold(o.green("create-vc-app"))} - Create a new VC Shell application or generate modules/blades
54
+
55
+ ${o.bold("Usage:")}
56
+ create-vc-app [project-name] [options] Create a new application
57
+ create-vc-app blade|generate Interactive generator (modules, blades, widgets)
58
+
59
+ ${o.bold("Create App Options:")}
60
+ --name, --app-name <name> Name of the application
61
+ --package-name <name> Package name (defaults to app name)
62
+ --base-path <path> Base path for the application [default: /apps/<app-name>/]
63
+ --skip-module-gen Skip module generation (create only base app)
64
+ --skip-form-editor Skip interactive form builder
65
+ --form-fields <json> JSON string with form field definitions
66
+ --overwrite Overwrite existing files without confirmation
67
+ --help, -h Show this help message
68
+ --version, -v Show version
69
+
70
+ ${o.bold("Blade Generator Options:")}
71
+ --module <name> Target module name
72
+ --type <grid|details> Blade type
73
+ --name <name> Blade name
74
+ --is-workspace Mark blade as workspace (main module blade)
75
+ --widget Generate widget instead of blade
76
+ --composable Generate composable
77
+ --locales Generate locales
78
+ --path <path> Target path
79
+
80
+ ${o.bold("Interactive Generator:")}
81
+ The blade/generate command provides an interactive menu to:
82
+ - Create new modules with Grid and/or Details blades
83
+ - Add blades to existing modules
84
+ - Generate widgets for existing blades
85
+ - Customize form fields interactively with rich components
86
+ - Automatically format generated code with Prettier
87
+
88
+ Features:
89
+ - Smart naming (no more "offerss" bugs)
90
+ - Filter support in Grid blades (staged/applied architecture)
91
+ - Proper useModificationTracker usage in Details blades
92
+ - All Vc components: VcInput, VcSelect, VcEditor, VcSwitch, VcGallery, etc.
93
+ - TODO comments for API client integration
94
+ - Automatic module registration in main.ts
95
+
96
+ ${o.bold("Examples:")}
97
+ ${o.gray("# Create new application interactively")}
98
+ ${o.gray("# Will prompt for: app name, package name, base path")}
99
+ ${o.gray("# Then use blade generator to create initial module")}
100
+ create-vc-app my-app
101
+
102
+ ${o.gray("# Create app without module (base only)")}
103
+ create-vc-app my-app --skip-module-gen
104
+
105
+ ${o.gray("# Interactive blade/module generator")}
106
+ create-vc-app blade
107
+
108
+ ${o.gray("# Create blade with custom form fields (non-interactive)")}
109
+ create-vc-app blade --module products --type details --name product-details \\
110
+ --form-fields '[{"name":"price","type":"currency","required":true},{"name":"description","type":"editor","required":false}]'
111
+
112
+ ${o.gray("# Generate widget interactively")}
113
+ create-vc-app blade --widget
114
+ `);
115
+ }
116
+ function be() {
117
+ console.log(`create-vc-app version ${U.version}`);
118
+ }
119
+ const Se = {
338
120
  _gitignore: ".gitignore",
339
121
  "_yarnrc.yml": ".yarnrc.yml",
340
122
  _browserslistrc: ".browserslistrc",
@@ -351,246 +133,1834 @@ const da = {
351
133
  _vscode: ".vscode",
352
134
  _yarn: ".yarn",
353
135
  "_package.json": "package.json"
354
- }, j = [
355
- // {
356
- // name: "dynamic",
357
- // display: "Dynamic view modules boilerplate",
358
- // },
359
- {
360
- name: "classic",
361
- display: "Classic view modules boilerplate"
136
+ }, $e = [".ts", ".vue", ".js", ".json", ".md"], Z = "18.0.0";
137
+ function Ee() {
138
+ const t = process.version.slice(1), [e] = t.split(".").map(Number), [n] = Z.split(".").map(Number);
139
+ return {
140
+ compatible: e >= n,
141
+ currentVersion: t,
142
+ minVersion: Z
143
+ };
144
+ }
145
+ async function P(t) {
146
+ try {
147
+ const e = r.readFileSync(t, "utf-8"), n = m.extname(t);
148
+ let a = "typescript";
149
+ n === ".vue" ? a = "vue" : n === ".json" ? a = "json" : n === ".md" ? a = "markdown" : n === ".css" || n === ".scss" ? a = "css" : n === ".html" ? a = "html" : n === ".js" || n === ".mjs" || n === ".cjs" ? a = "babel" : (n === ".ts" || n === ".mts" || n === ".cts") && (a = "typescript");
150
+ let s = null;
151
+ try {
152
+ s = await Y.resolveConfig(t, {
153
+ editorconfig: !0
154
+ });
155
+ } catch {
156
+ }
157
+ const l = {
158
+ ...{
159
+ endOfLine: "auto",
160
+ // Changed from "lf" to "auto"
161
+ singleAttributePerLine: !0
162
+ // Added for Vue files
163
+ },
164
+ ...s,
165
+ parser: a
166
+ // Always use detected parser
167
+ }, d = await Y.format(e, l);
168
+ r.writeFileSync(t, d, "utf-8");
169
+ } catch (e) {
170
+ console.warn(o.yellow(`⚠️ Warning: Could not format ${t}`)), console.warn(o.yellow(` ${e.message}`));
362
171
  }
363
- ], T = {
364
- classic: ["classic-module"],
365
- dynamic: ["dynamic-module"]
366
- };
367
- function ga() {
368
- console.log(`
369
- ${t.bold(t.green("create-vc-app"))} - Create a new VC Shell application
370
-
371
- ${t.bold("Usage:")}
372
- create-vc-app [project-name] [options]
373
-
374
- ${t.bold("Options:")}
375
- --name, --app-name <name> Name of the application
376
- --package-name <name> Package name (defaults to app name)
377
- --variant <variant> Module variant (classic|dynamic) [default: classic]
378
- --module-name <name> Module name (defaults to app name in title case)
379
- --base-path <path> Base path for the application [default: /apps/<app-name>/]
380
- --mocks Include additional module with sample data
381
- --overwrite Overwrite existing files without confirmation
382
- --help, -h Show this help message
383
- --version, -v Show version
172
+ }
173
+ async function te(t, e = [".ts", ".vue", ".js", ".json"]) {
174
+ const n = r.readdirSync(t);
175
+ for (const a of n) {
176
+ const s = m.join(t, a);
177
+ r.statSync(s).isDirectory() ? await te(s, e) : e.some((l) => a.endsWith(l)) && await P(s);
178
+ }
179
+ }
180
+ function W(t, e) {
181
+ const n = F(t), a = pe(t), s = F(a);
182
+ return {
183
+ entitySingular: t,
184
+ entityPlural: a,
185
+ moduleName: e,
186
+ entitySingularPascal: T(n),
187
+ entitySingularCamel: n,
188
+ entitySingularKebab: N(t),
189
+ entityPluralPascal: T(s),
190
+ entityPluralCamel: s,
191
+ entityPluralKebab: N(a),
192
+ moduleNamePascal: T(F(e)),
193
+ moduleNameUpperSnake: v(e).toUpperCase()
194
+ };
195
+ }
196
+ function z(t) {
197
+ return {
198
+ "{{EntityName}}": t.entitySingularPascal,
199
+ "{{EntityNamePlural}}": t.entityPluralPascal,
200
+ "{{entityName}}": t.entitySingularCamel,
201
+ "{{entityNamePlural}}": t.entityPluralCamel,
202
+ "{{entity-name}}": t.entitySingularKebab,
203
+ "{{entity-name-plural}}": t.entityPluralKebab,
204
+ "{{entity_name}}": v(t.entitySingular),
205
+ "{{entity_name_plural}}": v(t.entityPlural),
206
+ "{{ModuleName}}": t.moduleNamePascal,
207
+ "{{moduleName}}": F(t.moduleName),
208
+ "{{module-name}}": N(t.moduleName),
209
+ "{{MODULE_NAME}}": t.moduleNameUpperSnake,
210
+ "{{MODULE_NAME_UPPERCASE}}": t.moduleNameUpperSnake
211
+ };
212
+ }
213
+ function H(t, e) {
214
+ let n = t;
215
+ for (const [a, s] of Object.entries(e))
216
+ n = n.replace(new RegExp(a, "g"), s);
217
+ return n;
218
+ }
219
+ function ae(t) {
220
+ return t.replace(/'/g, "\\'").replace(/"/g, '\\"');
221
+ }
222
+ async function ne() {
223
+ const t = [];
224
+ let e = !0;
225
+ for (console.log(`
226
+ 📝 Configure form fields (press Ctrl+C to skip):
227
+ `); e; )
228
+ try {
229
+ const n = await x(
230
+ [
231
+ {
232
+ type: "text",
233
+ name: "name",
234
+ message: "Field name (e.g., price, description):",
235
+ validate: (a) => a ? /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(a) ? !0 : "Field name must be a valid identifier (letters, numbers, underscore)" : "Field name is required"
236
+ },
237
+ {
238
+ type: "select",
239
+ name: "type",
240
+ message: "Field type:",
241
+ choices: [
242
+ {
243
+ title: "Text Input",
244
+ value: "text"
245
+ /* Text */
246
+ },
247
+ {
248
+ title: "Textarea",
249
+ value: "textarea"
250
+ /* Textarea */
251
+ },
252
+ {
253
+ title: "Number",
254
+ value: "number"
255
+ /* Number */
256
+ },
257
+ {
258
+ title: "Date",
259
+ value: "date"
260
+ /* Date */
261
+ },
262
+ {
263
+ title: "Select Dropdown",
264
+ value: "select"
265
+ /* Select */
266
+ },
267
+ {
268
+ title: "Checkbox",
269
+ value: "checkbox"
270
+ /* Checkbox */
271
+ },
272
+ {
273
+ title: "Radio Button",
274
+ value: "radio"
275
+ /* RadioButton */
276
+ },
277
+ {
278
+ title: "Switch",
279
+ value: "switch"
280
+ /* Switch */
281
+ },
282
+ {
283
+ title: "Currency Input",
284
+ value: "currency"
285
+ /* Currency */
286
+ },
287
+ {
288
+ title: "Rich Text Editor",
289
+ value: "editor"
290
+ /* Editor */
291
+ },
292
+ {
293
+ title: "Image Upload",
294
+ value: "image"
295
+ /* Image */
296
+ },
297
+ {
298
+ title: "Multivalue Input",
299
+ value: "multivalue"
300
+ /* Multivalue */
301
+ },
302
+ {
303
+ title: "Gallery",
304
+ value: "gallery"
305
+ /* Gallery */
306
+ },
307
+ {
308
+ title: "Data Field",
309
+ value: "data-field"
310
+ /* DataField */
311
+ }
312
+ ]
313
+ },
314
+ {
315
+ type: (a) => a === "select" || a === "radio" ? "list" : null,
316
+ name: "options",
317
+ message: "Options (comma-separated):",
318
+ separator: ","
319
+ },
320
+ {
321
+ type: "text",
322
+ name: "label",
323
+ message: "Field label (optional, press Enter to skip):",
324
+ initial: ""
325
+ },
326
+ {
327
+ type: "confirm",
328
+ name: "required",
329
+ message: "Is this field required?",
330
+ initial: !1
331
+ },
332
+ {
333
+ type: "confirm",
334
+ name: "addAnother",
335
+ message: "Add another field?",
336
+ initial: !0
337
+ }
338
+ ],
339
+ {
340
+ onCancel: () => {
341
+ throw e = !1, new Error("cancelled");
342
+ }
343
+ }
344
+ );
345
+ if (!n.name) {
346
+ e = !1;
347
+ break;
348
+ }
349
+ t.push({
350
+ name: n.name,
351
+ type: n.type,
352
+ label: n.label || T(n.name),
353
+ required: n.required,
354
+ options: n.options
355
+ }), e = n.addAnother;
356
+ } catch (n) {
357
+ if (n.message === "cancelled")
358
+ break;
359
+ throw n;
360
+ }
361
+ return t;
362
+ }
363
+ function q(t, e) {
364
+ const n = v(t.name).toUpperCase(), a = t.required ? 'rules="required"' : "";
365
+ let s = "";
366
+ return t.type === "number" ? s = 'type="number"' : t.type === "date" && (s = 'type="date"'), ` <Field
367
+ v-slot="{ field, errorMessage, handleChange, errors }"
368
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
369
+ :model-value="item.${t.name}"
370
+ name="${t.name}"
371
+ ${a}
372
+ >
373
+ <VcInput
374
+ v-bind="field"
375
+ v-model="item.${t.name}"
376
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
377
+ :placeholder="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}_PLACEHOLDER')"
378
+ ${s}
379
+ ${t.required ? "required" : ""}
380
+ clearable
381
+ :error="!!errors.length"
382
+ :error-message="errorMessage"
383
+ @update:model-value="handleChange"
384
+ />
385
+ </Field>`;
386
+ }
387
+ function ve(t, e) {
388
+ const n = v(t.name).toUpperCase();
389
+ return ` <VcTextarea
390
+ v-model="item.${t.name}"
391
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
392
+ :placeholder="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}_PLACEHOLDER')"
393
+ ${t.required ? "required" : ""}
394
+ clearable
395
+ />`;
396
+ }
397
+ function Ie(t, e) {
398
+ const n = v(t.name).toUpperCase(), a = t.required ? 'rules="required"' : "", s = t.options?.map((c) => {
399
+ const l = ae(c);
400
+ return `{ value: '${l}', label: '${l}' }`;
401
+ }).join(", ") || "";
402
+ return ` <Field
403
+ v-slot="{ errorMessage, handleChange, errors }"
404
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
405
+ :model-value="item.${t.name}"
406
+ name="${t.name}"
407
+ ${a}
408
+ >
409
+ <VcSelect
410
+ v-model="item.${t.name}"
411
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
412
+ :placeholder="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}_PLACEHOLDER')"
413
+ :options="[${s}]"
414
+ option-value="value"
415
+ option-label="label"
416
+ searchable
417
+ ${t.required ? "required" : ""}
418
+ :clearable="false"
419
+ :error="!!errors.length"
420
+ :error-message="errorMessage"
421
+ @update:model-value="handleChange"
422
+ />
423
+ </Field>`;
424
+ }
425
+ function Ce(t, e) {
426
+ const n = v(t.name).toUpperCase(), a = t.required ? 'rules="required"' : "";
427
+ return ` <Field
428
+ v-slot="{ errorMessage, handleChange, errors }"
429
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
430
+ :model-value="item.${t.name}"
431
+ name="${t.name}"
432
+ ${a}
433
+ >
434
+ <VcEditor
435
+ v-model="item.${t.name}"
436
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
437
+ :placeholder="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}_PLACEHOLDER')"
438
+ ${t.required ? "required" : ""}
439
+ :error="!!errors.length"
440
+ :error-message="errorMessage"
441
+ @update:model-value="handleChange"
442
+ />
443
+ </Field>`;
444
+ }
445
+ function xe(t, e) {
446
+ const n = v(t.name).toUpperCase();
447
+ return ` <VcSwitch
448
+ v-model="item.${t.name}"
449
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
450
+ :tooltip="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}_TOOLTIP')"
451
+ :true-value="true"
452
+ :false-value="false"
453
+ />`;
454
+ }
455
+ function Ae(t, e) {
456
+ const n = v(t.name).toUpperCase();
457
+ return ` <VcCard :header="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')">
458
+ <VcGallery
459
+ :images="item.${t.name}"
460
+ multiple
461
+ @upload="assetsHandler.upload"
462
+ @sort="assetsHandler.edit"
463
+ @remove="assetsHandler.remove"
464
+ @edit="onGalleryItemEdit"
465
+ />
466
+ </VcCard>`;
467
+ }
468
+ function Ne(t) {
469
+ return `
470
+ // VcGallery Assets Handler Setup
471
+ // TODO: Import Image type from your API client (e.g., import { Image, IImage } from "@your-app/api/client")
472
+ const { upload, remove, edit, loading: assetsLoading } = useAssets();
384
473
 
385
- ${t.bold("Examples:")}
386
- create-vc-app my-app
387
- create-vc-app my-app --variant classic --mocks
388
- create-vc-app my-app --module-name "My Module" --base-path "/custom/path/"
389
- create-vc-app . --name existing-project --overwrite
474
+ /**
475
+ * Handles asset operations for VcGallery
476
+ * TODO: Update the path '${t}s/\${item.value?.id}' to match your entity structure
477
+ */
478
+ const assetsHandler = {
479
+ loading: assetsLoading,
480
+ async upload(files: FileList, startingSortOrder?: number) {
481
+ // TODO: Update path to match your entity (e.g., 'products/\${item.value?.id}')
482
+ const uploaded = await upload(files, \`${t}s/\${item.value?.id}\`, startingSortOrder);
483
+ // TODO: If using typed Image class, map: uploaded.map((x) => new Image(x))
484
+ item.value.images = [...(item.value?.images ?? []), ...uploaded];
485
+ },
486
+ async remove(file: ICommonAsset) {
487
+ if (await showConfirmation(t("COMMON.ALERTS.IMAGE_DELETE_CONFIRMATION"))) {
488
+ const remainingImages = remove([file], item.value?.images ?? []);
489
+ // TODO: If using typed Image class, map: remainingImages.map((x) => new Image(x))
490
+ item.value.images = remainingImages;
491
+ }
492
+ },
493
+ edit(files: ICommonAsset[]) {
494
+ const edited = edit(files, item.value?.images ?? []);
495
+ // TODO: If using typed Image class, map: edited.map((x) => new Image(x))
496
+ item.value.images = edited;
497
+ },
498
+ };
390
499
 
391
- ${t.bold("Non-interactive mode:")}
392
- create-vc-app my-app --variant classic --module-name "My Module" --mocks --overwrite
500
+ /**
501
+ * Opens asset details blade for editing
502
+ * TODO: Create AssetsDetails blade or remove this handler
503
+ */
504
+ const onGalleryItemEdit = (asset: ICommonAsset) => {
505
+ // openBlade({
506
+ // blade: { name: "AssetsDetails" },
507
+ // options: {
508
+ // asset: asset,
509
+ // assetEditHandler: (file: ICommonAsset) => assetsHandler.edit?.([file]),
510
+ // assetRemoveHandler: (file: ICommonAsset) => assetsHandler.remove?.(file),
511
+ // },
512
+ // });
513
+ console.log("Gallery item clicked:", asset);
514
+ };
515
+ `;
516
+ }
517
+ function Pe(t, e) {
518
+ const n = v(t.name).toUpperCase();
519
+ return ` <VcField
520
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
521
+ :model-value="item.${t.name}"
522
+ orientation="horizontal"
523
+ :aspect-ratio="[1, 2]"
524
+ type="text"
525
+ />`;
526
+ }
527
+ function Oe(t, e) {
528
+ const n = v(t.name).toUpperCase(), a = t.required ? 'rules="required"' : "";
529
+ return ` <Field
530
+ v-slot="{ field, errorMessage, handleChange, errors }"
531
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
532
+ :model-value="item.${t.name}"
533
+ name="${t.name}"
534
+ ${a}
535
+ >
536
+ <VcInputCurrency
537
+ v-bind="field"
538
+ v-model="item.${t.name}"
539
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
540
+ ${t.required ? "required" : ""}
541
+ clearable
542
+ :error="!!errors.length"
543
+ :error-message="errorMessage"
544
+ @update:model-value="handleChange"
545
+ />
546
+ </Field>`;
547
+ }
548
+ function Te(t, e) {
549
+ const n = v(t.name).toUpperCase(), a = t.required ? 'rules="required"' : "", s = t.options?.map((c) => {
550
+ const l = ae(c);
551
+ return ` <VcRadioButton
552
+ :model-value="item.${t.name}"
553
+ value="${l}"
554
+ :label="'${l}'"
555
+ @update:model-value="handleChange"
556
+ />`;
557
+ }).join(`
558
+ `) || "";
559
+ return ` <Field
560
+ v-slot="{ field, errorMessage, handleChange, errors }"
561
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
562
+ :model-value="item.${t.name}"
563
+ name="${t.name}"
564
+ ${a}
565
+ >
566
+ <div class="tw-space-y-2">
567
+ ${s}
568
+ </div>
569
+ <div v-if="errors.length" class="tw-text-red-500 tw-text-sm">{{ errorMessage }}</div>
570
+ </Field>`;
571
+ }
572
+ function Fe(t, e) {
573
+ const n = v(t.name).toUpperCase();
574
+ return ` <VcCheckbox
575
+ v-model="item.${t.name}"
576
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
577
+ />`;
578
+ }
579
+ function De(t, e) {
580
+ const n = v(t.name).toUpperCase(), a = t.required ? 'rules="required"' : "";
581
+ return ` <!-- TODO: Configure VcMultivalue dictionary and placeholder -->
582
+ <Field
583
+ v-slot="{ errorMessage, handleChange, errors }"
584
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
585
+ :model-value="item.${t.name}"
586
+ name="${t.name}"
587
+ ${a}
588
+ >
589
+ <VcMultivalue
590
+ v-model="item.${t.name}"
591
+ :label="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}')"
592
+ :placeholder="$t('${e}.PAGES.DETAILS.FORM.INFO.${n}_PLACEHOLDER')"
593
+ ${t.required ? "required" : ""}
594
+ :error="!!errors.length"
595
+ :error-message="errorMessage"
596
+ @update:model-value="handleChange"
597
+ />
598
+ </Field>`;
599
+ }
600
+ function Me(t) {
601
+ return t.some(
602
+ (e) => e.type === "gallery"
603
+ /* Gallery */
604
+ );
605
+ }
606
+ function R(t, e) {
607
+ return t.length === 0 ? oe(e) : t.map((n) => {
608
+ switch (n.type) {
609
+ case "text":
610
+ case "number":
611
+ case "date":
612
+ return q(n, e);
613
+ case "textarea":
614
+ return ve(n, e);
615
+ case "select":
616
+ return Ie(n, e);
617
+ case "editor":
618
+ return Ce(n, e);
619
+ case "switch":
620
+ return xe(n, e);
621
+ case "gallery":
622
+ return Ae(n, e);
623
+ case "data-field":
624
+ return Pe(n, e);
625
+ case "currency":
626
+ return Oe(n, e);
627
+ case "radio":
628
+ return Te(n, e);
629
+ case "checkbox":
630
+ return Fe(n, e);
631
+ case "multivalue":
632
+ return De(n, e);
633
+ case "image":
634
+ return q({
635
+ ...n,
636
+ type: "text"
637
+ /* Text */
638
+ }, e);
639
+ default:
640
+ return q(n, e);
641
+ }
642
+ }).join(`
393
643
 
394
- ${t.bold("Available variants:")}
395
- ${j.map((e) => ` ${e.name.padEnd(10)} - ${e.display}`).join(`
396
- `)}
397
644
  `);
398
645
  }
399
- function w(e) {
400
- return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(e);
646
+ function k(t) {
647
+ const e = {};
648
+ for (const n of t) {
649
+ const a = v(n.name).toUpperCase();
650
+ e[a] = n.label || T(n.name);
651
+ }
652
+ return e;
401
653
  }
402
- function p(e) {
403
- return e.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
654
+ function oe(t) {
655
+ return ` <Field
656
+ v-slot="{ field, errorMessage, handleChange, errors }"
657
+ :label="$t('${t}.PAGES.DETAILS.FORM.INFO.NAME')"
658
+ :model-value="item.name"
659
+ name="name"
660
+ rules="required"
661
+ >
662
+ <VcInput
663
+ v-bind="field"
664
+ v-model="item.name"
665
+ :label="$t('${t}.PAGES.DETAILS.FORM.INFO.NAME')"
666
+ :placeholder="$t('${t}.PAGES.DETAILS.FORM.INFO.NAME_PLACEHOLDER')"
667
+ required
668
+ clearable
669
+ :error="!!errors.length"
670
+ :error-message="errorMessage"
671
+ @update:model-value="handleChange"
672
+ />
673
+ </Field>
674
+
675
+ <VcField
676
+ :label="$t('${t}.PAGES.DETAILS.FORM.INFO.CREATED_DATE')"
677
+ :model-value="createdDate"
678
+ orientation="horizontal"
679
+ :aspect-ratio="[1, 2]"
680
+ type="text"
681
+ />`;
404
682
  }
405
- function Y(e) {
406
- return e.trim().toLowerCase().replace(/\/+/g, "/").replace(/[^a-z0-9/-]+/g, "/").replace(/\/?$/, "/");
683
+ async function Le(t, e, n) {
684
+ const a = m.join(t, "src", "main.ts");
685
+ if (!r.existsSync(a))
686
+ return console.log(o.yellow(`⚠️ main.ts not found at ${a}`)), console.log(o.yellow(" Please register the module manually.")), !1;
687
+ try {
688
+ let s = r.readFileSync(a, "utf-8");
689
+ const c = `import ${n}Module from "./modules/${e}";`, l = `.use(${n}Module, { router })`;
690
+ if (s.includes(c) || s.includes(`from "./modules/${e}"`))
691
+ return console.log(o.yellow(` Module ${e} is already registered in main.ts`)), !0;
692
+ const d = /^import\s+.+\s+from\s+['"]\.\/.+['"];?\s*$/gm, w = s.match(d);
693
+ if (w && w.length > 0) {
694
+ const p = w[w.length - 1], i = s.lastIndexOf(p);
695
+ s = s.slice(0, i + p.length) + `
696
+ ${c}` + s.slice(i + p.length);
697
+ } else {
698
+ const p = s.search(/^import/m);
699
+ p !== -1 && (s = s.slice(0, p) + `${c}
700
+ ` + s.slice(p));
701
+ }
702
+ const u = /(app\.use|\.use)\(router\)/, g = s.match(u);
703
+ if (g) {
704
+ const p = s.indexOf(g[0]);
705
+ let i = p;
706
+ for (; i > 0 && s[i - 1] !== `
707
+ `; )
708
+ i--;
709
+ const f = s.slice(i, p).match(/^\s*/)?.[0] || " ";
710
+ s = s.slice(0, i) + `${f}${l}
711
+ ` + s.slice(i);
712
+ } else {
713
+ const p = /(app\.use|\.use)\([^)]+\)/g, i = [...s.matchAll(p)];
714
+ if (i.length > 0) {
715
+ const f = i[i.length - 1], y = f.index + f[0].length;
716
+ s = s.slice(0, y) + `
717
+ ${l}` + s.slice(y);
718
+ }
719
+ }
720
+ return r.writeFileSync(a, s, "utf-8"), console.log(o.green("✓ Registered module in main.ts")), !0;
721
+ } catch (s) {
722
+ return console.log(o.yellow(`⚠️ Failed to auto-register module: ${s.message}`)), console.log(o.yellow(" Please register manually.")), !1;
723
+ }
407
724
  }
408
- function he(e) {
409
- if (s.existsSync(e))
410
- s.readdirSync(e).forEach((r) => {
411
- const a = c.join(e, r);
412
- s.lstatSync(a).isDirectory() ? he(a) : s.unlinkSync(a);
413
- });
414
- else
415
- return;
725
+ async function K(t, e) {
726
+ const n = m.join(t, "pages"), a = m.join(n, "index.ts");
727
+ try {
728
+ let s = "";
729
+ r.existsSync(a) && (s = r.readFileSync(a, "utf-8"));
730
+ for (const c of e) {
731
+ const l = `export { default as ${c.exportName} } from "./${c.fileName}.vue";`;
732
+ !s.includes(l) && !s.includes(`from "./${c.fileName}.vue"`) && (s += l + `
733
+ `);
734
+ }
735
+ return r.writeFileSync(a, s, "utf-8"), await P(a), console.log(o.green("✓ Updated pages/index.ts")), !0;
736
+ } catch (s) {
737
+ return console.log(o.yellow(`⚠️ Failed to update pages/index.ts: ${s.message}`)), !1;
738
+ }
416
739
  }
417
- function q(e) {
418
- const r = s.readdirSync(e);
419
- return r.length === 0 || r.length === 1 && r[0] === ".git";
740
+ class O extends Error {
741
+ exitCode;
742
+ constructor(e, n = 1) {
743
+ super(e), this.name = "CLIError", this.exitCode = n;
744
+ }
420
745
  }
421
- function xa(e) {
422
- const r = [];
423
- return e.variant && !j.some((a) => a.name === e.variant) && r.push(`Invalid variant: ${e.variant}. Available variants: ${j.map((a) => a.name).join(", ")}`), e["package-name"] && !w(e["package-name"]) && r.push(`Invalid package name: ${e["package-name"]}`), { valid: r.length === 0, errors: r };
746
+ class B extends O {
747
+ issues;
748
+ constructor(e) {
749
+ super("Validation failed", 1), this.name = "ValidationError", this.issues = e;
750
+ }
424
751
  }
425
- function ba() {
426
- return Ne(Te.slice(2), {
427
- alias: {
428
- h: "help",
429
- v: "version"
430
- },
431
- boolean: ["help", "version", "mocks", "overwrite"],
432
- string: ["name", "app-name", "package-name", "variant", "module-name", "base-path"]
433
- });
752
+ class E extends O {
753
+ constructor() {
754
+ super("Operation cancelled by user", 0), this.name = "UserCancelledError";
755
+ }
434
756
  }
435
- async function va() {
436
- const e = ba();
437
- if (e.help) {
438
- ga();
757
+ function se(t) {
758
+ if (!r.existsSync(t))
439
759
  return;
760
+ const e = m.relative(_(), t) || t;
761
+ throw new O(`File already exists: ${e}. Remove it or rename before regenerating.`);
762
+ }
763
+ async function le(t = {}) {
764
+ console.log(`
765
+ ${o.bold(o.green("@vc-shell/create-vc-app Generator"))}
766
+ `);
767
+ const e = t.path || _(), n = m.join(e, "package.json");
768
+ if (!r.existsSync(n))
769
+ throw new O("❌ No package.json found. Are you in a project directory?");
770
+ try {
771
+ if (t.module && t.type && t.name) {
772
+ console.log(o.cyan(`📝 Running in non-interactive mode
773
+ `)), await Re(e, {
774
+ moduleName: N(t.module),
775
+ // Normalize to kebab-case
776
+ bladeType: t.type,
777
+ entityName: t.name,
778
+ isWorkspace: t.isWorkspace ?? !1,
779
+ includeComposable: t.composable ?? !0,
780
+ includeLocales: t.locales ?? !0,
781
+ formFields: t.formFields,
782
+ skipFormEditor: t.skipFormEditor
783
+ });
784
+ return;
785
+ }
786
+ if (t.widget) {
787
+ await Q(e);
788
+ return;
789
+ }
790
+ let a;
791
+ t._skipActionPrompt ? a = "module" : a = (await x(
792
+ {
793
+ type: "select",
794
+ name: "action",
795
+ message: "What would you like to generate?",
796
+ choices: [
797
+ { title: "Module (with blades)", value: "module" },
798
+ { title: "Blade (in existing module)", value: "blade" },
799
+ { title: "Widget (for existing blade)", value: "widget" }
800
+ ]
801
+ },
802
+ {
803
+ onCancel: () => {
804
+ throw new E();
805
+ }
806
+ }
807
+ )).action, a === "module" ? await ke(e) : a === "blade" ? await je(e) : a === "widget" && await Q(e);
808
+ } catch (a) {
809
+ if (a instanceof E)
810
+ throw new E();
811
+ if (a instanceof O)
812
+ throw a;
813
+ const s = a instanceof Error ? a.message : String(a), c = a instanceof Error && a.stack ? `
814
+ ${a.stack}` : "";
815
+ throw new O(`
816
+ ❌ Generation failed: ${s}${c ? `
817
+ ${c}` : ""}`);
440
818
  }
441
- if (e.version) {
442
- console.log(`create-vc-app version ${I.version}`);
819
+ }
820
+ async function Re(t, e) {
821
+ const n = m.join(t, "src", "modules"), a = m.join(n, e.moduleName);
822
+ if (!r.existsSync(a)) {
823
+ console.log(o.cyan(`📦 Module "${e.moduleName}" not found. Creating new module...
824
+ `));
825
+ const y = {
826
+ moduleName: e.moduleName,
827
+ entitySingular: e.moduleName,
828
+ createBothBlades: !1,
829
+ createGridBlade: e.bladeType === "grid",
830
+ createDetailsBlade: e.bladeType === "details",
831
+ gridIsWorkspace: e.isWorkspace && e.bladeType === "grid",
832
+ detailsIsWorkspace: e.isWorkspace && e.bladeType === "details",
833
+ includeComposables: e.includeComposable,
834
+ includeLocales: e.includeLocales,
835
+ customizeForm: !1
836
+ };
837
+ await re(t, y, e.formFields, e.skipFormEditor), console.log(o.green(`✅ Module "${e.moduleName}" with ${e.bladeType} blade created successfully
838
+ `));
443
839
  return;
444
840
  }
445
- const r = xa(e);
446
- r.valid || (console.error(t.red("Error:")), r.errors.forEach((n) => console.error(t.red(` ${n}`))), process.exit(1)), console.log(` ${t.bold(t.green(`
447
- create-vc-app version: ${I.version}
448
- `))}`);
449
- const a = Me();
450
- let o = e._[0] || e.name || e["app-name"];
451
- const i = o || "vc-app", u = () => o === "." ? c.basename(c.resolve()) : o, $e = !!(o || e.name || e["app-name"]);
452
- let l;
453
- try {
454
- if ($e && e.variant) {
455
- o = o || e.name || e["app-name"] || i, o || (console.error(t.red("Project name is required")), process.exit(1)), s.existsSync(o) && !q(o) && !e.overwrite && (console.error(
456
- t.red(`Target directory "${o}" is not empty. Use --overwrite to overwrite existing files.`)
457
- ), process.exit(1));
458
- const n = u(), g = e["package-name"] || (w(n) ? n : p(n)), S = e["module-name"] || C(n), N = e["base-path"] || Y(`/apps/${p(n)}/`);
459
- l = {
460
- appName: p(o),
461
- packageName: g,
462
- variant: e.variant,
463
- moduleName: S,
464
- basePath: N,
465
- mocks: e.mocks || !1
466
- }, console.log(t.cyan("Creating app with the following configuration:")), console.log(t.cyan(` App name: ${l.appName}`)), console.log(t.cyan(` Package name: ${l.packageName}`)), console.log(t.cyan(` Variant: ${l.variant}`)), console.log(t.cyan(` Module name: ${l.moduleName}`)), console.log(t.cyan(` Base path: ${l.basePath}`)), console.log(t.cyan(` Mocks: ${l.mocks ? "Yes" : "No"}`)), console.log();
467
- } else
468
- l = await Ae(
841
+ const s = W(e.entityName, e.moduleName), c = z(s), l = V(), d = [];
842
+ let w = "", u = {}, g = [];
843
+ if (e.bladeType === "details" && e.formFields)
844
+ try {
845
+ g = JSON.parse(e.formFields), g.length > 0 && (w = R(g, s.moduleNameUpperSnake), u = k(g));
846
+ } catch (y) {
847
+ throw console.error(o.red("❌ Invalid form-fields JSON")), y;
848
+ }
849
+ const p = await j(
850
+ l,
851
+ a,
852
+ e.bladeType,
853
+ c,
854
+ e.isWorkspace,
855
+ w,
856
+ g
857
+ );
858
+ if (d.push(p), e.includeComposable) {
859
+ const y = await G(
860
+ l,
861
+ a,
862
+ e.bladeType,
863
+ s,
864
+ c
865
+ );
866
+ d.push(y);
867
+ const b = m.join(a, "composables", "index.ts"), h = `export * from "./${e.bladeType === "grid" ? `use${s.entitySingularPascal}List` : `use${s.entitySingularPascal}Details`}";
868
+ `;
869
+ r.existsSync(b) ? r.readFileSync(b, "utf-8").includes(h) || r.appendFileSync(b, h) : r.writeFileSync(b, h);
870
+ }
871
+ const i = e.bladeType === "grid" ? `${s.entitySingularPascal}List` : `${s.entitySingularPascal}Details`, f = e.bladeType === "grid" ? c["{{entity-name-plural}}"] : `${c["{{entity-name}}"]}-details`;
872
+ if (await K(a, [{ exportName: i, fileName: f }]), e.includeLocales && Object.keys(u).length > 0) {
873
+ const y = m.join(a, "locales", "en.json");
874
+ if (r.existsSync(y)) {
875
+ const b = JSON.parse(r.readFileSync(y, "utf-8"));
876
+ b.PAGES || (b.PAGES = {}), b.PAGES.DETAILS || (b.PAGES.DETAILS = {}), b.PAGES.DETAILS.FORM || (b.PAGES.DETAILS.FORM = {}), b.PAGES.DETAILS.FORM.INFO || (b.PAGES.DETAILS.FORM.INFO = {}), Object.assign(b.PAGES.DETAILS.FORM.INFO, u), r.writeFileSync(y, JSON.stringify(b, null, 2), "utf-8"), d.push(y);
877
+ }
878
+ }
879
+ console.log(o.cyan(`
880
+ ✨ Formatting files with Prettier...
881
+ `));
882
+ for (const y of d)
883
+ await P(y);
884
+ console.log(o.green(`
885
+ ✅ Blade generated successfully!
886
+ `));
887
+ }
888
+ async function ke(t, e, n, a) {
889
+ console.log(o.cyan(`
890
+ 📦 Creating new module
891
+ `));
892
+ let s;
893
+ {
894
+ let l = {
895
+ ...await x(
469
896
  [
470
897
  {
471
- name: "appName",
472
- type: o ? null : "text",
473
- message: t.reset("Project name:"),
474
- initial: i,
475
- onState: (n) => o = p(String(n.value).trim()) || i,
476
- format: (n) => p(String(n).trim())
477
- },
478
- {
479
- type: () => !s.existsSync(o) || q(o) ? null : "confirm",
480
- name: "overwrite",
481
- message: () => (o === "." ? "Current directory" : `Target directory "${o}"`) + " is not empty. Remove existing files and continue?"
482
- },
483
- {
484
- type: (n, { overwrite: g }) => {
485
- if (g === !1)
486
- throw new Error(t.red("✖") + " Operation cancelled");
487
- return null;
488
- },
489
- name: "overwriteChecker"
490
- },
491
- {
492
- name: "packageName",
493
- type: () => w(u()) ? null : "text",
494
- message: t.reset("Package name:"),
495
- initial: () => p(u()),
496
- validate: (n) => w(n) || "Invalid package.json name"
898
+ type: "text",
899
+ name: "moduleName",
900
+ message: "Module name (e.g., products, orders):",
901
+ validate: (d) => d.length > 0 ? !0 : "Module name is required",
902
+ format: (d) => N(d)
903
+ // Normalize to kebab-case
497
904
  },
498
905
  {
499
- name: "basePath",
500
906
  type: "text",
501
- message: t.reset("Base path:"),
502
- initial: () => "/apps/" + p(u()) + "/",
503
- format: (n) => Y(String(n).trim())
907
+ name: "entitySingular",
908
+ message: "Entity name (e.g., Product, Order):",
909
+ validate: (d) => d.length > 0 ? !0 : "Entity name is required"
504
910
  },
505
911
  {
506
- type: "select",
507
- name: "variant",
508
- message: t.reset("Select module variant:"),
509
- choices: j.map((n) => ({
510
- title: n.display,
511
- value: n.name
512
- }))
513
- },
912
+ type: "confirm",
913
+ name: "createBothBlades",
914
+ message: "Create both Grid and Details blades?",
915
+ initial: !0
916
+ }
917
+ ],
918
+ {
919
+ onCancel: () => {
920
+ throw new E();
921
+ }
922
+ }
923
+ ),
924
+ createGridBlade: !1,
925
+ createDetailsBlade: !1,
926
+ gridIsWorkspace: !1,
927
+ detailsIsWorkspace: !1,
928
+ includeComposables: !0,
929
+ includeLocales: !0,
930
+ customizeForm: !1
931
+ };
932
+ if (l.createBothBlades) {
933
+ const d = await x(
934
+ {
935
+ type: "select",
936
+ name: "workspace",
937
+ message: "Which blade should be the workspace blade (main module blade)?",
938
+ choices: [
939
+ { title: "Grid blade", value: "grid" },
940
+ { title: "Details blade", value: "details" },
941
+ { title: "None", value: "none" }
942
+ ]
943
+ },
944
+ {
945
+ onCancel: () => {
946
+ throw new E();
947
+ }
948
+ }
949
+ );
950
+ l.createGridBlade = !0, l.createDetailsBlade = !0, l.gridIsWorkspace = d.workspace === "grid", l.detailsIsWorkspace = d.workspace === "details";
951
+ } else {
952
+ const d = await x(
953
+ [
514
954
  {
515
- name: "moduleName",
516
- type: "text",
517
- message: t.reset("Module name:"),
518
- initial: () => C(u()),
519
- format: (n) => String(n).trim()
955
+ type: "select",
956
+ name: "bladeType",
957
+ message: "Which blade type?",
958
+ choices: [
959
+ { title: "Grid (List with table, search, pagination)", value: "grid" },
960
+ { title: "Details (Form with validation and toolbar)", value: "details" }
961
+ ]
520
962
  },
521
963
  {
522
- name: "mocks",
523
964
  type: "confirm",
524
- message: "Do you want to include additional module with sample data?",
525
- initial: !1
965
+ name: "isWorkspace",
966
+ message: "Make this a workspace blade (main module blade)?",
967
+ initial: !0
526
968
  }
527
969
  ],
528
970
  {
529
971
  onCancel: () => {
530
- throw new Error(t.red("✖") + " Creation cancelled");
972
+ throw new E();
531
973
  }
532
974
  }
533
975
  );
534
- } catch (n) {
535
- console.log(n.message), Ee(1);
536
- }
537
- const { packageName: Se, variant: v, moduleName: d, appName: z, basePath: ke, mocks: Ce } = l, A = /* @__PURE__ */ new Map([
538
- ["{{ModuleName}}", p(d)],
539
- ["{{ModuleNamePascalCase}}", L(G(d))],
540
- ["{{ModuleNameUppercase}}", d.toUpperCase()],
541
- ["{{ModuleNameUppercaseSnakeCase}}", ma(d).toUpperCase()],
542
- ["{{ModuleNameExports}}", pa(G(d))],
543
- ["{{ModuleNameSentenceCase}}", C(d)],
544
- ["{{AppName}}", z],
545
- ["{{AppNameSentenceCase}}", C(z)],
546
- ["{{BasePath}}", ke],
547
- ["{{PackageName}}", Se || u()]
548
- ]), f = c.join(a, o);
549
- s.existsSync(f) ? he(f) : s.existsSync(f) || s.mkdirSync(f), console.log(`
550
- Scaffolding app in ${f}...`);
551
- const we = c.resolve(Oe(import.meta.url), "..", "templates");
552
- function m(n, g = "") {
553
- const S = c.resolve(we, n), N = s.readdirSync(S);
554
- for (const y of N) {
555
- const O = c.join(S, y);
556
- let k = da[y] ?? y;
557
- for (const [D, h] of A.entries()) {
558
- const E = new RegExp(D, "g");
559
- k = k.replace(E, h);
976
+ l.createGridBlade = d.bladeType === "grid", l.createDetailsBlade = d.bladeType === "details", l.gridIsWorkspace = l.createGridBlade && d.isWorkspace, l.detailsIsWorkspace = l.createDetailsBlade && d.isWorkspace;
977
+ }
978
+ if (l.createDetailsBlade) {
979
+ const d = await x(
980
+ {
981
+ type: "confirm",
982
+ name: "customizeForm",
983
+ message: "Customize form fields interactively?",
984
+ initial: !1
985
+ },
986
+ {
987
+ onCancel: () => {
988
+ throw new E();
989
+ }
990
+ }
991
+ );
992
+ l.customizeForm = d.customizeForm;
993
+ }
994
+ s = l;
995
+ }
996
+ await re(t, s, n, a);
997
+ }
998
+ async function re(t, e, n, a) {
999
+ try {
1000
+ const s = W(e.entitySingular, e.moduleName), c = z(s), l = m.join(t, "src", "modules", e.moduleName);
1001
+ if (r.existsSync(l) && !We(l))
1002
+ throw new O(
1003
+ `Module "${e.moduleName}" already exists and is not empty. Use the blade generator to extend it instead of recreating.`
1004
+ );
1005
+ console.log(o.cyan(`
1006
+ 📁 Creating module structure...
1007
+ `));
1008
+ const d = [
1009
+ l,
1010
+ m.join(l, "pages"),
1011
+ m.join(l, "composables"),
1012
+ m.join(l, "locales"),
1013
+ m.join(l, "components"),
1014
+ m.join(l, "components", "widgets")
1015
+ ];
1016
+ for (const h of d)
1017
+ if (!r.existsSync(h))
1018
+ try {
1019
+ r.mkdirSync(h, { recursive: !0 }), console.log(o.green(`✓ Created directory: ${m.relative(t, h)}`));
1020
+ } catch ($) {
1021
+ throw new Error(`Failed to create directory ${h}: ${$.message}`);
1022
+ }
1023
+ const w = V(), u = [];
1024
+ let g = "", p = {};
1025
+ if (e.createGridBlade) {
1026
+ const h = await j(w, l, "grid", c, e.gridIsWorkspace);
1027
+ u.push(h);
1028
+ }
1029
+ let i = [];
1030
+ if (e.createDetailsBlade) {
1031
+ if (n)
1032
+ try {
1033
+ i = JSON.parse(n), i.length > 0 && (g = R(i, s.moduleNameUpperSnake), p = k(i));
1034
+ } catch ($) {
1035
+ throw console.error(o.red("❌ Invalid form-fields JSON")), $;
1036
+ }
1037
+ else e.customizeForm && !a && (i = await ne(), i.length > 0 && (g = R(i, s.moduleNameUpperSnake), p = k(i)));
1038
+ const h = await j(
1039
+ w,
1040
+ l,
1041
+ "details",
1042
+ c,
1043
+ e.detailsIsWorkspace,
1044
+ g,
1045
+ i
1046
+ );
1047
+ u.push(h);
1048
+ }
1049
+ if (e.includeComposables) {
1050
+ if (e.createGridBlade) {
1051
+ const $ = await G(w, l, "grid", s, c);
1052
+ u.push($);
1053
+ }
1054
+ if (e.createDetailsBlade) {
1055
+ const $ = await G(
1056
+ w,
1057
+ l,
1058
+ "details",
1059
+ s,
1060
+ c
1061
+ );
1062
+ u.push($);
560
1063
  }
561
- const M = c.join(f, g, k);
562
- if (s.statSync(O).isDirectory())
563
- s.mkdirSync(M, { recursive: !0 }), m(c.join(n, y), c.join(g, k));
564
- else if ([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".pdf", ".zip"].includes(
565
- c.extname(y).toLowerCase()
566
- ))
567
- s.copyFileSync(O, M);
568
- else {
569
- let h = s.readFileSync(O, "utf-8");
570
- for (const [E, je] of A.entries()) {
571
- const Re = new RegExp(E, "g");
572
- h = h.replace(Re, je);
1064
+ const h = await Be(l, e, s);
1065
+ u.push(h);
1066
+ }
1067
+ if (e.includeLocales) {
1068
+ const h = await Ve(l, s, c, p);
1069
+ u.push(h);
1070
+ const $ = m.join(l, "locales", "index.ts");
1071
+ r.writeFileSync($, `import en from "./en.json";
1072
+ export { en };
1073
+ `), u.push($);
1074
+ }
1075
+ const f = m.join(l, "index.ts");
1076
+ r.writeFileSync(f, `import * as pages from "./pages";
1077
+ import * as locales from "./locales";
1078
+ import { createAppModule } from "@vc-shell/framework";
1079
+
1080
+ export default createAppModule(pages, locales);
1081
+
1082
+ export * from "./composables";
1083
+ `), u.push(f);
1084
+ const b = [];
1085
+ e.createGridBlade && b.push({
1086
+ exportName: `${s.entitySingularPascal}List`,
1087
+ fileName: s.entityPluralKebab
1088
+ }), e.createDetailsBlade && b.push({
1089
+ exportName: `${s.entitySingularPascal}Details`,
1090
+ fileName: `${s.entitySingularKebab}-details`
1091
+ }), b.length > 0 && await K(l, b), console.log(o.cyan(`
1092
+ ✨ Formatting files with Prettier...
1093
+ `));
1094
+ for (const h of u)
1095
+ await P(h);
1096
+ console.log(o.green(`
1097
+ ✅ Module generated successfully!`)), console.log(o.cyan(`
1098
+ 📦 Registering module in main.ts...
1099
+ `));
1100
+ const S = await Le(t, e.moduleName, s.moduleNamePascal);
1101
+ console.log(o.cyan(`
1102
+ 📝 Next steps:`)), S ? (console.log(o.cyan(" 1. Update API client imports in the generated composables")), console.log(o.cyan(` 2. Customize the table columns and form fields as needed
1103
+ `))) : (console.log(o.cyan(" 1. Import the module in your main.ts:")), console.log(o.gray(` import ${s.moduleNamePascal}Module from "./modules/${e.moduleName}";`)), console.log(o.gray(` app.use(${s.moduleNamePascal}Module, { router });`)), console.log(o.cyan(" 2. Update API client imports in the generated composables")), console.log(o.cyan(` 3. Customize the table columns and form fields as needed
1104
+ `)));
1105
+ } catch (s) {
1106
+ throw console.error(o.red(`
1107
+ ❌ Module generation failed:`), s.message), s;
1108
+ }
1109
+ }
1110
+ async function je(t) {
1111
+ try {
1112
+ console.log(o.cyan(`
1113
+ 📄 Adding blade to existing module
1114
+ `));
1115
+ const e = m.join(t, "src", "modules");
1116
+ if (!r.existsSync(e))
1117
+ throw console.error(o.red("❌ No modules directory found at src/modules")), new Error("Modules directory not found");
1118
+ const n = r.readdirSync(e).filter((S) => r.statSync(m.join(e, S)).isDirectory());
1119
+ if (n.length === 0)
1120
+ throw console.error(o.red("❌ No existing modules found")), new Error("No existing modules found");
1121
+ const a = await x(
1122
+ [
1123
+ {
1124
+ type: "autocomplete",
1125
+ name: "moduleName",
1126
+ message: "Select existing module:",
1127
+ choices: n.map((S) => ({ title: S, value: S }))
1128
+ },
1129
+ {
1130
+ type: "text",
1131
+ name: "entitySingular",
1132
+ message: "Entity name (e.g., Product, Order):",
1133
+ validate: (S) => S.length > 0 ? !0 : "Entity name is required"
1134
+ },
1135
+ {
1136
+ type: "select",
1137
+ name: "bladeType",
1138
+ message: "Blade type:",
1139
+ choices: [
1140
+ { title: "Grid (List with table, search, pagination)", value: "grid" },
1141
+ { title: "Details (Form with validation and toolbar)", value: "details" }
1142
+ ]
1143
+ },
1144
+ {
1145
+ type: "confirm",
1146
+ name: "isWorkspace",
1147
+ message: "Is this a workspace blade?",
1148
+ initial: !1
1149
+ },
1150
+ {
1151
+ type: "confirm",
1152
+ name: "includeComposable",
1153
+ message: "Include composable?",
1154
+ initial: !0
1155
+ }
1156
+ ],
1157
+ {
1158
+ onCancel: () => {
1159
+ throw new E();
573
1160
  }
574
- s.writeFileSync(M, h);
575
1161
  }
1162
+ );
1163
+ let s = !1;
1164
+ a.bladeType === "details" && (s = (await x(
1165
+ {
1166
+ type: "confirm",
1167
+ name: "customizeForm",
1168
+ message: "Customize form fields interactively?",
1169
+ initial: !1
1170
+ },
1171
+ {
1172
+ onCancel: () => {
1173
+ throw new E();
1174
+ }
1175
+ }
1176
+ )).customizeForm);
1177
+ const c = W(a.entitySingular, a.moduleName), l = z(c), d = m.join(e, a.moduleName), w = V(), u = [];
1178
+ let g = "", p = {}, i = [];
1179
+ s && a.bladeType === "details" && (i = await ne(), i.length > 0 && (g = R(i, c.moduleNameUpperSnake), p = k(i)));
1180
+ const f = await j(
1181
+ w,
1182
+ d,
1183
+ a.bladeType,
1184
+ l,
1185
+ a.isWorkspace,
1186
+ g,
1187
+ i
1188
+ );
1189
+ if (u.push(f), a.includeComposable) {
1190
+ const S = await G(
1191
+ w,
1192
+ d,
1193
+ a.bladeType,
1194
+ c,
1195
+ l
1196
+ );
1197
+ u.push(S);
1198
+ const h = m.join(d, "composables", "index.ts"), I = `export * from "./${a.bladeType === "grid" ? `use${c.entitySingularPascal}List` : `use${c.entitySingularPascal}Details`}";
1199
+ `;
1200
+ r.existsSync(h) ? r.readFileSync(h, "utf-8").includes(I) || r.appendFileSync(h, I) : r.writeFileSync(h, I);
576
1201
  }
1202
+ if (Object.keys(p).length > 0) {
1203
+ const S = m.join(d, "locales", "en.json");
1204
+ if (r.existsSync(S)) {
1205
+ const h = JSON.parse(r.readFileSync(S, "utf-8")), $ = Object.keys(h)[0];
1206
+ $ && h[$]?.PAGES?.DETAILS?.FORM?.INFO && (h[$].PAGES.DETAILS.FORM.INFO = {
1207
+ ...h[$].PAGES.DETAILS.FORM.INFO,
1208
+ ...p
1209
+ }, r.writeFileSync(S, JSON.stringify(h, null, 2)), console.log(o.green("✓ Updated locales with custom fields")));
1210
+ }
1211
+ }
1212
+ const y = a.bladeType === "grid" ? `${c.entitySingularPascal}List` : `${c.entitySingularPascal}Details`, b = a.bladeType === "grid" ? l["{{entity-name-plural}}"] : `${l["{{entity-name}}"]}-details`;
1213
+ await K(d, [{ exportName: y, fileName: b }]), console.log(o.cyan(`
1214
+ ✨ Formatting files with Prettier...
1215
+ `));
1216
+ for (const S of u)
1217
+ await P(S);
1218
+ console.log(o.green(`
1219
+ ✅ Blade generated successfully!
1220
+ `));
1221
+ } catch (e) {
1222
+ throw console.error(o.red(`
1223
+ ❌ Blade generation failed:`), e.message), e;
577
1224
  }
578
- if (m("base"), T[v].forEach((n) => {
579
- m(`modules/${n}`, "src/modules/" + A.get("{{ModuleName}}"));
580
- }), Ce && (v === "dynamic" && T[v].forEach((n) => {
581
- m(`sample/${n}`, "src/modules/sample");
582
- }), v === "classic" && T[v].forEach((n) => {
583
- m(`sample/${n}`, "src/modules/sample");
584
- }), m("mocks", "src/modules/sample"), m("sample/overrides", "src")), console.log(`
585
- Done. You can now run application:
586
- `), f !== a) {
587
- const n = c.relative(a, f);
588
- console.log(
589
- ` ${t.bold(t.green(`cd ${n.includes(" ") ? `"${n}"` : n}`))}`
1225
+ }
1226
+ async function Q(t) {
1227
+ try {
1228
+ console.log(o.cyan(`
1229
+ 🧩 Creating widget
1230
+ `));
1231
+ const e = m.join(t, "src", "modules");
1232
+ if (!r.existsSync(e))
1233
+ throw console.error(o.red("❌ No modules directory found")), new Error("Modules directory not found");
1234
+ const n = r.readdirSync(e).filter((u) => r.statSync(m.join(e, u)).isDirectory());
1235
+ if (n.length === 0)
1236
+ throw console.error(o.red(" No existing modules found")), new Error("No existing modules found");
1237
+ const a = await x(
1238
+ {
1239
+ type: "autocomplete",
1240
+ name: "moduleName",
1241
+ message: "Select module:",
1242
+ choices: n.map((u) => ({ title: u, value: u }))
1243
+ },
1244
+ {
1245
+ onCancel: () => {
1246
+ throw new E();
1247
+ }
1248
+ }
1249
+ ), s = m.join(e, a.moduleName), c = m.join(s, "pages");
1250
+ if (!r.existsSync(c))
1251
+ throw console.error(o.red("❌ No pages directory found in this module")), new Error("Pages directory not found");
1252
+ const l = r.readdirSync(c).filter((u) => u.endsWith(".vue"));
1253
+ if (l.length === 0)
1254
+ throw console.error(o.red("❌ No blades found in this module")), new Error("No blades found in module");
1255
+ const d = await x(
1256
+ [
1257
+ {
1258
+ type: "autocomplete",
1259
+ name: "bladeName",
1260
+ message: "Select blade to register widget in:",
1261
+ choices: l.map((u) => ({ title: u, value: u.replace(".vue", "") }))
1262
+ },
1263
+ {
1264
+ type: "text",
1265
+ name: "widgetName",
1266
+ message: "Widget name (e.g., Stats, Chart, Items):",
1267
+ validate: (u) => u.length > 0 ? !0 : "Widget name is required"
1268
+ },
1269
+ {
1270
+ type: "text",
1271
+ name: "entityName",
1272
+ message: "Related entity name (e.g., Offer, Item, Review):",
1273
+ validate: (u) => u.length > 0 ? !0 : "Entity name is required"
1274
+ },
1275
+ {
1276
+ type: "select",
1277
+ name: "icon",
1278
+ message: "Widget icon:",
1279
+ choices: [
1280
+ { title: "List (material-list)", value: "material-list" },
1281
+ { title: "Sell/Price (material-sell)", value: "material-sell" },
1282
+ { title: "Shopping Cart (material-shopping_cart)", value: "material-shopping_cart" },
1283
+ { title: "Star/Rating (material-star)", value: "material-star" },
1284
+ { title: "Image (material-image)", value: "material-image" },
1285
+ { title: "Description (material-description)", value: "material-description" },
1286
+ { title: "Custom (enter manually)", value: "custom" }
1287
+ ]
1288
+ }
1289
+ ],
1290
+ {
1291
+ onCancel: () => {
1292
+ throw new E();
1293
+ }
1294
+ }
590
1295
  );
1296
+ let w = d.icon;
1297
+ w === "custom" && (w = (await x(
1298
+ {
1299
+ type: "text",
1300
+ name: "customIcon",
1301
+ message: "Enter custom icon name (e.g., material-dashboard):",
1302
+ validate: (g) => g.length > 0 ? !0 : "Icon is required"
1303
+ },
1304
+ {
1305
+ onCancel: () => {
1306
+ throw new E();
1307
+ }
1308
+ }
1309
+ )).customIcon), await Ge(s, d, w, a.moduleName);
1310
+ } catch (e) {
1311
+ throw console.error(o.red(`
1312
+ ❌ Widget generation failed:`), e.message), e;
1313
+ }
1314
+ }
1315
+ async function Ge(t, e, n, a) {
1316
+ try {
1317
+ const s = W(e.entityName, a), c = V(), l = m.join(c, "widgets", "widget.vue");
1318
+ if (!r.existsSync(l))
1319
+ throw new Error(`Widget template not found at ${l}`);
1320
+ const d = e.bladeName.match(/^(.+?)(-list|-details)?$/), w = d ? d[1] : e.bladeName, u = m.join(t, "components", "widgets"), g = m.join(u, N(e.widgetName)), p = m.join(g, `${N(e.widgetName)}-widget.vue`), i = m.join(g, "index.ts");
1321
+ if (!r.existsSync(g))
1322
+ try {
1323
+ r.mkdirSync(g, { recursive: !0 });
1324
+ } catch (C) {
1325
+ throw new Error(`Failed to create widget directory: ${C.message}`);
1326
+ }
1327
+ let f = r.readFileSync(l, "utf-8");
1328
+ const y = {
1329
+ "{{MODULE_NAME_UPPERCASE}}": v(a).toUpperCase(),
1330
+ "{{WIDGET_NAME_UPPERCASE}}": v(e.widgetName).toUpperCase(),
1331
+ "{{WIDGET_ICON}}": n,
1332
+ "{{EntityName}}": s.entitySingularPascal,
1333
+ "{{entityName}}": s.entitySingularCamel,
1334
+ "{{ParentEntity}}": T(F(w)),
1335
+ "{{parentEntityCamel}}": F(w),
1336
+ "{{BladeName}}": `${s.entitySingularPascal}List`
1337
+ };
1338
+ f = H(f, y), r.writeFileSync(p, f), console.log(o.green(`✓ Created widget: ${m.relative(process.cwd(), p)}`));
1339
+ const b = `${T(F(e.widgetName))}Widget`, S = `export { default as ${b} } from "./${N(e.widgetName)}-widget.vue";
1340
+ `;
1341
+ r.writeFileSync(i, S);
1342
+ const h = m.join(u, "index.ts"), $ = `export * from "./${N(e.widgetName)}";
1343
+ `;
1344
+ r.existsSync(h) ? r.readFileSync(h, "utf-8").includes($) || r.appendFileSync(h, $) : r.writeFileSync(h, $);
1345
+ const I = m.join(t, "locales", "en.json");
1346
+ if (r.existsSync(I))
1347
+ try {
1348
+ const C = JSON.parse(r.readFileSync(I, "utf-8")), M = Object.keys(C)[0];
1349
+ if (M) {
1350
+ C[M].WIDGETS || (C[M].WIDGETS = {});
1351
+ const J = v(e.widgetName).toUpperCase();
1352
+ C[M].WIDGETS[J] || (C[M].WIDGETS[J] = {
1353
+ TITLE: T(e.widgetName)
1354
+ }), r.writeFileSync(I, JSON.stringify(C, null, 2)), await P(I), console.log(o.green("✓ Updated locales with widget translations"));
1355
+ }
1356
+ } catch (C) {
1357
+ console.warn(o.yellow(`⚠️ Could not update locales: ${C.message}`));
1358
+ }
1359
+ const D = m.join(t, "pages", `${e.bladeName}.vue`);
1360
+ if (r.existsSync(D))
1361
+ try {
1362
+ await _e(D, b, s.entitySingularCamel), console.log(o.green(`✓ Registered widget in ${e.bladeName}.vue`));
1363
+ } catch (C) {
1364
+ console.warn(o.yellow(`⚠️ Could not auto-register widget in blade: ${C.message}`)), console.warn(o.yellow(" Please add the widget registration manually."));
1365
+ }
1366
+ await P(p), await P(i), r.existsSync(D) && await P(D), console.log(o.green(`
1367
+ ✅ Widget generated successfully!`)), console.log(o.cyan(`
1368
+ 📝 Widget is automatically registered in the blade!`)), console.log(o.cyan(` See TODO comments in widget file for API integration.
1369
+ `));
1370
+ } catch (s) {
1371
+ throw console.error(o.red(`
1372
+ ❌ Widget file creation failed:`), s.message), s;
591
1373
  }
592
- console.log(` ${t.bold(t.green("yarn"))}`), console.log(` ${t.bold(t.green("yarn serve"))}`);
593
1374
  }
594
- va().catch((e) => {
595
- console.error(e);
1375
+ async function _e(t, e, n) {
1376
+ let a = r.readFileSync(t, "utf-8");
1377
+ if (!new RegExp(
1378
+ `import\\s*\\{[^}]*\\b${e}\\b[^}]*\\}\\s*from\\s*["']\\.\\./components/widgets["']`
1379
+ ).test(a)) {
1380
+ const p = a.match(/import\s*\{([^}]+)\}\s*from\s*["']\.\.\/components\/widgets["']/);
1381
+ if (p) {
1382
+ const f = p[1].split(",").map((y) => y.trim()).filter(Boolean);
1383
+ if (!f.includes(e)) {
1384
+ f.push(e);
1385
+ const y = f.join(", ");
1386
+ a = a.replace(p[0], `import { ${y} } from "../components/widgets"`);
1387
+ }
1388
+ } else {
1389
+ const i = a.match(/<script\s+(?:setup\s+lang="ts"|lang="ts"\s+setup|setup)>/);
1390
+ if (i) {
1391
+ const f = a.indexOf(i[0]) + i[0].length, y = [...a.slice(f).matchAll(/import\s+[\s\S]+?;/g)];
1392
+ if (y.length > 0) {
1393
+ const b = y[y.length - 1], S = f + b.index + b[0].length;
1394
+ a = a.slice(0, S) + `
1395
+ import { ${e} } from "../components/widgets";` + a.slice(S);
1396
+ } else
1397
+ a = a.slice(0, f) + `
1398
+ import { ${e} } from "../components/widgets";
1399
+ ` + a.slice(f);
1400
+ }
1401
+ }
1402
+ }
1403
+ const c = `${e}`, l = ` registerWidget(
1404
+ {
1405
+ id: "${c}",
1406
+ component: ${e},
1407
+ props: { item },
1408
+ updateFunctionName: "updateActiveWidgetCount",
1409
+ // isVisible: computed(() => !!props.param), // Uncomment to show widget only when blade has param
1410
+ },
1411
+ blade?.value.id ?? "",
1412
+ );`, d = a.match(/function\s+registerWidgets\s*\(\s*\)\s*\{/);
1413
+ if (d) {
1414
+ const p = a.indexOf(d[0]) + d[0].length;
1415
+ let i = 1, f = p;
1416
+ for (let y = p; y < a.length && i > 0; y++)
1417
+ a[y] === "{" && i++, a[y] === "}" && i--, i === 1 && (f = y);
1418
+ a = a.slice(0, f) + `
1419
+ ` + l + `
1420
+ ` + a.slice(f);
1421
+ } else {
1422
+ const p = a.match(/defineExpose\s*\(/);
1423
+ if (p) {
1424
+ const i = a.indexOf(p[0]), f = `
1425
+ function registerWidgets() {
1426
+ ${l}
1427
+ }
1428
+
1429
+ registerWidgets();
1430
+
1431
+ `;
1432
+ a = a.slice(0, i) + f + a.slice(i);
1433
+ } else {
1434
+ const i = a.match(/<\/script>/);
1435
+ if (i) {
1436
+ const f = a.indexOf(i[0]), y = `
1437
+ function registerWidgets() {
1438
+ ${l}
1439
+ }
1440
+
1441
+ registerWidgets();
1442
+
1443
+ `;
1444
+ a = a.slice(0, f) + y + a.slice(f);
1445
+ }
1446
+ }
1447
+ }
1448
+ const w = ` unregisterWidget("${c}", blade?.value.id);`, u = a.match(/onBeforeUnmount\s*\(\s*\(\s*\)\s*=>\s*\{/);
1449
+ if (u) {
1450
+ const p = a.indexOf(u[0]) + u[0].length;
1451
+ a = a.slice(0, p) + `
1452
+ ` + w + `
1453
+ ` + a.slice(p);
1454
+ } else {
1455
+ const p = a.match(/defineExpose\s*\(/);
1456
+ if (p) {
1457
+ const i = a.indexOf(p[0]), f = `
1458
+ onBeforeUnmount(() => {
1459
+ ${w}
596
1460
  });
1461
+
1462
+ `;
1463
+ a = a.slice(0, i) + f + a.slice(i);
1464
+ }
1465
+ }
1466
+ const g = [
1467
+ // registerWidget and unregisterWidget come from useWidgets(), not direct imports
1468
+ { name: "useWidgets", from: "@vc-shell/framework" },
1469
+ { name: "useBlade", from: "@vc-shell/framework" },
1470
+ { name: "onBeforeUnmount", from: "vue" }
1471
+ // { name: "computed", from: "vue" }, // Not needed if isVisible is commented
1472
+ ];
1473
+ for (const { name: p, from: i } of g) {
1474
+ const f = i.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), y = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']${f}["']`, "g"), b = [...a.matchAll(y)];
1475
+ if (b.length > 0) {
1476
+ const S = b[0], $ = S[1].split(",").map((I) => I.trim()).filter(Boolean);
1477
+ if (!$.includes(p)) {
1478
+ $.push(p);
1479
+ const I = $.join(", ");
1480
+ a = a.replace(S[0], `import { ${I} } from "${i}"`);
1481
+ }
1482
+ } else {
1483
+ const S = a.match(/<script\s+(?:setup\s+lang="ts"|lang="ts"\s+setup|setup)>/);
1484
+ if (S) {
1485
+ const h = a.indexOf(S[0]) + S[0].length, $ = a.slice(h).match(/^[\s\n]*import/m);
1486
+ if ($) {
1487
+ const I = h + a.slice(h).indexOf($[0]);
1488
+ a = a.slice(0, I) + `import { ${p} } from "${i}";
1489
+ ` + a.slice(I);
1490
+ } else
1491
+ a = a.slice(0, h) + `
1492
+ import { ${p} } from "${i}";
1493
+ ` + a.slice(h);
1494
+ }
1495
+ }
1496
+ }
1497
+ if (!a.includes("const blade = useBlade()")) {
1498
+ const p = `
1499
+ const blade = useBlade();
1500
+ `, i = a.match(/const\s+\w+\s*=\s*[^;]+;(?=[^;]*const)/g);
1501
+ if (i && i.length > 0) {
1502
+ const f = i[i.length - 1], y = a.lastIndexOf(f) + f.length;
1503
+ a = a.slice(0, y) + p + a.slice(y);
1504
+ }
1505
+ }
1506
+ if (!a.includes("const { registerWidget, unregisterWidget } = useWidgets()")) {
1507
+ const p = `
1508
+ const { registerWidget, unregisterWidget } = useWidgets();
1509
+ `, i = a.match(/const blade = useBlade\(\);/);
1510
+ if (i) {
1511
+ const f = a.indexOf(i[0]) + i[0].length;
1512
+ a = a.slice(0, f) + p + a.slice(f);
1513
+ }
1514
+ }
1515
+ r.writeFileSync(t, a);
1516
+ }
1517
+ function V() {
1518
+ return m.resolve(X(import.meta.url), "..", "..", "templates");
1519
+ }
1520
+ async function j(t, e, n, a, s, c, l) {
1521
+ const d = m.join(t, "blades", n, "blade.vue"), w = n === "grid" ? `${a["{{entity-name-plural}}"]}.vue` : `${a["{{entity-name}}"]}-details.vue`, u = m.join(e, "pages", w);
1522
+ se(u);
1523
+ let g = r.readFileSync(d, "utf-8");
1524
+ if (s ? (g = g.replace(/{{isWorkspace}}/g, "true"), g = g.replace(
1525
+ /{{menuItem}}/g,
1526
+ `{
1527
+ id: "${a["{{entityName}}"]}",
1528
+ title: "${a["{{MODULE_NAME_UPPERCASE}}"]}.MENU.TITLE",
1529
+ icon: "material-list",
1530
+ priority: 1,
1531
+ }`
1532
+ )) : (g = g.replace(/{{isWorkspace}}/g, "false"), g = g.replace(/{{menuItem}}/g, "undefined")), n === "details") {
1533
+ if (c)
1534
+ g = g.replace(/\{\{FORM_FIELDS\}\}/g, c);
1535
+ else {
1536
+ const i = oe(a["{{MODULE_NAME_UPPERCASE}}"]);
1537
+ g = g.replace(/\{\{FORM_FIELDS\}\}/g, i);
1538
+ }
1539
+ if (l && Me(l)) {
1540
+ g = g.replace(/\{\{GALLERY_IMPORTS\}\}/g, `
1541
+ useAssets,
1542
+ ICommonAsset,`);
1543
+ const i = Ne(a["{{entityName}}"]);
1544
+ g = g.replace(/\{\{GALLERY_SCRIPT_ADDITIONS\}\}/g, i);
1545
+ } else
1546
+ g = g.replace(/\{\{GALLERY_IMPORTS\}\}/g, ""), g = g.replace(/\{\{GALLERY_SCRIPT_ADDITIONS\}\}/g, "");
1547
+ }
1548
+ return g = H(g, a), r.writeFileSync(u, g), console.log(o.green(`✓ Created ${n} blade: ${m.relative(process.cwd(), u)}`)), u;
1549
+ }
1550
+ async function G(t, e, n, a, s) {
1551
+ const c = n === "grid" ? "grid-composable.ts" : "details-composable.ts", l = m.join(t, "composables", c), d = n === "grid" ? `use${a.entitySingularPascal}List.ts` : `use${a.entitySingularPascal}Details.ts`, w = m.join(e, "composables", d);
1552
+ se(w);
1553
+ let u = r.readFileSync(l, "utf-8");
1554
+ return u = H(u, s), r.writeFileSync(w, u), console.log(o.green(`✓ Created composable: ${m.relative(process.cwd(), w)}`)), w;
1555
+ }
1556
+ function We(t) {
1557
+ const e = r.readdirSync(t);
1558
+ return e.length === 0 || e.length === 1 && e[0] === ".git";
1559
+ }
1560
+ async function Be(t, e, n) {
1561
+ const a = m.join(t, "composables", "index.ts");
1562
+ let s = "";
1563
+ return e.createGridBlade && (s += `export * from "./use${n.entitySingularPascal}List";
1564
+ `), e.createDetailsBlade && (s += `export * from "./use${n.entitySingularPascal}Details";
1565
+ `), r.writeFileSync(a, s), console.log(o.green("✓ Created composables index")), a;
1566
+ }
1567
+ async function Ve(t, e, n, a) {
1568
+ const s = m.join(t, "locales", "en.json"), c = {
1569
+ TITLE: "Information",
1570
+ NAME: "Name",
1571
+ NAME_PLACEHOLDER: `Enter ${e.entitySingularCamel} name`,
1572
+ CREATED_DATE: "Created Date"
1573
+ }, l = a && Object.keys(a).length > 0 ? { TITLE: "Information", ...a } : c, d = {
1574
+ [e.moduleNameUpperSnake]: {
1575
+ MENU: {
1576
+ TITLE: e.entityPluralPascal
1577
+ },
1578
+ PAGES: {
1579
+ LIST: {
1580
+ TITLE: e.entityPluralPascal,
1581
+ SEARCH: {
1582
+ PLACEHOLDER: `Search ${e.entityPluralCamel}...`
1583
+ },
1584
+ TOOLBAR: {
1585
+ REFRESH: "Refresh",
1586
+ ADD: `Add ${e.entitySingularPascal}`,
1587
+ DELETE: "Delete selected"
1588
+ },
1589
+ TABLE: {
1590
+ HEADER: {
1591
+ NAME: "Name",
1592
+ CREATED_DATE: "Created"
1593
+ },
1594
+ TOTALS: `{count} ${e.entityPluralCamel}`,
1595
+ FILTER: {
1596
+ STATUS: {
1597
+ TITLE: "Status",
1598
+ Active: "Active",
1599
+ Inactive: "Inactive",
1600
+ Pending: "Pending"
1601
+ },
1602
+ DATE: {
1603
+ TITLE: "Date Range",
1604
+ START_DATE: "Start Date",
1605
+ END_DATE: "End Date"
1606
+ },
1607
+ APPLY: "Apply",
1608
+ RESET: "Reset"
1609
+ }
1610
+ },
1611
+ EMPTY: {
1612
+ NO_ITEMS: `No ${e.entityPluralCamel} yet`,
1613
+ ADD: `Add ${e.entitySingularPascal}`
1614
+ },
1615
+ NOT_FOUND: {
1616
+ EMPTY: `No ${e.entityPluralCamel} found`,
1617
+ RESET: "Reset search"
1618
+ }
1619
+ },
1620
+ DETAILS: {
1621
+ TITLE: `New ${e.entitySingularPascal}`,
1622
+ TOOLBAR: {
1623
+ SAVE: "Save",
1624
+ DELETE: "Delete"
1625
+ },
1626
+ FORM: {
1627
+ INFO: l
1628
+ }
1629
+ },
1630
+ ALERTS: {
1631
+ DELETE: `Are you sure you want to delete this ${e.entitySingularCamel}?`,
1632
+ DELETE_SELECTED_CONFIRMATION: {
1633
+ MESSAGE: `Are you sure you want to delete {count} ${e.entityPluralCamel}?`,
1634
+ ALL: "all {totalCount}"
1635
+ },
1636
+ CLOSE_CONFIRMATION: "You have unsaved changes. Are you sure you want to close?",
1637
+ NOT_VALID: "Please fill all required fields correctly."
1638
+ }
1639
+ }
1640
+ }
1641
+ };
1642
+ return r.writeFileSync(s, JSON.stringify(d, null, 2)), console.log(o.green("✓ Created locales file")), s;
1643
+ }
1644
+ async function qe(t) {
1645
+ const { args: e, cwd: n } = t, a = e._[0] || e.name || e["app-name"], l = await Ue({
1646
+ args: e,
1647
+ defaultAppName: a || "vc-app",
1648
+ hasAllArgs: !!a
1649
+ });
1650
+ console.log(o.cyan(`
1651
+ 📋 Creating app with the following configuration:`)), console.log(o.cyan(` App name: ${l.appName}`)), console.log(o.cyan(` Package name: ${l.packageName}`)), console.log(o.cyan(` Base path: ${l.basePath}`)), console.log();
1652
+ const d = a === "." ? n : m.join(n, l.appName);
1653
+ He(d, {
1654
+ overwrite: !!e.overwrite
1655
+ }), console.log(o.cyan(`
1656
+ 📦 Scaffolding app in ${o.bold(d)}...`));
1657
+ const w = Ke(l), u = Je({
1658
+ templateName: "base",
1659
+ targetDirectory: d,
1660
+ replacements: w
1661
+ });
1662
+ return console.log(o.green(`✅ Created ${u} files`)), console.log(o.cyan(`
1663
+ 🎨 Formatting files with Prettier...`)), await Xe(d), e["skip-module-gen"] || await et(d, e), {
1664
+ root: d,
1665
+ filesCreated: u,
1666
+ config: l
1667
+ };
1668
+ }
1669
+ async function Ue(t) {
1670
+ const { args: e, defaultAppName: n, hasAllArgs: a } = t;
1671
+ if (a) {
1672
+ const s = A(e._[0] || e.name || e["app-name"] || n), c = e._[0] || e.name || e["app-name"] || s, l = e["package-name"] || (L(c) ? c : A(c)), d = ee(e["base-path"] || `/apps/${A(c)}/`);
1673
+ return {
1674
+ appName: s,
1675
+ packageName: l,
1676
+ moduleName: "",
1677
+ basePath: d
1678
+ };
1679
+ }
1680
+ return ze(n);
1681
+ }
1682
+ async function ze(t) {
1683
+ let e = t;
1684
+ try {
1685
+ const n = await x(
1686
+ [
1687
+ {
1688
+ name: "appName",
1689
+ type: "text",
1690
+ message: o.reset("Project name:"),
1691
+ initial: t,
1692
+ onState: (l) => {
1693
+ e = A(String(l.value).trim()) || t;
1694
+ },
1695
+ format: (l) => A(String(l).trim())
1696
+ },
1697
+ {
1698
+ type: () => !r.existsSync(e) || de(e) ? null : "confirm",
1699
+ name: "overwrite",
1700
+ message: () => (e === "." ? "Current directory" : `Target directory "${e}"`) + " is not empty. Remove existing files and continue?"
1701
+ },
1702
+ {
1703
+ type: (l, { overwrite: d }) => {
1704
+ if (d === !1)
1705
+ throw new E();
1706
+ return null;
1707
+ },
1708
+ name: "overwriteChecker"
1709
+ },
1710
+ {
1711
+ name: "packageName",
1712
+ type: () => L(e) ? null : "text",
1713
+ message: o.reset("Package name:"),
1714
+ initial: () => A(e),
1715
+ validate: (l) => L(l) || "Invalid package.json name"
1716
+ },
1717
+ {
1718
+ name: "basePath",
1719
+ type: "text",
1720
+ message: o.reset("Base path:"),
1721
+ initial: () => `/apps/${A(e)}/`,
1722
+ format: (l) => ee(String(l).trim())
1723
+ }
1724
+ ],
1725
+ {
1726
+ onCancel: () => {
1727
+ throw new E();
1728
+ }
1729
+ }
1730
+ ), a = n.appName || A(t), s = n.packageName || A(a), c = n.basePath || `/apps/${a}/`;
1731
+ return {
1732
+ appName: a,
1733
+ packageName: s,
1734
+ moduleName: "",
1735
+ basePath: c
1736
+ };
1737
+ } catch (n) {
1738
+ if (n instanceof E)
1739
+ throw n;
1740
+ const a = n;
1741
+ throw new B([a.message]);
1742
+ }
1743
+ }
1744
+ function He(t, e) {
1745
+ if (r.existsSync(t)) {
1746
+ if (!de(t) && !e.overwrite)
1747
+ throw new B([
1748
+ `Target directory "${t}" is not empty. Use --overwrite to overwrite existing files.`
1749
+ ]);
1750
+ ce(t);
1751
+ } else
1752
+ r.mkdirSync(t, { recursive: !0 });
1753
+ }
1754
+ function Ke(t) {
1755
+ return /* @__PURE__ */ new Map([
1756
+ ["{{AppName}}", t.appName],
1757
+ ["{{AppNameSentenceCase}}", tt(t.appName)],
1758
+ ["{{BasePath}}", t.basePath],
1759
+ ["{{PackageName}}", t.packageName]
1760
+ ]);
1761
+ }
1762
+ function Je(t) {
1763
+ const e = m.resolve(X(import.meta.url), "..", "..", "templates"), n = m.join(e, t.templateName);
1764
+ let a = 0;
1765
+ return ie(n, (s, c) => {
1766
+ const l = m.join(t.targetDirectory, c), d = Ye(l, t.replacements);
1767
+ if (r.statSync(s).isDirectory()) {
1768
+ r.mkdirSync(d, { recursive: !0 });
1769
+ return;
1770
+ }
1771
+ const u = m.dirname(d);
1772
+ if (r.existsSync(u) || r.mkdirSync(u, { recursive: !0 }), Qe(s))
1773
+ r.copyFileSync(s, d);
1774
+ else {
1775
+ const g = r.readFileSync(s, "utf-8"), p = Ze(g, t.replacements);
1776
+ r.writeFileSync(d, p);
1777
+ }
1778
+ a += 1;
1779
+ }), a;
1780
+ }
1781
+ function ie(t, e, n = "") {
1782
+ const a = r.readdirSync(t);
1783
+ for (const s of a) {
1784
+ const c = m.join(t, s), l = m.join(n, Se[s] ?? s);
1785
+ r.statSync(c).isDirectory() ? ie(c, e, l) : e(c, l);
1786
+ }
1787
+ }
1788
+ function Ye(t, e) {
1789
+ let n = t;
1790
+ for (const [a, s] of e) {
1791
+ const c = new RegExp(a, "g");
1792
+ n = n.replace(c, s);
1793
+ }
1794
+ return n;
1795
+ }
1796
+ function Ze(t, e) {
1797
+ let n = t;
1798
+ for (const [a, s] of e) {
1799
+ const c = new RegExp(a, "g");
1800
+ n = n.replace(c, s);
1801
+ }
1802
+ return n;
1803
+ }
1804
+ function Qe(t) {
1805
+ const e = m.extname(t).toLowerCase();
1806
+ return [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".pdf", ".zip"].includes(e);
1807
+ }
1808
+ function ce(t) {
1809
+ if (r.existsSync(t))
1810
+ for (const e of r.readdirSync(t)) {
1811
+ const n = m.join(t, e);
1812
+ r.lstatSync(n).isDirectory() ? ce(n) : r.unlinkSync(n);
1813
+ }
1814
+ }
1815
+ function de(t) {
1816
+ const e = r.readdirSync(t);
1817
+ return e.length === 0 || e.length === 1 && e[0] === ".git";
1818
+ }
1819
+ async function Xe(t) {
1820
+ try {
1821
+ await te(t, $e), console.log(o.green("✅ All files formatted"));
1822
+ } catch (e) {
1823
+ console.log(o.yellow(`⚠️ Some files could not be formatted: ${e.message}`));
1824
+ }
1825
+ }
1826
+ async function et(t, e) {
1827
+ console.log(o.cyan(`
1828
+ 🏗️ Creating module with blade generator...
1829
+ `));
1830
+ try {
1831
+ await le({
1832
+ name: void 0,
1833
+ type: void 0,
1834
+ module: void 0,
1835
+ composable: !0,
1836
+ locales: !0,
1837
+ widget: !1,
1838
+ isWorkspace: !0,
1839
+ path: t,
1840
+ formFields: e["form-fields"],
1841
+ skipFormEditor: e["skip-form-editor"],
1842
+ _skipActionPrompt: !0
1843
+ });
1844
+ } catch (n) {
1845
+ if (n instanceof E) {
1846
+ console.log(o.yellow(`
1847
+ ⚠️ Module generation cancelled`)), console.log(o.yellow(" You can add modules later using: create-vc-app blade"));
1848
+ return;
1849
+ }
1850
+ console.log(o.yellow(`
1851
+ ⚠️ Module generation failed: ${n.message}`)), console.log(o.yellow(" You can add modules later using: create-vc-app blade"));
1852
+ }
1853
+ }
1854
+ function tt(t) {
1855
+ return t.split("-").map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(" ");
1856
+ }
1857
+ async function at(t) {
1858
+ const e = ge(t);
1859
+ if (e.help)
1860
+ return we(), 0;
1861
+ if (e.version)
1862
+ return be(), 0;
1863
+ nt();
1864
+ const n = e._[0];
1865
+ if (n === "blade" || n === "generate")
1866
+ return await ot(e), 0;
1867
+ const a = ye(e);
1868
+ if (a.length > 0)
1869
+ throw new B(a);
1870
+ return lt(), await st(e), 0;
1871
+ }
1872
+ function nt() {
1873
+ const t = Ee();
1874
+ if (!t.compatible)
1875
+ throw new O(
1876
+ [
1877
+ o.red(`❌ Node.js ${t.minVersion} or higher is required.`),
1878
+ o.red(` Current version: ${t.currentVersion}`),
1879
+ o.yellow(`
1880
+ Please upgrade Node.js to continue.`)
1881
+ ].join(`
1882
+ `)
1883
+ );
1884
+ }
1885
+ async function ot(t) {
1886
+ const [, e] = t._;
1887
+ await le({
1888
+ name: e || t.name,
1889
+ type: t.type,
1890
+ module: t.module,
1891
+ composable: t.composable,
1892
+ locales: t.locales,
1893
+ widget: t.widget,
1894
+ isWorkspace: t["is-workspace"],
1895
+ path: t.path,
1896
+ formFields: t["form-fields"],
1897
+ skipFormEditor: t["skip-form-editor"]
1898
+ });
1899
+ }
1900
+ async function st(t) {
1901
+ try {
1902
+ const e = await qe({ args: t, cwd: _() });
1903
+ rt(e.root, e.config.packageName, e.config.basePath, e.filesCreated), it(e.root);
1904
+ } catch (e) {
1905
+ if (e instanceof E) {
1906
+ console.log(o.yellow(`
1907
+ ⚠️ Operation cancelled by user`)), console.log(o.gray(` No changes were made.
1908
+ `));
1909
+ return;
1910
+ }
1911
+ throw e;
1912
+ }
1913
+ }
1914
+ function lt() {
1915
+ const t = "═".repeat(50);
1916
+ console.log(o.bold(o.green(`
1917
+ ╔${t}╗`))), console.log(o.bold(o.green(`║ create-vc-app v${U.version}${" ".repeat(33 - String(U.version).length)}║`))), console.log(o.bold(o.green(`╚${t}╝
1918
+ `)));
1919
+ }
1920
+ function rt(t, e, n, a) {
1921
+ console.log(o.green(`
1922
+ ${"=".repeat(50)}`)), console.log(o.green(o.bold("✨ Application created successfully!"))), console.log(o.green(`${"=".repeat(50)}
1923
+ `)), console.log(o.cyan("📊 Summary:")), console.log(o.cyan(` Location: ${o.bold(t)}`)), console.log(o.cyan(` Package: ${o.bold(e)}`)), console.log(o.cyan(` Base path: ${o.bold(n)}`)), console.log(o.cyan(` Files created: ${o.bold(a.toString())}`));
1924
+ }
1925
+ function it(t) {
1926
+ console.log(o.cyan(`
1927
+ 🚀 Next steps:
1928
+ `));
1929
+ const e = _();
1930
+ if (t !== e) {
1931
+ const n = m.relative(e, t) || t, a = n.includes(" ") ? `"${n}"` : n;
1932
+ console.log(o.white(` 1. ${o.bold(o.cyan(`cd ${a}`))}`)), console.log(o.white(` 2. ${o.bold(o.cyan("yarn"))}`)), console.log(o.white(` 3. ${o.bold(o.cyan("yarn serve"))}`));
1933
+ } else
1934
+ console.log(o.white(` 1. ${o.bold(o.cyan("yarn"))}`)), console.log(o.white(` 2. ${o.bold(o.cyan("yarn serve"))}`));
1935
+ console.log(o.gray(`
1936
+ You can also run:`)), console.log(o.gray(" yarn build - Build for production")), console.log(o.gray(" yarn lint - Run linter")), console.log(o.gray(" create-vc-app blade - Generate modules/blades/widgets")), console.log();
1937
+ }
1938
+ async function ct() {
1939
+ try {
1940
+ await at(process.argv.slice(2));
1941
+ } catch (t) {
1942
+ dt(t);
1943
+ }
1944
+ }
1945
+ function dt(t) {
1946
+ if (t instanceof E && (console.log(o.yellow(`
1947
+ ⚠️ Operation cancelled by user
1948
+ `)), process.exit(0)), t instanceof B) {
1949
+ if (t.issues?.length) {
1950
+ console.error(o.red(`
1951
+ ❌ Validation errors:
1952
+ `));
1953
+ for (const n of t.issues)
1954
+ console.error(o.red(` • ${n}`));
1955
+ console.log(o.gray(`
1956
+ Run ${o.cyan("create-vc-app --help")} for usage information.
1957
+ `));
1958
+ }
1959
+ process.exit(t.exitCode);
1960
+ }
1961
+ t instanceof O && (console.error(t.message), process.exit(t.exitCode));
1962
+ const e = t instanceof Error ? t.message : String(t);
1963
+ console.error(o.red(`
1964
+ ❌ Unexpected error: ${e}`)), t instanceof Error && t.stack && console.error(o.gray(t.stack)), process.exit(1);
1965
+ }
1966
+ ct();