@vc-shell/create-vc-app 2.4.0-pr302.99e48e1 → 2.4.0-pr302.b052b38

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.
@@ -1,9 +1,12 @@
1
1
  /**
2
- * Add a module import and app.use() call to main.ts
2
+ * Add a module import and its `app.use()` registration to main.ts.
3
+ *
4
+ * Throws when either anchor is missing, so the caller can tell the user what to
5
+ * add by hand rather than reporting a change it did not make.
3
6
  */
4
7
  export declare function addModuleToMain(mainTsPath: string, moduleName: string): void;
5
8
  /**
6
- * Add a menu item registration to bootstrap.ts
9
+ * Add a menu item registration to bootstrap.ts, after the last existing one.
7
10
  */
8
11
  export declare function addMenuItemToBootstrap(bootstrapPath: string, moduleName: string): void;
9
12
  //# sourceMappingURL=codegen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/engine/codegen.ts"],"names":[],"mappings":"AAuBA;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAuB5E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAsCtF"}
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/engine/codegen.ts"],"names":[],"mappings":"AA6IA;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CA2B5E;AAiCD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAsCtF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=codegen.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.test.d.ts","sourceRoot":"","sources":["../../src/engine/codegen.test.ts"],"names":[],"mappings":""}
package/dist/index.js CHANGED
@@ -1,54 +1,54 @@
1
1
  #!/usr/bin/env node
2
- import B from "mri";
3
- import a from "picocolors";
4
- import c from "node:path";
5
- import { exit as O, argv as V } from "node:process";
6
- import { fileURLToPath as K } from "node:url";
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
7
  import P from "prompts";
