@vc-shell/create-vc-app 2.4.0 → 2.5.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 (32) hide show
  1. package/dist/commands/add-module.d.ts.map +1 -1
  2. package/dist/commands/init.d.ts.map +1 -1
  3. package/dist/engine/codegen.d.ts +5 -2
  4. package/dist/engine/codegen.d.ts.map +1 -1
  5. package/dist/engine/codegen.test.d.ts +2 -0
  6. package/dist/engine/codegen.test.d.ts.map +1 -0
  7. package/dist/engine/format.d.ts +13 -0
  8. package/dist/engine/format.d.ts.map +1 -0
  9. package/dist/index.js +330 -233
  10. package/dist/templates/dynamic-module/_package.json.ejs +3 -3
  11. package/dist/templates/dynamic-module/tsconfig.json +1 -5
  12. package/dist/templates/module/composables/useDetails.ts.ejs +1 -0
  13. package/dist/templates/module/composables/useList.ts.ejs +2 -1
  14. package/dist/templates/module/pages/list.vue.ejs +24 -4
  15. package/dist/templates/sample-module/composables/useList/index.ts +1 -1
  16. package/dist/templates/sample-module/pages/index.ts +1 -1
  17. package/dist/templates/sample-module/pages/list.vue +9 -1
  18. package/dist/templates/sample-module/sample-data/index.ts +2 -2
  19. package/dist/templates/standalone/_github/COMMIT_CONVENTION.md +12 -12
  20. package/dist/templates/standalone/_github/PULL_REQUEST_TEMPLATE.md +3 -0
  21. package/dist/templates/standalone/_package.json.ejs +4 -4
  22. package/dist/templates/standalone/_vscode/extensions.json +1 -3
  23. package/dist/templates/standalone/_vscode/settings.json +3 -8
  24. package/dist/templates/standalone/eslint.config.mjs +20 -0
  25. package/dist/templates/standalone/src/api_client/README.md +38 -37
  26. package/dist/templates/standalone/src/bootstrap.ts.ejs +1 -2
  27. package/dist/templates/standalone/src/components/dashboard-widgets/Welcome.vue +1 -2
  28. package/dist/templates/standalone/src/pages/App.vue.ejs +1 -0
  29. package/dist/templates/standalone/src/pages/Dashboard.vue.ejs +1 -1
  30. package/dist/templates/standalone/src/router/routes.ts.ejs +12 -15
  31. package/dist/templates/standalone/tsconfig.json +2 -9
  32. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1,53 +1,54 @@
1
1
  #!/usr/bin/env node
