@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.
- package/dist/commands/add-module.d.ts.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/engine/codegen.d.ts +5 -2
- package/dist/engine/codegen.d.ts.map +1 -1
- package/dist/engine/codegen.test.d.ts +2 -0
- package/dist/engine/codegen.test.d.ts.map +1 -0
- package/dist/engine/format.d.ts +13 -0
- package/dist/engine/format.d.ts.map +1 -0
- package/dist/index.js +330 -233
- package/dist/templates/dynamic-module/_package.json.ejs +3 -3
- package/dist/templates/dynamic-module/tsconfig.json +1 -5
- package/dist/templates/module/composables/useDetails.ts.ejs +1 -0
- package/dist/templates/module/composables/useList.ts.ejs +2 -1
- package/dist/templates/module/pages/list.vue.ejs +24 -4
- package/dist/templates/sample-module/composables/useList/index.ts +1 -1
- package/dist/templates/sample-module/pages/index.ts +1 -1
- package/dist/templates/sample-module/pages/list.vue +9 -1
- package/dist/templates/sample-module/sample-data/index.ts +2 -2
- package/dist/templates/standalone/_github/COMMIT_CONVENTION.md +12 -12
- package/dist/templates/standalone/_github/PULL_REQUEST_TEMPLATE.md +3 -0
- package/dist/templates/standalone/_package.json.ejs +4 -4
- package/dist/templates/standalone/_vscode/extensions.json +1 -3
- package/dist/templates/standalone/_vscode/settings.json +3 -8
- package/dist/templates/standalone/eslint.config.mjs +20 -0
- package/dist/templates/standalone/src/api_client/README.md +38 -37
- package/dist/templates/standalone/src/bootstrap.ts.ejs +1 -2
- package/dist/templates/standalone/src/components/dashboard-widgets/Welcome.vue +1 -2
- package/dist/templates/standalone/src/pages/App.vue.ejs +1 -0
- package/dist/templates/standalone/src/pages/Dashboard.vue.ejs +1 -1
- package/dist/templates/standalone/src/router/routes.ts.ejs +12 -15
- package/dist/templates/standalone/tsconfig.json +2 -9
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,53 +1,54 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { exit as
|
|
6
|
-
import { fileURLToPath as
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
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
|
|
17
|
-
return e.replace(/[-_\s]+(.)?/g, (
|
|
17
|
+
function M(e) {
|
|
18
|
+
return e.replace(/[-_\s]+(.)?/g, (t, n) => n ? n.toUpperCase() : "").replace(/^(.)/, (t, n) => n.toUpperCase());
|
|
18
19
|
}
|
|
19
|
-
function
|
|
20
|
-
const
|
|
21
|
-
return
|
|
20
|
+
function G(e) {
|
|
21
|
+
const t = M(e);
|
|
22
|
+
return t.charAt(0).toLowerCase() + t.slice(1);
|
|
22
23
|
}
|
|
23
|
-
function
|
|
24
|
+
function O(e) {
|
|
24
25
|
return e.replace(/[-\s]+/g, "_").replace(/([a-z])([A-Z])/g, "$1_$2").toUpperCase();
|
|
25
26
|
}
|
|
26
|
-
function
|
|
27
|
-
return e.replace(/[-_]+/g, " ").replace(/\b\w/g, (
|
|
27
|
+
function x(e) {
|
|
28
|
+
return e.replace(/[-_]+/g, " ").replace(/\b\w/g, (t) => t.toUpperCase());
|
|
28
29
|
}
|
|
29
|
-
function
|
|
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
|
|
33
|
+
function A(e) {
|
|
33
34
|
return e.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
|
|
34
35
|
}
|
|
35
|
-
function
|
|
36
|
+
function E(e) {
|
|
36
37
|
return e.trim().toLowerCase().replace(/\/+/g, "/").replace(/[^a-z0-9/-]+/g, "/").replace(/\/?$/, "/");
|
|
37
38
|
}
|
|
38
|
-
function
|
|
39
|
-
const
|
|
39
|
+
function U(e) {
|
|
40
|
+
const t = e.moduleName || "", n = t ? v(t) : "", o = {
|
|
40
41
|
hasModule: !!e.moduleName,
|
|
41
|
-
ModuleName:
|
|
42
|
-
ModuleNamePascalCase:
|
|
43
|
-
ModuleNameCamelCase:
|
|
44
|
-
ModuleNameUppercase:
|
|
45
|
-
ModuleNameScreamingSnake:
|
|
46
|
-
ModuleNameSentenceCase:
|
|
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 && (
|
|
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
|
|
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
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
71
|
-
|
|
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
|
|
74
|
-
|
|
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,
|
|
78
|
-
if (!
|
|
79
|
-
const
|
|
80
|
-
for (const
|
|
81
|
-
const
|
|
82
|
-
let
|
|
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
|
-
|
|
85
|
+
c = F.render(c, n);
|
|
85
86
|
} catch {
|
|
86
87
|
}
|
|
87
|
-
const
|
|
88
|
-
|
|
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
|
|
92
|
-
if (
|
|
93
|
-
for (const
|
|
94
|
-
if (
|
|
95
|
-
const
|
|
96
|
-
|
|
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
|
|
100
|
-
if (!
|
|
101
|
-
const
|
|
102
|
-
return
|
|
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
|
|
127
|
+
const ne = {
|
|
105
128
|
standalone: "Standalone App",
|
|
106
129
|
"dynamic-module": "Dynamic Module"
|
|
107
130
|
};
|
|
108
|
-
function
|
|
109
|
-
const
|
|
131
|
+
function oe(e) {
|
|
132
|
+
const t = ne[e.projectType] ?? e.projectType, n = !!e.moduleName;
|
|
110
133
|
console.log(`
|
|
111
|
-
${
|
|
112
|
-
${
|
|
113
|
-
${
|
|
114
|
-
${
|
|
115
|
-
${
|
|
116
|
-
${
|
|
117
|
-
${
|
|
118
|
-
` : ""} ${
|
|
119
|
-
${
|
|
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
|
-
${
|
|
144
|
+
${r.bold("Next steps:")}
|
|
122
145
|
|
|
123
146
|
1. cd ${e.projectName}
|
|
124
147
|
2. yarn install
|
|
125
148
|
3. yarn serve
|
|
126
|
-
${
|
|
149
|
+
${n && e.moduleName ? `
|
|
127
150
|
Module is ready at:
|
|
128
|
-
src/modules/${
|
|
151
|
+
src/modules/${ae(e.moduleName)}/
|
|
129
152
|
` : ""}
|
|
130
|
-
${
|
|
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
|
|
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
|
|
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
|
|
141
|
-
return typeof e == "string" &&
|
|
163
|
+
function re(e) {
|
|
164
|
+
return typeof e == "string" && D.some((t) => t.value === e);
|
|
142
165
|
}
|
|
143
|
-
async function
|
|
144
|
-
const
|
|
145
|
-
let
|
|
146
|
-
const
|
|
147
|
-
let
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
if (!
|
|
152
|
-
const
|
|
153
|
-
console.error(
|
|
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
|
-
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
projectName:
|
|
159
|
-
packageName: e["package-name"] || (
|
|
160
|
-
projectType:
|
|
161
|
-
moduleName:
|
|
162
|
-
basePath: e["base-path"] ||
|
|
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
|
|
170
|
-
throw new Error(
|
|
192
|
+
const y = () => {
|
|
193
|
+
throw new Error(r.red("✖") + " Creation cancelled");
|
|
171
194
|
};
|
|
172
195
|
try {
|
|
173
|
-
const
|
|
196
|
+
const f = await P(
|
|
174
197
|
[
|
|
175
198
|
{
|
|
176
199
|
name: "projectName",
|
|
177
|
-
type:
|
|
178
|
-
message:
|
|
179
|
-
initial:
|
|
200
|
+
type: a ? null : "text",
|
|
201
|
+
message: r.reset("Project name:"),
|
|
202
|
+
initial: l,
|
|
180
203
|
onState: (w) => {
|
|
181
|
-
|
|
204
|
+
a = v(String(w.value).trim()) || l;
|
|
182
205
|
},
|
|
183
|
-
format: (w) =>
|
|
206
|
+
format: (w) => v(String(w).trim())
|
|
184
207
|
},
|
|
185
208
|
{
|
|
186
|
-
type: () => !
|
|
209
|
+
type: () => !i.existsSync(m.resolve(n, a)) || T(m.resolve(n, a)) ? null : "confirm",
|
|
187
210
|
name: "overwrite",
|
|
188
|
-
message: () => (
|
|
211
|
+
message: () => (a === "." ? "Current directory" : `Target directory "${a}"`) + " is not empty. Remove existing files and continue?"
|
|
189
212
|
},
|
|
190
213
|
{
|
|
191
|
-
type: (w, { overwrite:
|
|
192
|
-
if (
|
|
193
|
-
throw new Error(
|
|
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: () =>
|
|
201
|
-
message:
|
|
202
|
-
initial: () =>
|
|
203
|
-
validate: (w) =>
|
|
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:
|
|
209
|
-
choices:
|
|
231
|
+
message: r.reset("Project type:"),
|
|
232
|
+
choices: D
|
|
210
233
|
}
|
|
211
234
|
],
|
|
212
|
-
{ onCancel:
|
|
213
|
-
),
|
|
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,
|
|
224
|
-
message:
|
|
225
|
-
initial:
|
|
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:
|
|
232
|
-
initial:
|
|
233
|
-
format: (w) =>
|
|
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:
|
|
283
|
+
{ onCancel: y }
|
|
261
284
|
);
|
|
262
|
-
|
|
263
|
-
projectName:
|
|
264
|
-
packageName:
|
|
285
|
+
d = {
|
|
286
|
+
projectName: h,
|
|
287
|
+
packageName: f.packageName || (N(h) ? h : A(h)),
|
|
265
288
|
projectType: g,
|
|
266
|
-
moduleName: $.moduleName || ($.includeModule !== !1 ?
|
|
267
|
-
basePath: $.basePath ||
|
|
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 (
|
|
274
|
-
console.log(
|
|
296
|
+
} catch (f) {
|
|
297
|
+
console.log(f.message), process.exit(1);
|
|
275
298
|
}
|
|
276
299
|
}
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
Scaffolding ${
|
|
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
|
|
282
|
-
if (j(
|
|
283
|
-
const
|
|
284
|
-
j(
|
|
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
|
-
|
|
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
|
|
289
|
-
const
|
|
290
|
-
let
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
|
299
|
-
` + e;
|
|
347
|
+
return n.join("");
|
|
300
348
|
}
|
|
301
|
-
function
|
|
302
|
-
let
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
|
|
358
|
+
return -1;
|
|
315
359
|
}
|
|
316
|
-
function
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const
|
|
321
|
-
if (
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
}
|
|
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
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
-
|
|
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
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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: (
|
|
360
|
-
})).moduleName),
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
const
|
|
364
|
-
j(
|
|
365
|
-
const
|
|
366
|
-
if (
|
|
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
|
-
|
|
465
|
+
le(h, c), console.log(r.green(` ✔ Updated src/main.ts — added import & app.use(${u})`));
|
|
369
466
|
} catch {
|
|
370
|
-
console.warn(
|
|
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 =
|
|
373
|
-
if (
|
|
469
|
+
const g = m.join(n, "src/bootstrap.ts");
|
|
470
|
+
if (i.existsSync(g))
|
|
374
471
|
try {
|
|
375
|
-
|
|
472
|
+
de(g, c), console.log(r.green(` ✔ Updated src/bootstrap.ts — added menu item "${x(c)}"`));
|
|
376
473
|
} catch {
|
|
377
|
-
console.warn(
|
|
474
|
+
console.warn(r.yellow(" ⚠ Could not auto-update src/bootstrap.ts. Add addMenuItem() manually."));
|
|
378
475
|
}
|
|
379
|
-
console.log(`
|
|
380
|
-
Module "${
|
|
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
|
|
384
|
-
function
|
|
480
|
+
const R = m.resolve(Z(import.meta.url), "..", "templates");
|
|
481
|
+
function pe() {
|
|
385
482
|
console.log(`
|
|
386
|
-
${
|
|
483
|
+
${r.bold(r.green("create-vc-app"))} — Create VC Shell applications and modules
|
|
387
484
|
|
|
388
|
-
${
|
|
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
|
-
${
|
|
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
|
-
${
|
|
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
|
-
${
|
|
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
|
|
416
|
-
const e =
|
|
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
|
-
|
|
519
|
+
pe();
|
|
423
520
|
return;
|
|
424
521
|
}
|
|
425
522
|
if (e.version) {
|
|
426
|
-
console.log(`create-vc-app v${
|
|
523
|
+
console.log(`create-vc-app v${W.version}`);
|
|
427
524
|
return;
|
|
428
525
|
}
|
|
429
|
-
e._[0] === "add-module" ? await
|
|
526
|
+
e._[0] === "add-module" ? await ue(e, R) : await se(e, R);
|
|
430
527
|
}
|
|
431
|
-
|
|
432
|
-
console.error(
|
|
528
|
+
fe().catch((e) => {
|
|
529
|
+
console.error(r.red(e.message || String(e))), J(1);
|
|
433
530
|
});
|