8
- import r from "node:fs";
9
- import D from "ejs";
10
- import C from "prettier";
11
- const Z = "2.4.0-pr302.99e48e1", J = {
12
- version: Z
8
+ import i from "node:fs";
9
+ import F from "ejs";
10
+ import I from "prettier";
11
+ const q = "2.4.0-pr302.b052b38", W = {
12
+ version: q
13
13
  };
14
- function h(e) {
14
+ function v(e) {
15
15
  return e.trim().replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase().replace(/[^a-z0-9-]/g, "");
16
16
  }
17
- function x(e) {
18
- return e.replace(/[-_\s]+(.)?/g, (n, t) => t ? t.toUpperCase() : "").replace(/^(.)/, (n, t) => t.toUpperCase());
17
+ function M(e) {
18
+ return e.replace(/[-_\s]+(.)?/g, (t, n) => n ? n.toUpperCase() : "").replace(/^(.)/, (t, n) => n.toUpperCase());
19
19
  }
20
- function Y(e) {
21
- const n = x(e);
22
- return n.charAt(0).toLowerCase() + n.slice(1);
20
+ function G(e) {
21
+ const t = M(e);
22
+ return t.charAt(0).toLowerCase() + t.slice(1);
23
23
  }
24
- function R(e) {
24
+ function O(e) {
25
25
  return e.replace(/[-\s]+/g, "_").replace(/([a-z])([A-Z])/g, "$1_$2").toUpperCase();
26
26
  }
27
- function j(e) {
28
- return e.replace(/[-_]+/g, " ").replace(/\b\w/g, (n) => n.toUpperCase());
27
+ function x(e) {
28
+ return e.replace(/[-_]+/g, " ").replace(/\b\w/g, (t) => t.toUpperCase());
29
29
  }
30
- function k(e) {
30
+ function N(e) {
31
31
  return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(e);
32
32
  }
33
- function _(e) {
33
+ function A(e) {
34
34
  return e.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
35
35
  }
36
- function I(e) {
36
+ function E(e) {
37
37
  return e.trim().toLowerCase().replace(/\/+/g, "/").replace(/[^a-z0-9/-]+/g, "/").replace(/\/?$/, "/");
38
38
  }
39
- function F(e) {
40
- const n = e.moduleName || "", t = n ? h(n) : "", s = {
39
+ function U(e) {
40
+ const t = e.moduleName || "", n = t ? v(t) : "", o = {
41
41
  hasModule: !!e.moduleName,
42
- ModuleName: t,
43
- ModuleNamePascalCase: n ? x(n) : "",
44
- ModuleNameCamelCase: n ? Y(n) : "",
45
- ModuleNameUppercase: t.toUpperCase(),
46
- ModuleNameScreamingSnake: n ? R(n) : "",
47
- ModuleNameSentenceCase: n ? j(n) : ""
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) : ""
48
48
  };
49
- return e.projectName && (s.AppName = h(e.projectName), s.AppNameSentenceCase = j(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;
50
50
  }
51
- const q = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".pdf", ".zip"]), W = {
51
+ const H = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".pdf", ".zip"]), X = {
52
52
  _gitignore: ".gitignore",
53
53
  "_yarnrc.yml": ".yarnrc.yml",
54
54
  _browserslistrc: ".browserslistrc",
@@ -63,177 +63,177 @@ const q = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ic
63
63
  _yarn: ".yarn",
64
64
  "_package.json": "package.json"
65
65
  };
66
- function G(e, n, t) {
67
- n.endsWith(".ejs") && (n = n.slice(0, -4));
68
- const s = c.dirname(n);
69
- r.existsSync(s) || r.mkdirSync(s, { recursive: !0 });
70
- const o = c.extname(e.replace(/\.ejs$/, "")).toLowerCase();
71
- if (q.has(o))
72
- r.copyFileSync(e, n);
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);
73
73
  else {
74
- const d = r.readFileSync(e, "utf-8"), p = D.render(d, t, { filename: e });
75
- r.writeFileSync(n, p);
74
+ const l = i.readFileSync(e, "utf-8"), s = F.render(l, n, { filename: e });
75
+ i.writeFileSync(t, s);
76
76
  }
77
77
  }
78
- function b(e, n, t) {
79
- if (!r.existsSync(e)) return;
80
- const s = r.readdirSync(e);
81
- for (const o of s) {
82
- const d = c.join(e, o), p = o.endsWith(".ejs") ? o.slice(0, -4) : o;
83
- let m = W[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;
84
84
  try {
85
- m = D.render(m, t);
85
+ c = F.render(c, n);
86
86
  } catch {
87
87
  }
88
- const i = c.join(n, m);
89
- r.statSync(d).isDirectory() ? (r.existsSync(i) || r.mkdirSync(i, { recursive: !0 }), b(d, i, t)) : G(d, i, 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);
90
90
  }
91
91
  }
92
- function H(e) {
93
- if (r.existsSync(e))
94
- for (const n of r.readdirSync(e)) {
95
- if (n === ".git") continue;
96
- const t = c.join(e, n);
97
- 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);
98
98
  }
99
99
  }
100
- function A(e) {
101
- if (!r.existsSync(e)) return !0;
102
- const n = r.readdirSync(e);
103
- return n.length === 0 || n.length === 1 && n[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
104
  }
105
- const X = /* @__PURE__ */ new Set(["node_modules", ".git", ".yarn", "dist"]);
106
- function U(e, n = []) {
107
- if (!r.existsSync(e)) return n;
108
- if (!r.statSync(e).isDirectory())
109
- return n.push(e), n;
110
- for (const t of r.readdirSync(e))
111
- X.has(t) || U(c.join(e, t), n);
112
- return n;
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
113
  }
114
114
  async function z(e) {
115
- const n = e.flatMap((s) => U(s));
116
- let t = 0;
117
- for (const s of n)
115
+ const t = e.flatMap((o) => L(o));
116
+ let n = 0;
117
+ for (const o of t)
118
118
  try {
119
- const o = await C.getFileInfo(s, { resolveConfig: !0 });
120
- if (!o.inferredParser || o.ignored) continue;
121
- const d = r.readFileSync(s, "utf-8"), p = await C.resolveConfig(s, { editorconfig: !0 }), m = await C.format(d, { ...p, filepath: s });
122
- m !== d && (r.writeFileSync(s, m), t++);
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
123
  } catch {
124
124
  }
125
- return t;
125
+ return n;
126
126
  }
127
- const Q = {
127
+ const ne = {
128
128
  standalone: "Standalone App",
129
129
  "dynamic-module": "Dynamic Module"
130
130
  };
131
- function ee(e) {
132
- const n = Q[e.projectType] ?? e.projectType, t = !!e.moduleName;
131
+ function oe(e) {
132
+ const t = ne[e.projectType] ?? e.projectType, n = !!e.moduleName;
133
133
  console.log(`
134
- ${a.green("╭─────────────────────────────────────────╮")}
135
- ${a.green("│")} ${a.green("│")}
136
- ${a.green("│")} ${a.bold("VC Shell App created successfully!")} ${a.green("│")}
137
- ${a.green("│")} ${a.green("│")}
138
- ${a.green("│")} Project: ${a.cyan(e.projectName.padEnd(28))}${a.green("│")}
139
- ${a.green("│")} Type: ${a.cyan(n.padEnd(28))}${a.green("│")}
140
- ${t && e.moduleName ? ` ${a.green("│")} Module: ${a.cyan(e.moduleName.padEnd(28))}${a.green("│")}
141
- ` : ""} ${a.green("│")} ${a.green("│")}
142
- ${a.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("╰─────────────────────────────────────────╯")}
143
143
 
144
- ${a.bold("Next steps:")}
144
+ ${r.bold("Next steps:")}
145
145
 
146
146
  1. cd ${e.projectName}
147
147
  2. yarn install
148
148
  3. yarn serve
149
- ${t && e.moduleName ? `
149
+ ${n && e.moduleName ? `
150
150
  Module is ready at:
151
- src/modules/${te(e.moduleName)}/
151
+ src/modules/${ae(e.moduleName)}/
152
152
  ` : ""}
153
- ${a.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/")}
154
154
  `);
155
155
  }
156
- function te(e) {
156
+ function ae(e) {
157
157
  return e.trim().replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase().replace(/[^a-z0-9-]/g, "");
158
158
  }
159
- const T = [
159
+ const D = [
160
160
  { title: "Standalone App — full application with bundled modules", value: "standalone" },
161
161
  { title: "Dynamic Module — remote module loaded by host via Module Federation", value: "dynamic-module" }
162
162
  ];
163
- function ne(e) {
164
- return typeof e == "string" && T.some((n) => n.value === e);
163
+ function re(e) {
164
+ return typeof e == "string" && D.some((t) => t.value === e);
165
165
  }
166
- async function ae(e, n) {
167
- const t = process.cwd();
168
- let o = e._?.[0] || e.name || e["app-name"];
169
- const d = o || "vc-app", p = () => o === "." ? c.basename(c.resolve()) : o, m = !!(o && e.type);
170
- let i;
171
- if (m) {
172
- o = o || d;
173
- const f = c.resolve(t, o);
174
- if (!ne(e.type)) {
175
- const N = T.map((S) => S.value).join(", ");
176
- console.error(a.red(`Unknown project type: "${e.type}". Valid types: ${N}`)), 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);
177
177
  }
178
- r.existsSync(f) && !A(f) && !e.overwrite && (console.error(a.red(`Target directory "${o}" is not empty. Use --overwrite to overwrite.`)), process.exit(1));
179
- const u = p(), y = e.type, g = e["module-name"], $ = y === "dynamic-module" ? g || j(u) : g || void 0;
180
- i = {
181
- projectName: h(u),
182
- packageName: e["package-name"] || (k(u) ? u : _(u)),
183
- projectType: y,
184
- moduleName: $,
185
- basePath: e["base-path"] || I(`/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)}/`),
186
186
  tenantRoutes: e["tenant-routes"] || !1,
187
187
  aiAgent: e["ai-agent"] || !1,
188
188
  dashboard: e.dashboard || !1,
189
189
  mocks: e.mocks || !1
190
190
  };
191
191
  } else {
192
- const f = () => {
193
- throw new Error(a.red("✖") + " Creation cancelled");
192
+ const y = () => {
193
+ throw new Error(r.red("✖") + " Creation cancelled");
194
194
  };
195
195
  try {
196
- const u = await P(
196
+ const f = await P(
197
197
  [
198
198
  {
199
199
  name: "projectName",
200
- type: o ? null : "text",
201
- message: a.reset("Project name:"),
202
- initial: d,
200
+ type: a ? null : "text",
201
+ message: r.reset("Project name:"),
202
+ initial: l,
203
203
  onState: (w) => {
204
- o = h(String(w.value).trim()) || d;
204
+ a = v(String(w.value).trim()) || l;
205
205
  },
206
- format: (w) => h(String(w).trim())
206
+ format: (w) => v(String(w).trim())
207
207
  },
208
208
  {
209
- type: () => !r.existsSync(c.resolve(t, o)) || A(c.resolve(t, o)) ? null : "confirm",
209
+ type: () => !i.existsSync(m.resolve(n, a)) || T(m.resolve(n, a)) ? null : "confirm",
210
210
  name: "overwrite",
211
- 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?"
212
212
  },
213
213
  {
214
- type: (w, { overwrite: M }) => {
215
- if (M === !1)
216
- throw new Error(a.red("✖") + " Operation cancelled");
214
+ type: (w, { overwrite: _ }) => {
215
+ if (_ === !1)
216
+ throw new Error(r.red("✖") + " Operation cancelled");
217
217
  return null;
218
218
  },
219
219
  name: "overwriteChecker"
220
220
  },
221
221
  {
222
222
  name: "packageName",
223
- type: () => k(p()) ? null : "text",
224
- message: a.reset("Package name:"),
225
- initial: () => _(p()),
226
- 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"
227
227
  },
228
228
  {
229
229
  type: "select",
230
230
  name: "projectType",
231
- message: a.reset("Project type:"),
232
- choices: T
231
+ message: r.reset("Project type:"),
232
+ choices: D
233
233
  }
234
234
  ],
235
- { onCancel: f }
236
- ), y = o ? h(o) : u.projectName, g = u.projectType || "standalone", $ = j(y), N = "/apps/" + h(y) + "/", S = await P(
235
+ { onCancel: y }
236
+ ), h = a ? v(a) : f.projectName, g = f.projectType || "standalone", b = x(h), S = "/apps/" + v(h) + "/", $ = await P(
237
237
  [
238
238
  {
239
239
  name: "includeModule",
@@ -243,17 +243,17 @@ async function ae(e, n) {
243
243
  },
244
244
  {
245
245
  name: "moduleName",
246
- type: (w, M) => g === "standalone" && !M.includeModule ? null : "text",
247
- message: a.reset("Module name:"),
248
- initial: $,
246
+ type: (w, _) => g === "standalone" && !_.includeModule ? null : "text",
247
+ message: r.reset("Module name:"),
248
+ initial: b,
249
249
  format: (w) => String(w).trim()
250
250
  },
251
251
  {
252
252
  name: "basePath",
253
253
  type: g === "dynamic-module" ? null : "text",
254
- message: a.reset("Base path:"),
255
- initial: N,
256
- format: (w) => I(String(w).trim())
254
+ message: r.reset("Base path:"),
255
+ initial: S,
256
+ format: (w) => E(String(w).trim())
257
257
  },
258
258
  {
259
259
  type: g === "dynamic-module" ? null : "confirm",
@@ -280,139 +280,213 @@ async function ae(e, n) {
280
280
  initial: !1
281
281
  }
282
282
  ],
283
- { onCancel: f }
283
+ { onCancel: y }
284
284
  );
285
- i = {
286
- projectName: y,
287
- packageName: u.packageName || (k(y) ? y : _(y)),
285
+ d = {
286
+ projectName: h,
287
+ packageName: f.packageName || (N(h) ? h : A(h)),
288
288
  projectType: g,
289
- moduleName: S.moduleName || (S.includeModule !== !1 ? $ : void 0),
290
- basePath: S.basePath || I(N),
291
- tenantRoutes: S.tenantRoutes || !1,
292
- aiAgent: S.aiAgent || !1,
293
- dashboard: S.dashboard ?? !0,
294
- mocks: S.mocks || !1
289
+ moduleName: $.moduleName || ($.includeModule !== !1 ? b : void 0),
290
+ basePath: $.basePath || E(S),
291
+ tenantRoutes: $.tenantRoutes || !1,
292
+ aiAgent: $.aiAgent || !1,
293
+ dashboard: $.dashboard ?? !0,
294
+ mocks: $.mocks || !1
295
295
  };
296
- } catch (u) {
297
- console.log(u.message), process.exit(1);
296
+ } catch (f) {
297
+ console.log(f.message), process.exit(1);
298
298
  }
299
299
  }
300
- const l = c.resolve(t, o);
301
- r.existsSync(l) && !A(l) ? H(l) : r.existsSync(l) || r.mkdirSync(l, { recursive: !0 }), console.log(`
302
- Scaffolding ${a.cyan(i.projectType)} in ${a.green(l)}...
300
+ const p = m.resolve(n, a);
301
+ i.existsSync(p) && !T(p) ? ee(p) : i.existsSync(p) || i.mkdirSync(p, { recursive: !0 }), console.log(`
302
+ Scaffolding ${r.cyan(d.projectType)} in ${r.green(p)}...
303
303
  `);
304
- const v = F(i);
305
- if (b(c.join(n, i.projectType), l, v), i.moduleName) {
306
- const f = h(i.moduleName), u = i.projectType === "dynamic-module" ? c.join(l, "src/modules") : c.join(l, "src/modules", f);
307
- b(c.join(n, "module"), u, v);
304
+ const u = U(d);
305
+ if (j(m.join(t, d.projectType), p, u), d.moduleName) {
306
+ const y = v(d.moduleName), f = d.projectType === "dynamic-module" ? m.join(p, "src/modules") : m.join(p, "src/modules", y);
307
+ j(m.join(t, "module"), f, u);
308
+ }
309
+ d.mocks && j(m.join(t, "sample-module"), m.join(p, "src/modules/sample"), u), await z([p]), oe(d);
310
+ }
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++;
308
346
  }
309
- i.mocks && b(c.join(n, "sample-module"), c.join(l, "src/modules/sample"), v), await z([l]), ee(i);
347
+ return n.join("");
310
348
  }
311
- function L(e, n) {
312
- const t = /^import\s.+$/gm;
313
- let s = null, o;
314
- for (; (o = t.exec(e)) !== null; )
315
- s = o;
316
- if (s) {
317
- const d = s.index + s[0].length;
318
- return e.slice(0, d) + `
319
- ` + n + e.slice(d);
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;
320
357
  }
321
- return n + `
322
- ` + e;
358
+ return -1;
323
359
  }
324
- function oe(e, n) {
325
- let t = r.readFileSync(e, "utf-8");
326
- const s = x(n), o = h(n);
327
- t = L(t, `import ${s} from "./modules/${o}";`);
328
- const d = /\.use\([A-Z]\w+,\s*\{\s*router\s*\}\)/g;
329
- let p = null, m;
330
- for (; (m = d.exec(t)) !== null; )
331
- p = m;
332
- if (p) {
333
- const i = p.index + p[0].length, l = `
334
- .use(${s}, { router })`;
335
- t = t.slice(0, i) + l + t.slice(i);
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 });
336
369
  }
337
- r.writeFileSync(e, t);
370
+ return o;
338
371
  }
339
- function re(e, n) {
340
- let t = r.readFileSync(e, "utf-8");
341
- const s = h(n), o = R(n);
342
- if (!t.includes("addMenuItem")) {
343
- const v = /import\s*\{([^}]+)\}\s*from\s*["']@vc-shell\/framework["']/.exec(t);
344
- if (v) {
345
- const f = v[1].trim() + ", addMenuItem";
346
- t = t.replace(v[0], `import { ${f} } from "@vc-shell/framework"`);
347
- } else
348
- t = L(t, 'import { addMenuItem } from "@vc-shell/framework";');
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;
349
379
  }
350
- const d = /addMenuItem\(\{[\s\S]*?\}\);/g;
351
- let p = null, m;
352
- for (; (m = d.exec(t)) !== null; )
353
- p = m;
354
- const i = `
355
- addMenuItem({
356
- title: "${o}.MENU.TITLE",
357
- icon: "lucide-box",
358
- priority: 10,
359
- url: "/${s}",
360
- });`;
361
- if (p) {
362
- const l = p.index + p[0].length;
363
- t = t.slice(0, l) + `
364
- ` + i + t.slice(l);
365
- } else {
366
- const l = t.lastIndexOf("}");
367
- l !== -1 && (t = t.slice(0, l) + i + `
368
- ` + t.slice(l));
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] ?? "";
386
+ }
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 = (u) => [
425
+ `${u}addMenuItem({`,
426
+ `${u} title: "${o}.MENU.TITLE",`,
427
+ `${u} icon: "lucide-box",`,
428
+ `${u} priority: 10,`,
429
+ `${u} url: "/${n}",`,
430
+ `${u}});`
431
+ ].join(`
432
+ `), c = ce(l, "addMenuItem"), d = c[c.length - 1];
433
+ if (d) {
434
+ const u = V(a, d.start);
435
+ i.writeFileSync(e, C(a, [{ at: d.end, text: `
436
+
437
+ ${s(u)}` }]));
438
+ return;
369
439
  }
370
- r.writeFileSync(e, t);
440
+ const p = l.lastIndexOf("}");
441
+ if (p === -1)
442
+ throw new Error("Could not find the bootstrap function body in bootstrap.ts");
443
+ i.writeFileSync(e, C(a, [{ at: p, text: `${s(" ")}
444
+ ` }]));
371
445
  }
372
- async function se(e, n) {
373
- const t = process.cwd(), s = e._?.[1], o = c.join(t, "package.json");
374
- r.existsSync(o) || (console.error(a.red("Error: No package.json found. Run this command from a vc-shell project root.")), process.exit(1));
375
- const d = JSON.parse(r.readFileSync(o, "utf-8"));
376
- ({ ...d.dependencies, ...d.devDependencies })["@vc-shell/framework"] || (console.error(a.red("Error: Not a vc-shell project (@vc-shell/framework not found in dependencies).")), process.exit(1));
377
- let m = s;
378
- m || (m = (await P({
446
+ async function pe(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({
379
453
  type: "text",
380
454
  name: "moduleName",
381
455
  message: "Module name:",
382
- validate: (N) => N.trim().length > 0 || "Module name is required"
383
- })).moduleName), m || (console.error(a.red("Module name is required.")), process.exit(1));
384
- const i = h(m), l = x(m), v = c.join(t, "src/modules"), f = c.join(v, i);
385
- r.existsSync(v) || r.mkdirSync(v, { recursive: !0 }), r.existsSync(f) && (console.error(a.red(`Error: Module "${i}" already exists at ${c.relative(t, f)}`)), process.exit(1));
386
- const u = F({ moduleName: m, projectName: c.basename(t) });
387
- b(c.join(n, "module"), f, u), console.log(a.green(` ✔ Created ${c.relative(t, f)}/`));
388
- const y = c.join(t, "src/main.ts");
389
- 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), p = M(c), u = m.join(n, "src/modules"), y = m.join(u, d);
459
+ i.existsSync(u) || i.mkdirSync(u, { 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))
390
464
  try {
391
- oe(y, m), console.log(a.green(` ✔ Updated src/main.ts — added import & app.use(${l})`));
465
+ le(h, c), console.log(r.green(` ✔ Updated src/main.ts — added import & app.use(${p})`));
392
466
  } catch {
393
- console.warn(a.yellow(" ⚠ Could not auto-update src/main.ts. Add manually:")), console.warn(a.yellow(` import ${l} from "./modules/${i}";`)), console.warn(a.yellow(` app.use(${l}, { router });`));
467
+ console.warn(r.yellow(" ⚠ Could not auto-update src/main.ts. Add manually:")), console.warn(r.yellow(` import ${p} from "./modules/${d}";`)), console.warn(r.yellow(` app.use(${p}, { router });`));
394
468
  }
395
- const g = c.join(t, "src/bootstrap.ts");
396
- if (r.existsSync(g))
469
+ const g = m.join(n, "src/bootstrap.ts");
470
+ if (i.existsSync(g))
397
471
  try {
398
- re(g, m), console.log(a.green(` ✔ Updated src/bootstrap.ts — added menu item "${j(m)}"`));
472
+ de(g, c), console.log(r.green(` ✔ Updated src/bootstrap.ts — added menu item "${x(c)}"`));
399
473
  } catch {
400
- console.warn(a.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."));
401
475
  }
402
- await z([f, y, g]), console.log(`
403
- Module "${i}" is ready! Run ${a.bold(a.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.
404
478
  `);
405
479
  }
406
- const E = c.resolve(K(import.meta.url), "..", "templates");
407
- function ce() {
480
+ const R = m.resolve(Z(import.meta.url), "..", "templates");
481
+ function ue() {
408
482
  console.log(`
409
- ${a.bold(a.green("create-vc-app"))} — Create VC Shell applications and modules
483
+ ${r.bold(r.green("create-vc-app"))} — Create VC Shell applications and modules
410
484
 
411
- ${a.bold("Usage:")}
485
+ ${r.bold("Usage:")}
412
486
  create-vc-app [project-name] [options] Create a new project
413
487
  create-vc-app add-module <module-name> Add a module to existing project
414
488
 
415
- ${a.bold("Options (create):")}
489
+ ${r.bold("Options (create):")}
416
490
  --type <type> Project type: standalone | dynamic-module
417
491
  --name, --app-name <name> Application name
418
492
  --package-name <name> npm package name
@@ -426,31 +500,31 @@ ${a.bold("Options (create):")}
426
500
  --help, -h Show this help
427
501
  --version, -v Show version
428
502
 
429
- ${a.bold("Examples:")}
503
+ ${r.bold("Examples:")}
430
504
  create-vc-app my-app
431
505
  create-vc-app my-app --type standalone --dashboard --mocks
432
506
  create-vc-app my-module --type dynamic-module --module-name "Reviews"
433
507
  create-vc-app add-module orders
434
508
 
435
- ${a.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/
436
510
  `);
437
511
  }
438
- async function ie() {
439
- const e = B(V.slice(2), {
512
+ async function fe() {
513
+ const e = K(Y.slice(2), {
440
514
  alias: { h: "help", v: "version" },
441
515
  boolean: ["help", "version", "mocks", "overwrite", "tenant-routes", "ai-agent", "dashboard"],
442
516
  string: ["type", "name", "app-name", "package-name", "module-name", "base-path"]
443
517
  });
444
518
  if (e.help) {
445
- ce();
519
+ ue();
446
520
  return;
447
521
  }
448
522
  if (e.version) {
449
- console.log(`create-vc-app v${J.version}`);
523
+ console.log(`create-vc-app v${W.version}`);
450
524
  return;
451
525
  }
452
- e._[0] === "add-module" ? await se(e, E) : await ae(e, E);
526
+ e._[0] === "add-module" ? await pe(e, R) : await se(e, R);
453
527
  }
454
- ie().catch((e) => {
455
- console.error(a.red(e.message || String(e))), O(1);
528
+ fe().catch((e) => {
529
+ console.error(r.red(e.message || String(e))), J(1);
456
530
  });
@@ -4,6 +4,7 @@ import { useAsync, useLoading } from "@vc-shell/framework";
4
4
  export default function use<%- ModuleNamePascalCase %>Details() {
5
5
  const item = ref<Record<string, any>>({});
6
6
 
7
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- used by the TODO API call below
7
8
  const { loading: itemLoading, action: fetchItem } = useAsync(async (id?: string) => {
8
9
  // TODO: Replace with real API call
9
10
  // const result = await apiClient.getById(id);
@@ -8,11 +8,11 @@ export interface <%- ModuleNamePascalCase %>ListQuery {
8
8
  take?: number;
9
9
  }
10
10
 
11
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
11
  export default function use<%- ModuleNamePascalCase %>List() {
13
12
  const data: Ref<Record<string, any>[]> = ref([]);
14
13
  const totalCount = ref(0);
15
14
 
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- used by the TODO API call below
16
16
  const { loading: itemsLoading, action: getItems } = useAsync<<%- ModuleNamePascalCase %>ListQuery>(async (query) => {
17
17
  // TODO: Replace with real API call
18
18
  // const result = await apiClient.search({
@@ -25,6 +25,7 @@ export default function use<%- ModuleNamePascalCase %>List() {
25
25
  // totalCount.value = result.totalCount ?? 0;
26
26
  });
27
27
 
28
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- used by the TODO API call below
28
29
  const { loading: deleteLoading, action: removeItems } = useAsync(async (ids?: string[]) => {
29
30
  // TODO: Replace with real API call
30
31
  // await Promise.all((ids ?? []).map((id) => apiClient.delete(id)));
@@ -1,7 +1,6 @@
1
- import { App } from "vue";
1
+ import { App<% if (dashboard) { %>, markRaw<% } %> } from "vue";
2
2
  <% if (dashboard) { -%>
3
3
  import { addMenuItem, registerDashboardWidget } from "@vc-shell/framework";
4
- import { markRaw } from "vue";
5
4
  import Welcome from "./components/dashboard-widgets/Welcome.vue";
6
5
  <% } -%>
7
6
 
@@ -18,6 +18,7 @@ const isReady = ref(false);
18
18
  const version = import.meta.env.PACKAGE_VERSION;
19
19
 
20
20
  const { isAuthenticated } = useUser();
21
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- used by the TODO example below
21
22
  const { setBroadcastFilter } = useBroadcastFilter();
22
23
 
23
24
  onMounted(async () => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vc-shell/create-vc-app",
3
3
  "description": "Application scaffolding",
4
- "version": "2.4.0-pr302.99e48e1",
4
+ "version": "2.4.0-pr302.b052b38",
5
5
  "type": "module",
6
6
  "bin": "./dist/index.js",
7
7
  "files": [
@@ -16,7 +16,7 @@
16
16
  "devDependencies": {
17
17
  "@types/ejs": "^3.1.5",
18
18
  "@types/prompts": "^2.4.4",
19
- "@vc-shell/ts-config": "2.4.0-pr302.99e48e1",
19
+ "@vc-shell/ts-config": "2.4.0-pr302.b052b38",
20
20
  "copyfiles": "^2.4.1",
21
21
  "cross-env": "^7.0.3",
22
22
  "shx": "^0.3.4",
@@ -24,7 +24,6 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "ejs": "^3.1.10",
27
- "magicast": "^0.3.5",
28
27
  "mri": "^1.2.0",
29
28
  "picocolors": "^1.1.1",
30
29
  "prettier": "^3.6.2",