2
- import z from "mri";
3
- import n from "picocolors";
4
- import c from "node:path";
5
- import { exit as L, argv as B } from "node:process";
6
- import { fileURLToPath as F } from "node:url";
7
- import A from "prompts";
8
- import r from "node:fs";
9
- import E from "ejs";
10
- const O = "2.4.0", V = {
11
- version: O
2
+ import K from "mri";
3
+ import r from "picocolors";
4
+ import m from "node:path";
5
+ import { exit as J, argv as Y } from "node:process";
6
+ import { fileURLToPath as Z } from "node:url";
7
+ import P from "prompts";
8
+ import i from "node:fs";
9
+ import F from "ejs";
10
+ import I from "prettier";
11
+ const q = "2.5.0", W = {
12
+ version: q
12
13
  };
13
- function h(e) {
14
+ function v(e) {
14
15
  return e.trim().replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase().replace(/[^a-z0-9-]/g, "");
15
16
  }
16
- function x(e) {
17
- return e.replace(/[-_\s]+(.)?/g, (a, t) => t ? t.toUpperCase() : "").replace(/^(.)/, (a, t) => t.toUpperCase());
17
+ function M(e) {
18
+ return e.replace(/[-_\s]+(.)?/g, (t, n) => n ? n.toUpperCase() : "").replace(/^(.)/, (t, n) => n.toUpperCase());
18
19
  }
19
- function Z(e) {
20
- const a = x(e);
21
- return a.charAt(0).toLowerCase() + a.slice(1);
20
+ function G(e) {
21
+ const t = M(e);
22
+ return t.charAt(0).toLowerCase() + t.slice(1);
22
23
  }
23
- function D(e) {
24
+ function O(e) {
24
25
  return e.replace(/[-\s]+/g, "_").replace(/([a-z])([A-Z])/g, "$1_$2").toUpperCase();
25
26
  }
26
- function S(e) {
27
- return e.replace(/[-_]+/g, " ").replace(/\b\w/g, (a) => a.toUpperCase());
27
+ function x(e) {
28
+ return e.replace(/[-_]+/g, " ").replace(/\b\w/g, (t) => t.toUpperCase());
28
29
  }
29
- function k(e) {
30
+ function N(e) {
30
31
  return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(e);
31
32
  }
32
- function C(e) {
33
+ function A(e) {
33
34
  return e.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
34
35
  }
35
- function _(e) {
36
+ function E(e) {
36
37
  return e.trim().toLowerCase().replace(/\/+/g, "/").replace(/[^a-z0-9/-]+/g, "/").replace(/\/?$/, "/");
37
38
  }
38
- function R(e) {
39
- const a = e.moduleName || "", t = a ? h(a) : "", s = {
39
+ function U(e) {
40
+ const t = e.moduleName || "", n = t ? v(t) : "", o = {
40
41
  hasModule: !!e.moduleName,
41
- ModuleName: t,
42
- ModuleNamePascalCase: a ? x(a) : "",
43
- ModuleNameCamelCase: a ? Z(a) : "",
44
- ModuleNameUppercase: t.toUpperCase(),
45
- ModuleNameScreamingSnake: a ? D(a) : "",
46
- ModuleNameSentenceCase: a ? S(a) : ""
42
+ ModuleName: n,
43
+ ModuleNamePascalCase: t ? M(t) : "",
44
+ ModuleNameCamelCase: t ? G(t) : "",
45
+ ModuleNameUppercase: n.toUpperCase(),
46
+ ModuleNameScreamingSnake: t ? O(t) : "",
47
+ ModuleNameSentenceCase: t ? x(t) : ""
47
48
  };
48
- return e.projectName && (s.AppName = h(e.projectName), s.AppNameSentenceCase = S(e.projectName)), e.packageName !== void 0 && (s.PackageName = e.packageName || "", s.BasePath = e.basePath || "", s.tenantRoutes = e.tenantRoutes || !1, s.aiAgent = e.aiAgent || !1, s.dashboard = e.dashboard || !1, s.mocks = e.mocks || !1), s;
49
+ return e.projectName && (o.AppName = v(e.projectName), o.AppNameSentenceCase = x(e.projectName)), e.packageName !== void 0 && (o.PackageName = e.packageName || "", o.BasePath = e.basePath || "", o.tenantRoutes = e.tenantRoutes || !1, o.aiAgent = e.aiAgent || !1, o.dashboard = e.dashboard || !1, o.mocks = e.mocks || !1), o;
49
50
  }
50
- const J = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".pdf", ".zip"]), K = {
51
+ const H = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".pdf", ".zip"]), X = {
51
52
  _gitignore: ".gitignore",
52
53
  "_yarnrc.yml": ".yarnrc.yml",
53
54
  _browserslistrc: ".browserslistrc",
@@ -62,155 +63,177 @@ const J = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ic
62
63
  _yarn: ".yarn",
63
64
  "_package.json": "package.json"
64
65
  };
65
- function Y(e, a, t) {
66
- a.endsWith(".ejs") && (a = a.slice(0, -4));
67
- const s = c.dirname(a);
68
- r.existsSync(s) || r.mkdirSync(s, { recursive: !0 });
69
- const o = c.extname(e.replace(/\.ejs$/, "")).toLowerCase();
70
- if (J.has(o))
71
- r.copyFileSync(e, a);
66
+ function Q(e, t, n) {
67
+ t.endsWith(".ejs") && (t = t.slice(0, -4));
68
+ const o = m.dirname(t);
69
+ i.existsSync(o) || i.mkdirSync(o, { recursive: !0 });
70
+ const a = m.extname(e.replace(/\.ejs$/, "")).toLowerCase();
71
+ if (H.has(a))
72
+ i.copyFileSync(e, t);
72
73
  else {
73
- const d = r.readFileSync(e, "utf-8"), p = E.render(d, t, { filename: e });
74
- r.writeFileSync(a, p);
74
+ const l = i.readFileSync(e, "utf-8"), s = F.render(l, n, { filename: e });
75
+ i.writeFileSync(t, s);
75
76
  }
76
77
  }
77
- function j(e, a, t) {
78
- if (!r.existsSync(e)) return;
79
- const s = r.readdirSync(e);
80
- for (const o of s) {
81
- const d = c.join(e, o), p = o.endsWith(".ejs") ? o.slice(0, -4) : o;
82
- let m = K[p] ?? p;
78
+ function j(e, t, n) {
79
+ if (!i.existsSync(e)) return;
80
+ const o = i.readdirSync(e);
81
+ for (const a of o) {
82
+ const l = m.join(e, a), s = a.endsWith(".ejs") ? a.slice(0, -4) : a;
83
+ let c = X[s] ?? s;
83
84
  try {
84
- m = E.render(m, t);
85
+ c = F.render(c, n);
85
86
  } catch {
86
87
  }
87
- const l = c.join(a, m);
88
- r.statSync(d).isDirectory() ? (r.existsSync(l) || r.mkdirSync(l, { recursive: !0 }), j(d, l, t)) : Y(d, l, t);
88
+ const d = m.join(t, c);
89
+ i.statSync(l).isDirectory() ? (i.existsSync(d) || i.mkdirSync(d, { recursive: !0 }), j(l, d, n)) : Q(l, d, n);
89
90
  }
90
91
  }
91
- function q(e) {
92
- if (r.existsSync(e))
93
- for (const a of r.readdirSync(e)) {
94
- if (a === ".git") continue;
95
- const t = c.join(e, a);
96
- r.statSync(t).isDirectory() ? r.rmSync(t, { recursive: !0, force: !0 }) : r.unlinkSync(t);
92
+ function ee(e) {
93
+ if (i.existsSync(e))
94
+ for (const t of i.readdirSync(e)) {
95
+ if (t === ".git") continue;
96
+ const n = m.join(e, t);
97
+ i.statSync(n).isDirectory() ? i.rmSync(n, { recursive: !0, force: !0 }) : i.unlinkSync(n);
97
98
  }
98
99
  }
99
- function I(e) {
100
- if (!r.existsSync(e)) return !0;
101
- const a = r.readdirSync(e);
102
- return a.length === 0 || a.length === 1 && a[0] === ".git";
100
+ function T(e) {
101
+ if (!i.existsSync(e)) return !0;
102
+ const t = i.readdirSync(e);
103
+ return t.length === 0 || t.length === 1 && t[0] === ".git";
104
+ }
105
+ const te = /* @__PURE__ */ new Set(["node_modules", ".git", ".yarn", "dist"]);
106
+ function L(e, t = []) {
107
+ if (!i.existsSync(e)) return t;
108
+ if (!i.statSync(e).isDirectory())
109
+ return t.push(e), t;
110
+ for (const n of i.readdirSync(e))
111
+ te.has(n) || L(m.join(e, n), t);
112
+ return t;
113
+ }
114
+ async function z(e) {
115
+ const t = e.flatMap((o) => L(o));
116
+ let n = 0;
117
+ for (const o of t)
118
+ try {
119
+ const a = await I.getFileInfo(o, { resolveConfig: !0 });
120
+ if (!a.inferredParser || a.ignored) continue;
121
+ const l = i.readFileSync(o, "utf-8"), s = await I.resolveConfig(o, { editorconfig: !0 }), c = await I.format(l, { ...s, filepath: o });
122
+ c !== l && (i.writeFileSync(o, c), n++);
123
+ } catch {
124
+ }
125
+ return n;
103
126
  }
104
- const W = {
127
+ const ne = {
105
128
  standalone: "Standalone App",
106
129
  "dynamic-module": "Dynamic Module"
107
130
  };
108
- function H(e) {
109
- const a = W[e.projectType] ?? e.projectType, t = !!e.moduleName;
131
+ function oe(e) {
132
+ const t = ne[e.projectType] ?? e.projectType, n = !!e.moduleName;
110
133
  console.log(`
111
- ${n.green("╭─────────────────────────────────────────╮")}
112
- ${n.green("│")} ${n.green("│")}
113
- ${n.green("│")} ${n.bold("VC Shell App created successfully!")} ${n.green("│")}
114
- ${n.green("│")} ${n.green("│")}
115
- ${n.green("│")} Project: ${n.cyan(e.projectName.padEnd(28))}${n.green("│")}
116
- ${n.green("│")} Type: ${n.cyan(a.padEnd(28))}${n.green("│")}
117
- ${t && e.moduleName ? ` ${n.green("│")} Module: ${n.cyan(e.moduleName.padEnd(28))}${n.green("│")}
118
- ` : ""} ${n.green("│")} ${n.green("│")}
119
- ${n.green("╰─────────────────────────────────────────╯")}
134
+ ${r.green("╭─────────────────────────────────────────╮")}
135
+ ${r.green("│")} ${r.green("│")}
136
+ ${r.green("│")} ${r.bold("VC Shell App created successfully!")} ${r.green("│")}
137
+ ${r.green("│")} ${r.green("│")}
138
+ ${r.green("│")} Project: ${r.cyan(e.projectName.padEnd(28))}${r.green("│")}
139
+ ${r.green("│")} Type: ${r.cyan(t.padEnd(28))}${r.green("│")}
140
+ ${n && e.moduleName ? ` ${r.green("│")} Module: ${r.cyan(e.moduleName.padEnd(28))}${r.green("│")}
141
+ ` : ""} ${r.green("│")} ${r.green("│")}
142
+ ${r.green("╰─────────────────────────────────────────╯")}
120
143
 
121
- ${n.bold("Next steps:")}
144
+ ${r.bold("Next steps:")}
122
145
 
123
146
  1. cd ${e.projectName}
124
147
  2. yarn install
125
148
  3. yarn serve
126
- ${t && e.moduleName ? `
149
+ ${n && e.moduleName ? `
127
150
  Module is ready at:
128
- src/modules/${X(e.moduleName)}/
151
+ src/modules/${ae(e.moduleName)}/
129
152
  ` : ""}
130
- ${n.dim("Docs: https://docs.virtocommerce.org/platform/developer-guide/latest/custom-apps-development/vc-shell/vc-shell-overview/")}
153
+ ${r.dim("Docs: https://docs.virtocommerce.org/platform/developer-guide/latest/custom-apps-development/vc-shell/vc-shell-overview/")}
131
154
  `);
132
155
  }
133
- function X(e) {
156
+ function ae(e) {
134
157
  return e.trim().replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase().replace(/[^a-z0-9-]/g, "");
135
158
  }
136
- const P = [
159
+ const D = [
137
160
  { title: "Standalone App — full application with bundled modules", value: "standalone" },
138
161
  { title: "Dynamic Module — remote module loaded by host via Module Federation", value: "dynamic-module" }
139
162
  ];
140
- function G(e) {
141
- return typeof e == "string" && P.some((a) => a.value === e);
163
+ function re(e) {
164
+ return typeof e == "string" && D.some((t) => t.value === e);
142
165
  }
143
- async function Q(e, a) {
144
- const t = process.cwd();
145
- let o = e._?.[0] || e.name || e["app-name"];
146
- const d = o || "vc-app", p = () => o === "." ? c.basename(c.resolve()) : o, m = !!(o && e.type);
147
- let l;
148
- if (m) {
149
- o = o || d;
150
- const f = c.resolve(t, o);
151
- if (!G(e.type)) {
152
- const b = P.map(($) => $.value).join(", ");
153
- console.error(n.red(`Unknown project type: "${e.type}". Valid types: ${b}`)), process.exit(1);
166
+ async function se(e, t) {
167
+ const n = process.cwd();
168
+ let a = e._?.[0] || e.name || e["app-name"];
169
+ const l = a || "vc-app", s = () => a === "." ? m.basename(m.resolve()) : a, c = !!(a && e.type);
170
+ let d;
171
+ if (c) {
172
+ a = a || l;
173
+ const y = m.resolve(n, a);
174
+ if (!re(e.type)) {
175
+ const S = D.map(($) => $.value).join(", ");
176
+ console.error(r.red(`Unknown project type: "${e.type}". Valid types: ${S}`)), process.exit(1);
154
177
  }
155
- r.existsSync(f) && !I(f) && !e.overwrite && (console.error(n.red(`Target directory "${o}" is not empty. Use --overwrite to overwrite.`)), process.exit(1));
156
- const u = p(), y = e.type, g = e["module-name"], N = y === "dynamic-module" ? g || S(u) : g || void 0;
157
- l = {
158
- projectName: h(u),
159
- packageName: e["package-name"] || (k(u) ? u : C(u)),
160
- projectType: y,
161
- moduleName: N,
162
- basePath: e["base-path"] || _(`/apps/${h(u)}/`),
178
+ i.existsSync(y) && !T(y) && !e.overwrite && (console.error(r.red(`Target directory "${a}" is not empty. Use --overwrite to overwrite.`)), process.exit(1));
179
+ const f = s(), h = e.type, g = e["module-name"], b = h === "dynamic-module" ? g || x(f) : g || void 0;
180
+ d = {
181
+ projectName: v(f),
182
+ packageName: e["package-name"] || (N(f) ? f : A(f)),
183
+ projectType: h,
184
+ moduleName: b,
185
+ basePath: e["base-path"] || E(`/apps/${v(f)}/`),
163
186
  tenantRoutes: e["tenant-routes"] || !1,
164
187
  aiAgent: e["ai-agent"] || !1,
165
188
  dashboard: e.dashboard || !1,
166
189
  mocks: e.mocks || !1
167
190
  };
168
191
  } else {
169
- const f = () => {
170
- throw new Error(n.red("✖") + " Creation cancelled");
192
+ const y = () => {
193
+ throw new Error(r.red("✖") + " Creation cancelled");
171
194
  };
172
195
  try {
173
- const u = await A(
196
+ const f = await P(
174
197
  [
175
198
  {
176
199
  name: "projectName",
177
- type: o ? null : "text",
178
- message: n.reset("Project name:"),
179
- initial: d,
200
+ type: a ? null : "text",
201
+ message: r.reset("Project name:"),
202
+ initial: l,
180
203
  onState: (w) => {
181
- o = h(String(w.value).trim()) || d;
204
+ a = v(String(w.value).trim()) || l;
182
205
  },
183
- format: (w) => h(String(w).trim())
206
+ format: (w) => v(String(w).trim())
184
207
  },
185
208
  {
186
- type: () => !r.existsSync(c.resolve(t, o)) || I(c.resolve(t, o)) ? null : "confirm",
209
+ type: () => !i.existsSync(m.resolve(n, a)) || T(m.resolve(n, a)) ? null : "confirm",
187
210
  name: "overwrite",
188
- message: () => (o === "." ? "Current directory" : `Target directory "${o}"`) + " is not empty. Remove existing files and continue?"
211
+ message: () => (a === "." ? "Current directory" : `Target directory "${a}"`) + " is not empty. Remove existing files and continue?"
189
212
  },
190
213
  {
191
- type: (w, { overwrite: M }) => {
192
- if (M === !1)
193
- throw new Error(n.red("✖") + " Operation cancelled");
214
+ type: (w, { overwrite: _ }) => {
215
+ if (_ === !1)
216
+ throw new Error(r.red("✖") + " Operation cancelled");
194
217
  return null;
195
218
  },
196
219
  name: "overwriteChecker"
197
220
  },
198
221
  {
199
222
  name: "packageName",
200
- type: () => k(p()) ? null : "text",
201
- message: n.reset("Package name:"),
202
- initial: () => C(p()),
203
- validate: (w) => k(w) || "Invalid package.json name"
223
+ type: () => N(s()) ? null : "text",
224
+ message: r.reset("Package name:"),
225
+ initial: () => A(s()),
226
+ validate: (w) => N(w) || "Invalid package.json name"
204
227
  },
205
228
  {
206
229
  type: "select",
207
230
  name: "projectType",
208
- message: n.reset("Project type:"),
209
- choices: P
231
+ message: r.reset("Project type:"),
232
+ choices: D
210
233
  }
211
234
  ],
212
- { onCancel: f }
213
- ), y = o ? h(o) : u.projectName, g = u.projectType || "standalone", N = S(y), b = "/apps/" + h(y) + "/", $ = await A(
235
+ { onCancel: y }
236
+ ), h = a ? v(a) : f.projectName, g = f.projectType || "standalone", b = x(h), S = "/apps/" + v(h) + "/", $ = await P(
214
237
  [
215
238
  {
216
239
  name: "includeModule",
@@ -220,17 +243,17 @@ async function Q(e, a) {
220
243
  },
221
244
  {
222
245
  name: "moduleName",
223
- type: (w, M) => g === "standalone" && !M.includeModule ? null : "text",
224
- message: n.reset("Module name:"),
225
- initial: N,
246
+ type: (w, _) => g === "standalone" && !_.includeModule ? null : "text",
247
+ message: r.reset("Module name:"),
248
+ initial: b,
226
249
  format: (w) => String(w).trim()
227
250
  },
228
251
  {
229
252
  name: "basePath",
230
253
  type: g === "dynamic-module" ? null : "text",
231
- message: n.reset("Base path:"),
232
- initial: b,
233
- format: (w) => _(String(w).trim())
254
+ message: r.reset("Base path:"),
255
+ initial: S,
256
+ format: (w) => E(String(w).trim())
234
257
  },
235
258
  {
236
259
  type: g === "dynamic-module" ? null : "confirm",
@@ -257,139 +280,213 @@ async function Q(e, a) {
257
280
  initial: !1
258
281
  }
259
282
  ],
260
- { onCancel: f }
283
+ { onCancel: y }
261
284
  );
262
- l = {
263
- projectName: y,
264
- packageName: u.packageName || (k(y) ? y : C(y)),
285
+ d = {
286
+ projectName: h,
287
+ packageName: f.packageName || (N(h) ? h : A(h)),
265
288
  projectType: g,
266
- moduleName: $.moduleName || ($.includeModule !== !1 ? N : void 0),
267
- basePath: $.basePath || _(b),
289
+ moduleName: $.moduleName || ($.includeModule !== !1 ? b : void 0),
290
+ basePath: $.basePath || E(S),
268
291
  tenantRoutes: $.tenantRoutes || !1,
269
292
  aiAgent: $.aiAgent || !1,
270
293
  dashboard: $.dashboard ?? !0,
271
294
  mocks: $.mocks || !1
272
295
  };
273
- } catch (u) {
274
- console.log(u.message), process.exit(1);
296
+ } catch (f) {
297
+ console.log(f.message), process.exit(1);
275
298
  }
276
299
  }
277
- const i = c.resolve(t, o);
278
- r.existsSync(i) && !I(i) ? q(i) : r.existsSync(i) || r.mkdirSync(i, { recursive: !0 }), console.log(`
279
- Scaffolding ${n.cyan(l.projectType)} in ${n.green(i)}...
300
+ const u = m.resolve(n, a);
301
+ i.existsSync(u) && !T(u) ? ee(u) : i.existsSync(u) || i.mkdirSync(u, { recursive: !0 }), console.log(`
302
+ Scaffolding ${r.cyan(d.projectType)} in ${r.green(u)}...
280
303
  `);
281
- const v = R(l);
282
- if (j(c.join(a, l.projectType), i, v), l.moduleName) {
283
- const f = h(l.moduleName), u = l.projectType === "dynamic-module" ? c.join(i, "src/modules") : c.join(i, "src/modules", f);
284
- j(c.join(a, "module"), u, v);
304
+ const p = U(d);
305
+ if (j(m.join(t, d.projectType), u, p), d.moduleName) {
306
+ const y = v(d.moduleName), f = d.projectType === "dynamic-module" ? m.join(u, "src/modules") : m.join(u, "src/modules", y);
307
+ j(m.join(t, "module"), f, p);
285
308
  }
286
- l.mocks && j(c.join(a, "sample-module"), c.join(i, "src/modules/sample"), v), H(l);
309
+ d.mocks && j(m.join(t, "sample-module"), m.join(u, "src/modules/sample"), p), await z([u]), oe(d);
287
310
  }
288
- function U(e, a) {
289
- const t = /^import\s.+$/gm;
290
- let s = null, o;
291
- for (; (o = t.exec(e)) !== null; )
292
- s = o;
293
- if (s) {
294
- const d = s.index + s[0].length;
295
- return e.slice(0, d) + `
296
- ` + a + e.slice(d);
311
+ function k(e, { strings: t = !0 } = {}) {
312
+ const n = e.split("");
313
+ let o = 0;
314
+ const a = (l, s) => {
315
+ for (let c = l; c < s && c < e.length; c++)
316
+ n[c] !== `
317
+ ` && (n[c] = " ");
318
+ };
319
+ for (; o < e.length; ) {
320
+ const l = e[o];
321
+ if (l === "/" && e[o + 1] === "/") {
322
+ const s = e.indexOf(`
323
+ `, o), c = s === -1 ? e.length : s;
324
+ a(o, c), o = c;
325
+ continue;
326
+ }
327
+ if (l === "/" && e[o + 1] === "*") {
328
+ const s = e.indexOf("*/", o + 2), c = s === -1 ? e.length : s + 2;
329
+ a(o, c), o = c;
330
+ continue;
331
+ }
332
+ if (l === '"' || l === "'" || l === "`") {
333
+ let s = o + 1;
334
+ for (; s < e.length; ) {
335
+ if (e[s] === "\\") {
336
+ s += 2;
337
+ continue;
338
+ }
339
+ if (e[s] === l) break;
340
+ s++;
341
+ }
342
+ t && a(o + 1, s), o = s + 1;
343
+ continue;
344
+ }
345
+ o++;
297
346
  }
298
- return a + `
299
- ` + e;
347
+ return n.join("");
300
348
  }
301
- function ee(e, a) {
302
- let t = r.readFileSync(e, "utf-8");
303
- const s = x(a), o = h(a);
304
- t = U(t, `import ${s} from "./modules/${o}";`);
305
- const d = /\.use\([A-Z]\w+,\s*\{\s*router\s*\}\)/g;
306
- let p = null, m;
307
- for (; (m = d.exec(t)) !== null; )
308
- p = m;
309
- if (p) {
310
- const l = p.index + p[0].length, i = `
311
- .use(${s}, { router })`;
312
- t = t.slice(0, l) + i + t.slice(l);
349
+ function ie(e, t) {
350
+ let n = 0;
351
+ for (let o = t; o < e.length; o++) {
352
+ const a = e[o];
353
+ if (a === "(" || a === "[" || a === "{")
354
+ n++;
355
+ else if ((a === ")" || a === "]" || a === "}") && (n--, n === 0))
356
+ return e[o + 1] === ";" ? o + 2 : o + 1;
313
357
  }
314
- r.writeFileSync(e, t);
358
+ return -1;
315
359
  }
316
- function te(e, a) {
317
- let t = r.readFileSync(e, "utf-8");
318
- const s = h(a), o = D(a);
319
- if (!t.includes("addMenuItem")) {
320
- const v = /import\s*\{([^}]+)\}\s*from\s*["']@vc-shell\/framework["']/.exec(t);
321
- if (v) {
322
- const f = v[1].trim() + ", addMenuItem";
323
- t = t.replace(v[0], `import { ${f} } from "@vc-shell/framework"`);
324
- } else
325
- t = U(t, 'import { addMenuItem } from "@vc-shell/framework";');
360
+ function ce(e, t) {
361
+ const n = new RegExp(`\\b${t}\\s*\\(`, "g"), o = [];
362
+ let a;
363
+ for (; (a = n.exec(e)) !== null; ) {
364
+ const l = o[o.length - 1];
365
+ if (l && a.index < l.end) continue;
366
+ const s = ie(e, a.index + a[0].length - 1);
367
+ if (s === -1) break;
368
+ o.push({ start: a.index, end: s });
326
369
  }
327
- const d = /addMenuItem\(\{[\s\S]*?\}\);/g;
328
- let p = null, m;
329
- for (; (m = d.exec(t)) !== null; )
330
- p = m;
331
- const l = `
332
- addMenuItem({
333
- title: "${o}.MENU.TITLE",
334
- icon: "lucide-box",
335
- priority: 10,
336
- url: "/${s}",
337
- });`;
338
- if (p) {
339
- const i = p.index + p[0].length;
340
- t = t.slice(0, i) + `
341
- ` + l + t.slice(i);
342
- } else {
343
- const i = t.lastIndexOf("}");
344
- i !== -1 && (t = t.slice(0, i) + l + `
345
- ` + t.slice(i));
370
+ return o;
371
+ }
372
+ function B(e) {
373
+ const t = /^[ \t]*import(?=[\s{"'])/gm;
374
+ let n = -1, o;
375
+ for (; (o = t.exec(e)) !== null; ) {
376
+ const a = e.indexOf(";", o.index);
377
+ if (a === -1) break;
378
+ n = a + 1, t.lastIndex = n;
346
379
  }
347
- r.writeFileSync(e, t);
380
+ return n;
381
+ }
382
+ function V(e, t) {
383
+ const n = e.lastIndexOf(`
384
+ `, t - 1) + 1;
385
+ return /^[ \t]*/.exec(e.slice(n, t))?.[0] ?? "";
348
386
  }
349
- async function ae(e, a) {
350
- const t = process.cwd(), s = e._?.[1], o = c.join(t, "package.json");
351
- r.existsSync(o) || (console.error(n.red("Error: No package.json found. Run this command from a vc-shell project root.")), process.exit(1));
352
- const d = JSON.parse(r.readFileSync(o, "utf-8"));
353
- ({ ...d.dependencies, ...d.devDependencies })["@vc-shell/framework"] || (console.error(n.red("Error: Not a vc-shell project (@vc-shell/framework not found in dependencies).")), process.exit(1));
354
- let m = s;
355
- m || (m = (await A({
387
+ function C(e, t) {
388
+ return [...t].sort((n, o) => o.at - n.at).reduce((n, { at: o, text: a }) => n.slice(0, o) + a + n.slice(o), e);
389
+ }
390
+ function le(e, t) {
391
+ const n = i.readFileSync(e, "utf-8"), o = k(n), a = M(t), l = v(t), s = /^[ \t]*app\.use\(\s*router\s*\)\s*;/m.exec(o);
392
+ if (!s)
393
+ throw new Error("Could not find `app.use(router)` in main.ts");
394
+ const c = B(o);
395
+ if (c === -1)
396
+ throw new Error("Could not find an import statement in main.ts");
397
+ const d = V(n, s.index + s[0].length);
398
+ i.writeFileSync(
399
+ e,
400
+ C(n, [
401
+ { at: c, text: `
402
+ import ${a} from "./modules/${l}";` },
403
+ { at: s.index, text: `${d}app.use(${a});
404
+ ` }
405
+ ])
406
+ );
407
+ }
408
+ function me(e) {
409
+ const t = k(e);
410
+ if (/\baddMenuItem\b/.test(t)) return e;
411
+ const n = /import\s*\{([^}]*)\}\s*from\s*["']@vc-shell\/framework["']/.exec(
412
+ k(e, { strings: !1 })
413
+ );
414
+ if (n) {
415
+ const l = n[1].trim().replace(/,$/, ""), s = n.index + n[0].length;
416
+ return e.slice(0, n.index) + `import { ${l}, addMenuItem } from "@vc-shell/framework"` + e.slice(s);
417
+ }
418
+ const o = 'import { addMenuItem } from "@vc-shell/framework";', a = B(t);
419
+ return a === -1 ? `${o}
420
+ ${e}` : C(e, [{ at: a, text: `
421
+ ${o}` }]);
422
+ }
423
+ function de(e, t) {
424
+ const n = v(t), o = O(t), a = me(i.readFileSync(e, "utf-8")), l = k(a), s = (p) => [
425
+ `${p}addMenuItem({`,
426
+ `${p} title: "${o}.MENU.TITLE",`,
427
+ `${p} icon: "lucide-box",`,
428
+ `${p} priority: 10,`,
429
+ `${p} url: "/${n}",`,
430
+ `${p}});`
431
+ ].join(`
432
+ `), c = ce(l, "addMenuItem"), d = c[c.length - 1];
433
+ if (d) {
434
+ const p = V(a, d.start);
435
+ i.writeFileSync(e, C(a, [{ at: d.end, text: `
436
+
437
+ ${s(p)}` }]));
438
+ return;
439
+ }
440
+ const u = l.lastIndexOf("}");
441
+ if (u === -1)
442
+ throw new Error("Could not find the bootstrap function body in bootstrap.ts");
443
+ i.writeFileSync(e, C(a, [{ at: u, text: `${s(" ")}
444
+ ` }]));
445
+ }
446
+ async function ue(e, t) {
447
+ const n = process.cwd(), o = e._?.[1], a = m.join(n, "package.json");
448
+ i.existsSync(a) || (console.error(r.red("Error: No package.json found. Run this command from a vc-shell project root.")), process.exit(1));
449
+ const l = JSON.parse(i.readFileSync(a, "utf-8"));
450
+ ({ ...l.dependencies, ...l.devDependencies })["@vc-shell/framework"] || (console.error(r.red("Error: Not a vc-shell project (@vc-shell/framework not found in dependencies).")), process.exit(1));
451
+ let c = o;
452
+ c || (c = (await P({
356
453
  type: "text",
357
454
  name: "moduleName",
358
455
  message: "Module name:",
359
- validate: (b) => b.trim().length > 0 || "Module name is required"
360
- })).moduleName), m || (console.error(n.red("Module name is required.")), process.exit(1));
361
- const l = h(m), i = x(m), v = c.join(t, "src/modules"), f = c.join(v, l);
362
- r.existsSync(v) || r.mkdirSync(v, { recursive: !0 }), r.existsSync(f) && (console.error(n.red(`Error: Module "${l}" already exists at ${c.relative(t, f)}`)), process.exit(1));
363
- const u = R({ moduleName: m, projectName: c.basename(t) });
364
- j(c.join(a, "module"), f, u), console.log(n.green(` ✔ Created ${c.relative(t, f)}/`));
365
- const y = c.join(t, "src/main.ts");
366
- if (r.existsSync(y))
456
+ validate: (S) => S.trim().length > 0 || "Module name is required"
457
+ })).moduleName), c || (console.error(r.red("Module name is required.")), process.exit(1));
458
+ const d = v(c), u = M(c), p = m.join(n, "src/modules"), y = m.join(p, d);
459
+ i.existsSync(p) || i.mkdirSync(p, { recursive: !0 }), i.existsSync(y) && (console.error(r.red(`Error: Module "${d}" already exists at ${m.relative(n, y)}`)), process.exit(1));
460
+ const f = U({ moduleName: c, projectName: m.basename(n) });
461
+ j(m.join(t, "module"), y, f), console.log(r.green(` ✔ Created ${m.relative(n, y)}/`));
462
+ const h = m.join(n, "src/main.ts");
463
+ if (i.existsSync(h))
367
464
  try {
368
- ee(y, m), console.log(n.green(` ✔ Updated src/main.ts — added import & app.use(${i})`));
465
+ le(h, c), console.log(r.green(` ✔ Updated src/main.ts — added import & app.use(${u})`));
369
466
  } catch {
370
- console.warn(n.yellow(" ⚠ Could not auto-update src/main.ts. Add manually:")), console.warn(n.yellow(` import ${i} from "./modules/${l}";`)), console.warn(n.yellow(` app.use(${i}, { router });`));
467
+ console.warn(r.yellow(" ⚠ Could not auto-update src/main.ts. Add manually:")), console.warn(r.yellow(` import ${u} from "./modules/${d}";`)), console.warn(r.yellow(` app.use(${u}, { router });`));
371
468
  }
372
- const g = c.join(t, "src/bootstrap.ts");
373
- if (r.existsSync(g))
469
+ const g = m.join(n, "src/bootstrap.ts");
470
+ if (i.existsSync(g))
374
471
  try {
375
- te(g, m), console.log(n.green(` ✔ Updated src/bootstrap.ts — added menu item "${S(m)}"`));
472
+ de(g, c), console.log(r.green(` ✔ Updated src/bootstrap.ts — added menu item "${x(c)}"`));
376
473
  } catch {
377
- console.warn(n.yellow(" ⚠ Could not auto-update src/bootstrap.ts. Add addMenuItem() manually."));
474
+ console.warn(r.yellow(" ⚠ Could not auto-update src/bootstrap.ts. Add addMenuItem() manually."));
378
475
  }
379
- console.log(`
380
- Module "${l}" is ready! Run ${n.bold(n.green("yarn serve"))} to see it.
476
+ await z([y, h, g]), console.log(`
477
+ Module "${d}" is ready! Run ${r.bold(r.green("yarn serve"))} to see it.
381
478
  `);
382
479
  }
383
- const T = c.resolve(F(import.meta.url), "..", "templates");
384
- function ne() {
480
+ const R = m.resolve(Z(import.meta.url), "..", "templates");
481
+ function pe() {
385
482
  console.log(`
386
- ${n.bold(n.green("create-vc-app"))} — Create VC Shell applications and modules
483
+ ${r.bold(r.green("create-vc-app"))} — Create VC Shell applications and modules
387
484
 
388
- ${n.bold("Usage:")}
485
+ ${r.bold("Usage:")}
389
486
  create-vc-app [project-name] [options] Create a new project
390
487
  create-vc-app add-module <module-name> Add a module to existing project
391
488
 
392
- ${n.bold("Options (create):")}
489
+ ${r.bold("Options (create):")}
393
490
  --type <type> Project type: standalone | dynamic-module
394
491
  --name, --app-name <name> Application name
395
492
  --package-name <name> npm package name
@@ -403,31 +500,31 @@ ${n.bold("Options (create):")}
403
500
  --help, -h Show this help
404
501
  --version, -v Show version
405
502
 
406
- ${n.bold("Examples:")}
503
+ ${r.bold("Examples:")}
407
504
  create-vc-app my-app
408
505
  create-vc-app my-app --type standalone --dashboard --mocks
409
506
  create-vc-app my-module --type dynamic-module --module-name "Reviews"
410
507
  create-vc-app add-module orders
411
508
 
412
- ${n.bold("Docs:")} https://docs.virtocommerce.org/platform/developer-guide/latest/custom-apps-development/vc-shell/vc-shell-overview/
509
+ ${r.bold("Docs:")} https://docs.virtocommerce.org/platform/developer-guide/latest/custom-apps-development/vc-shell/vc-shell-overview/
413
510
  `);
414
511
  }
415
- async function oe() {
416
- const e = z(B.slice(2), {
512
+ async function fe() {
513
+ const e = K(Y.slice(2), {
417
514
  alias: { h: "help", v: "version" },
418
515
  boolean: ["help", "version", "mocks", "overwrite", "tenant-routes", "ai-agent", "dashboard"],
419
516
  string: ["type", "name", "app-name", "package-name", "module-name", "base-path"]
420
517
  });
421
518
  if (e.help) {
422
- ne();
519
+ pe();
423
520
  return;
424
521
  }
425
522
  if (e.version) {
426
- console.log(`create-vc-app v${V.version}`);
523
+ console.log(`create-vc-app v${W.version}`);
427
524
  return;
428
525
  }
429
- e._[0] === "add-module" ? await ae(e, T) : await Q(e, T);
526
+ e._[0] === "add-module" ? await ue(e, R) : await se(e, R);
430
527
  }
431
- oe().catch((e) => {
432
- console.error(n.red(e.message || String(e))), L(1);
528
+ fe().catch((e) => {
529
+ console.error(r.red(e.message || String(e))), J(1);
433
530
  });