@vc-shell/create-vc-app 2.4.0-pr300.83479a4 → 2.4.0-pr302.99e48e1
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/format.d.ts +13 -0
- package/dist/engine/format.d.ts.map +1 -0
- package/dist/index.js +176 -153
- package/dist/templates/dynamic-module/tsconfig.json +1 -5
- 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/_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/components/dashboard-widgets/Welcome.vue +1 -2
- 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 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add-module.d.ts","sourceRoot":"","sources":["../../src/commands/add-module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"add-module.d.ts","sourceRoot":"","sources":["../../src/commands/add-module.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFzF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAA+B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAA+B,MAAM,aAAa,CAAC;AAsBxE,wBAAsB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4NpF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format generated sources in place.
|
|
3
|
+
*
|
|
4
|
+
* Templates are `.ejs`, so neither Prettier nor ESLint can check them directly —
|
|
5
|
+
* EJS control tags and the regex splicing in `codegen.ts` both emit code whose
|
|
6
|
+
* shape depends on runtime data. Running Prettier over the *output* is the only
|
|
7
|
+
* point where the result can be normalised.
|
|
8
|
+
*
|
|
9
|
+
* Formatting is best-effort: a file Prettier cannot parse is left untouched
|
|
10
|
+
* rather than failing the scaffold.
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatGenerated(targets: string[]): Promise<number>;
|
|
13
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/engine/format.ts"],"names":[],"mappings":"AAyBA;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BxE"}
|
package/dist/index.js
CHANGED
|
@@ -1,53 +1,54 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import B from "mri";
|
|
3
|
+
import a from "picocolors";
|
|
4
4
|
import c from "node:path";
|
|
5
|
-
import { exit as
|
|
6
|
-
import { fileURLToPath as
|
|
7
|
-
import
|
|
5
|
+
import { exit as O, argv as V } from "node:process";
|
|
6
|
+
import { fileURLToPath as K } from "node:url";
|
|
7
|
+
import P from "prompts";
|
|
8
8
|
import r from "node:fs";
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import D from "ejs";
|
|
10
|
+
import C from "prettier";
|
|
11
|
+
const Z = "2.4.0-pr302.99e48e1", J = {
|
|
12
|
+
version: Z
|
|
12
13
|
};
|
|
13
14
|
function h(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
17
|
function x(e) {
|
|
17
|
-
return e.replace(/[-_\s]+(.)?/g, (
|
|
18
|
+
return e.replace(/[-_\s]+(.)?/g, (n, t) => t ? t.toUpperCase() : "").replace(/^(.)/, (n, t) => t.toUpperCase());
|
|
18
19
|
}
|
|
19
|
-
function
|
|
20
|
-
const
|
|
21
|
-
return
|
|
20
|
+
function Y(e) {
|
|
21
|
+
const n = x(e);
|
|
22
|
+
return n.charAt(0).toLowerCase() + n.slice(1);
|
|
22
23
|
}
|
|
23
|
-
function
|
|
24
|
+
function R(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 j(e) {
|
|
28
|
+
return e.replace(/[-_]+/g, " ").replace(/\b\w/g, (n) => n.toUpperCase());
|
|
28
29
|
}
|
|
29
30
|
function k(e) {
|
|
30
31
|
return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(e);
|
|
31
32
|
}
|
|
32
|
-
function
|
|
33
|
+
function _(e) {
|
|
33
34
|
return e.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
|
|
34
35
|
}
|
|
35
|
-
function
|
|
36
|
+
function I(e) {
|
|
36
37
|
return e.trim().toLowerCase().replace(/\/+/g, "/").replace(/[^a-z0-9/-]+/g, "/").replace(/\/?$/, "/");
|
|
37
38
|
}
|
|
38
|
-
function
|
|
39
|
-
const
|
|
39
|
+
function F(e) {
|
|
40
|
+
const n = e.moduleName || "", t = n ? h(n) : "", s = {
|
|
40
41
|
hasModule: !!e.moduleName,
|
|
41
42
|
ModuleName: t,
|
|
42
|
-
ModuleNamePascalCase:
|
|
43
|
-
ModuleNameCamelCase:
|
|
43
|
+
ModuleNamePascalCase: n ? x(n) : "",
|
|
44
|
+
ModuleNameCamelCase: n ? Y(n) : "",
|
|
44
45
|
ModuleNameUppercase: t.toUpperCase(),
|
|
45
|
-
ModuleNameScreamingSnake:
|
|
46
|
-
ModuleNameSentenceCase:
|
|
46
|
+
ModuleNameScreamingSnake: n ? R(n) : "",
|
|
47
|
+
ModuleNameSentenceCase: n ? j(n) : ""
|
|
47
48
|
};
|
|
48
|
-
return e.projectName && (s.AppName = h(e.projectName), s.AppNameSentenceCase =
|
|
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
50
|
}
|
|
50
|
-
const
|
|
51
|
+
const q = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".pdf", ".zip"]), W = {
|
|
51
52
|
_gitignore: ".gitignore",
|
|
52
53
|
"_yarnrc.yml": ".yarnrc.yml",
|
|
53
54
|
_browserslistrc: ".browserslistrc",
|
|
@@ -62,104 +63,126 @@ 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 s = c.dirname(
|
|
66
|
+
function G(e, n, t) {
|
|
67
|
+
n.endsWith(".ejs") && (n = n.slice(0, -4));
|
|
68
|
+
const s = c.dirname(n);
|
|
68
69
|
r.existsSync(s) || r.mkdirSync(s, { recursive: !0 });
|
|
69
70
|
const o = c.extname(e.replace(/\.ejs$/, "")).toLowerCase();
|
|
70
|
-
if (
|
|
71
|
-
r.copyFileSync(e,
|
|
71
|
+
if (q.has(o))
|
|
72
|
+
r.copyFileSync(e, n);
|
|
72
73
|
else {
|
|
73
|
-
const d = r.readFileSync(e, "utf-8"), p =
|
|
74
|
-
r.writeFileSync(
|
|
74
|
+
const d = r.readFileSync(e, "utf-8"), p = D.render(d, t, { filename: e });
|
|
75
|
+
r.writeFileSync(n, p);
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
|
-
function
|
|
78
|
+
function b(e, n, t) {
|
|
78
79
|
if (!r.existsSync(e)) return;
|
|
79
80
|
const s = r.readdirSync(e);
|
|
80
81
|
for (const o of s) {
|
|
81
82
|
const d = c.join(e, o), p = o.endsWith(".ejs") ? o.slice(0, -4) : o;
|
|
82
|
-
let m =
|
|
83
|
+
let m = W[p] ?? p;
|
|
83
84
|
try {
|
|
84
|
-
m =
|
|
85
|
+
m = D.render(m, t);
|
|
85
86
|
} catch {
|
|
86
87
|
}
|
|
87
|
-
const
|
|
88
|
-
r.statSync(d).isDirectory() ? (r.existsSync(
|
|
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);
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
|
-
function
|
|
92
|
+
function H(e) {
|
|
92
93
|
if (r.existsSync(e))
|
|
93
|
-
for (const
|
|
94
|
-
if (
|
|
95
|
-
const t = c.join(e,
|
|
94
|
+
for (const n of r.readdirSync(e)) {
|
|
95
|
+
if (n === ".git") continue;
|
|
96
|
+
const t = c.join(e, n);
|
|
96
97
|
r.statSync(t).isDirectory() ? r.rmSync(t, { recursive: !0, force: !0 }) : r.unlinkSync(t);
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
|
-
function
|
|
100
|
+
function A(e) {
|
|
100
101
|
if (!r.existsSync(e)) return !0;
|
|
101
|
-
const
|
|
102
|
-
return
|
|
102
|
+
const n = r.readdirSync(e);
|
|
103
|
+
return n.length === 0 || n.length === 1 && n[0] === ".git";
|
|
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;
|
|
103
113
|
}
|
|
104
|
-
|
|
114
|
+
async function z(e) {
|
|
115
|
+
const n = e.flatMap((s) => U(s));
|
|
116
|
+
let t = 0;
|
|
117
|
+
for (const s of n)
|
|
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++);
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
return t;
|
|
126
|
+
}
|
|
127
|
+
const Q = {
|
|
105
128
|
standalone: "Standalone App",
|
|
106
129
|
"dynamic-module": "Dynamic Module"
|
|
107
130
|
};
|
|
108
|
-
function
|
|
109
|
-
const
|
|
131
|
+
function ee(e) {
|
|
132
|
+
const n = Q[e.projectType] ?? e.projectType, t = !!e.moduleName;
|
|
110
133
|
console.log(`
|
|
111
|
-
${
|
|
112
|
-
${
|
|
113
|
-
${
|
|
114
|
-
${
|
|
115
|
-
${
|
|
116
|
-
${
|
|
117
|
-
${t && e.moduleName ? ` ${
|
|
118
|
-
` : ""} ${
|
|
119
|
-
${
|
|
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("╰─────────────────────────────────────────╯")}
|
|
120
143
|
|
|
121
|
-
${
|
|
144
|
+
${a.bold("Next steps:")}
|
|
122
145
|
|
|
123
146
|
1. cd ${e.projectName}
|
|
124
147
|
2. yarn install
|
|
125
148
|
3. yarn serve
|
|
126
149
|
${t && e.moduleName ? `
|
|
127
150
|
Module is ready at:
|
|
128
|
-
src/modules/${
|
|
151
|
+
src/modules/${te(e.moduleName)}/
|
|
129
152
|
` : ""}
|
|
130
|
-
${
|
|
153
|
+
${a.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 te(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 T = [
|
|
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 ne(e) {
|
|
164
|
+
return typeof e == "string" && T.some((n) => n.value === e);
|
|
142
165
|
}
|
|
143
|
-
async function
|
|
166
|
+
async function ae(e, n) {
|
|
144
167
|
const t = process.cwd();
|
|
145
168
|
let o = e._?.[0] || e.name || e["app-name"];
|
|
146
169
|
const d = o || "vc-app", p = () => o === "." ? c.basename(c.resolve()) : o, m = !!(o && e.type);
|
|
147
|
-
let
|
|
170
|
+
let i;
|
|
148
171
|
if (m) {
|
|
149
172
|
o = o || d;
|
|
150
173
|
const f = c.resolve(t, o);
|
|
151
|
-
if (!
|
|
152
|
-
const
|
|
153
|
-
console.error(
|
|
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);
|
|
154
177
|
}
|
|
155
|
-
r.existsSync(f) && !
|
|
156
|
-
const u = p(), y = e.type, g = e["module-name"],
|
|
157
|
-
|
|
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 = {
|
|
158
181
|
projectName: h(u),
|
|
159
|
-
packageName: e["package-name"] || (k(u) ? u :
|
|
182
|
+
packageName: e["package-name"] || (k(u) ? u : _(u)),
|
|
160
183
|
projectType: y,
|
|
161
|
-
moduleName:
|
|
162
|
-
basePath: e["base-path"] ||
|
|
184
|
+
moduleName: $,
|
|
185
|
+
basePath: e["base-path"] || I(`/apps/${h(u)}/`),
|
|
163
186
|
tenantRoutes: e["tenant-routes"] || !1,
|
|
164
187
|
aiAgent: e["ai-agent"] || !1,
|
|
165
188
|
dashboard: e.dashboard || !1,
|
|
@@ -167,15 +190,15 @@ async function Q(e, a) {
|
|
|
167
190
|
};
|
|
168
191
|
} else {
|
|
169
192
|
const f = () => {
|
|
170
|
-
throw new Error(
|
|
193
|
+
throw new Error(a.red("✖") + " Creation cancelled");
|
|
171
194
|
};
|
|
172
195
|
try {
|
|
173
|
-
const u = await
|
|
196
|
+
const u = await P(
|
|
174
197
|
[
|
|
175
198
|
{
|
|
176
199
|
name: "projectName",
|
|
177
200
|
type: o ? null : "text",
|
|
178
|
-
message:
|
|
201
|
+
message: a.reset("Project name:"),
|
|
179
202
|
initial: d,
|
|
180
203
|
onState: (w) => {
|
|
181
204
|
o = h(String(w.value).trim()) || d;
|
|
@@ -183,14 +206,14 @@ async function Q(e, a) {
|
|
|
183
206
|
format: (w) => h(String(w).trim())
|
|
184
207
|
},
|
|
185
208
|
{
|
|
186
|
-
type: () => !r.existsSync(c.resolve(t, o)) ||
|
|
209
|
+
type: () => !r.existsSync(c.resolve(t, o)) || A(c.resolve(t, o)) ? null : "confirm",
|
|
187
210
|
name: "overwrite",
|
|
188
211
|
message: () => (o === "." ? "Current directory" : `Target directory "${o}"`) + " is not empty. Remove existing files and continue?"
|
|
189
212
|
},
|
|
190
213
|
{
|
|
191
214
|
type: (w, { overwrite: M }) => {
|
|
192
215
|
if (M === !1)
|
|
193
|
-
throw new Error(
|
|
216
|
+
throw new Error(a.red("✖") + " Operation cancelled");
|
|
194
217
|
return null;
|
|
195
218
|
},
|
|
196
219
|
name: "overwriteChecker"
|
|
@@ -198,19 +221,19 @@ async function Q(e, a) {
|
|
|
198
221
|
{
|
|
199
222
|
name: "packageName",
|
|
200
223
|
type: () => k(p()) ? null : "text",
|
|
201
|
-
message:
|
|
202
|
-
initial: () =>
|
|
224
|
+
message: a.reset("Package name:"),
|
|
225
|
+
initial: () => _(p()),
|
|
203
226
|
validate: (w) => k(w) || "Invalid package.json name"
|
|
204
227
|
},
|
|
205
228
|
{
|
|
206
229
|
type: "select",
|
|
207
230
|
name: "projectType",
|
|
208
|
-
message:
|
|
209
|
-
choices:
|
|
231
|
+
message: a.reset("Project type:"),
|
|
232
|
+
choices: T
|
|
210
233
|
}
|
|
211
234
|
],
|
|
212
235
|
{ onCancel: f }
|
|
213
|
-
), y = o ? h(o) : u.projectName, g = u.projectType || "standalone",
|
|
236
|
+
), y = o ? h(o) : u.projectName, g = u.projectType || "standalone", $ = j(y), N = "/apps/" + h(y) + "/", S = await P(
|
|
214
237
|
[
|
|
215
238
|
{
|
|
216
239
|
name: "includeModule",
|
|
@@ -221,16 +244,16 @@ async function Q(e, a) {
|
|
|
221
244
|
{
|
|
222
245
|
name: "moduleName",
|
|
223
246
|
type: (w, M) => g === "standalone" && !M.includeModule ? null : "text",
|
|
224
|
-
message:
|
|
225
|
-
initial:
|
|
247
|
+
message: a.reset("Module name:"),
|
|
248
|
+
initial: $,
|
|
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: a.reset("Base path:"),
|
|
255
|
+
initial: N,
|
|
256
|
+
format: (w) => I(String(w).trim())
|
|
234
257
|
},
|
|
235
258
|
{
|
|
236
259
|
type: g === "dynamic-module" ? null : "confirm",
|
|
@@ -259,33 +282,33 @@ async function Q(e, a) {
|
|
|
259
282
|
],
|
|
260
283
|
{ onCancel: f }
|
|
261
284
|
);
|
|
262
|
-
|
|
285
|
+
i = {
|
|
263
286
|
projectName: y,
|
|
264
|
-
packageName: u.packageName || (k(y) ? y :
|
|
287
|
+
packageName: u.packageName || (k(y) ? y : _(y)),
|
|
265
288
|
projectType: g,
|
|
266
|
-
moduleName:
|
|
267
|
-
basePath:
|
|
268
|
-
tenantRoutes:
|
|
269
|
-
aiAgent:
|
|
270
|
-
dashboard:
|
|
271
|
-
mocks:
|
|
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
|
|
272
295
|
};
|
|
273
296
|
} catch (u) {
|
|
274
297
|
console.log(u.message), process.exit(1);
|
|
275
298
|
}
|
|
276
299
|
}
|
|
277
|
-
const
|
|
278
|
-
r.existsSync(
|
|
279
|
-
Scaffolding ${
|
|
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)}...
|
|
280
303
|
`);
|
|
281
|
-
const v =
|
|
282
|
-
if (
|
|
283
|
-
const f = h(
|
|
284
|
-
|
|
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);
|
|
285
308
|
}
|
|
286
|
-
|
|
309
|
+
i.mocks && b(c.join(n, "sample-module"), c.join(l, "src/modules/sample"), v), await z([l]), ee(i);
|
|
287
310
|
}
|
|
288
|
-
function
|
|
311
|
+
function L(e, n) {
|
|
289
312
|
const t = /^import\s.+$/gm;
|
|
290
313
|
let s = null, o;
|
|
291
314
|
for (; (o = t.exec(e)) !== null; )
|
|
@@ -293,42 +316,42 @@ function U(e, a) {
|
|
|
293
316
|
if (s) {
|
|
294
317
|
const d = s.index + s[0].length;
|
|
295
318
|
return e.slice(0, d) + `
|
|
296
|
-
` +
|
|
319
|
+
` + n + e.slice(d);
|
|
297
320
|
}
|
|
298
|
-
return
|
|
321
|
+
return n + `
|
|
299
322
|
` + e;
|
|
300
323
|
}
|
|
301
|
-
function
|
|
324
|
+
function oe(e, n) {
|
|
302
325
|
let t = r.readFileSync(e, "utf-8");
|
|
303
|
-
const s = x(
|
|
304
|
-
t =
|
|
326
|
+
const s = x(n), o = h(n);
|
|
327
|
+
t = L(t, `import ${s} from "./modules/${o}";`);
|
|
305
328
|
const d = /\.use\([A-Z]\w+,\s*\{\s*router\s*\}\)/g;
|
|
306
329
|
let p = null, m;
|
|
307
330
|
for (; (m = d.exec(t)) !== null; )
|
|
308
331
|
p = m;
|
|
309
332
|
if (p) {
|
|
310
|
-
const
|
|
333
|
+
const i = p.index + p[0].length, l = `
|
|
311
334
|
.use(${s}, { router })`;
|
|
312
|
-
t = t.slice(0,
|
|
335
|
+
t = t.slice(0, i) + l + t.slice(i);
|
|
313
336
|
}
|
|
314
337
|
r.writeFileSync(e, t);
|
|
315
338
|
}
|
|
316
|
-
function
|
|
339
|
+
function re(e, n) {
|
|
317
340
|
let t = r.readFileSync(e, "utf-8");
|
|
318
|
-
const s = h(
|
|
341
|
+
const s = h(n), o = R(n);
|
|
319
342
|
if (!t.includes("addMenuItem")) {
|
|
320
343
|
const v = /import\s*\{([^}]+)\}\s*from\s*["']@vc-shell\/framework["']/.exec(t);
|
|
321
344
|
if (v) {
|
|
322
345
|
const f = v[1].trim() + ", addMenuItem";
|
|
323
346
|
t = t.replace(v[0], `import { ${f} } from "@vc-shell/framework"`);
|
|
324
347
|
} else
|
|
325
|
-
t =
|
|
348
|
+
t = L(t, 'import { addMenuItem } from "@vc-shell/framework";');
|
|
326
349
|
}
|
|
327
350
|
const d = /addMenuItem\(\{[\s\S]*?\}\);/g;
|
|
328
351
|
let p = null, m;
|
|
329
352
|
for (; (m = d.exec(t)) !== null; )
|
|
330
353
|
p = m;
|
|
331
|
-
const
|
|
354
|
+
const i = `
|
|
332
355
|
addMenuItem({
|
|
333
356
|
title: "${o}.MENU.TITLE",
|
|
334
357
|
icon: "lucide-box",
|
|
@@ -336,60 +359,60 @@ function te(e, a) {
|
|
|
336
359
|
url: "/${s}",
|
|
337
360
|
});`;
|
|
338
361
|
if (p) {
|
|
339
|
-
const
|
|
340
|
-
t = t.slice(0,
|
|
341
|
-
` +
|
|
362
|
+
const l = p.index + p[0].length;
|
|
363
|
+
t = t.slice(0, l) + `
|
|
364
|
+
` + i + t.slice(l);
|
|
342
365
|
} else {
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
` + t.slice(
|
|
366
|
+
const l = t.lastIndexOf("}");
|
|
367
|
+
l !== -1 && (t = t.slice(0, l) + i + `
|
|
368
|
+
` + t.slice(l));
|
|
346
369
|
}
|
|
347
370
|
r.writeFileSync(e, t);
|
|
348
371
|
}
|
|
349
|
-
async function
|
|
372
|
+
async function se(e, n) {
|
|
350
373
|
const t = process.cwd(), s = e._?.[1], o = c.join(t, "package.json");
|
|
351
|
-
r.existsSync(o) || (console.error(
|
|
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));
|
|
352
375
|
const d = JSON.parse(r.readFileSync(o, "utf-8"));
|
|
353
|
-
({ ...d.dependencies, ...d.devDependencies })["@vc-shell/framework"] || (console.error(
|
|
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));
|
|
354
377
|
let m = s;
|
|
355
|
-
m || (m = (await
|
|
378
|
+
m || (m = (await P({
|
|
356
379
|
type: "text",
|
|
357
380
|
name: "moduleName",
|
|
358
381
|
message: "Module name:",
|
|
359
|
-
validate: (
|
|
360
|
-
})).moduleName), m || (console.error(
|
|
361
|
-
const
|
|
362
|
-
r.existsSync(v) || r.mkdirSync(v, { recursive: !0 }), r.existsSync(f) && (console.error(
|
|
363
|
-
const u =
|
|
364
|
-
|
|
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)}/`));
|
|
365
388
|
const y = c.join(t, "src/main.ts");
|
|
366
389
|
if (r.existsSync(y))
|
|
367
390
|
try {
|
|
368
|
-
|
|
391
|
+
oe(y, m), console.log(a.green(` ✔ Updated src/main.ts — added import & app.use(${l})`));
|
|
369
392
|
} catch {
|
|
370
|
-
console.warn(
|
|
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 });`));
|
|
371
394
|
}
|
|
372
395
|
const g = c.join(t, "src/bootstrap.ts");
|
|
373
396
|
if (r.existsSync(g))
|
|
374
397
|
try {
|
|
375
|
-
|
|
398
|
+
re(g, m), console.log(a.green(` ✔ Updated src/bootstrap.ts — added menu item "${j(m)}"`));
|
|
376
399
|
} catch {
|
|
377
|
-
console.warn(
|
|
400
|
+
console.warn(a.yellow(" ⚠ Could not auto-update src/bootstrap.ts. Add addMenuItem() manually."));
|
|
378
401
|
}
|
|
379
|
-
console.log(`
|
|
380
|
-
Module "${
|
|
402
|
+
await z([f, y, g]), console.log(`
|
|
403
|
+
Module "${i}" is ready! Run ${a.bold(a.green("yarn serve"))} to see it.
|
|
381
404
|
`);
|
|
382
405
|
}
|
|
383
|
-
const
|
|
384
|
-
function
|
|
406
|
+
const E = c.resolve(K(import.meta.url), "..", "templates");
|
|
407
|
+
function ce() {
|
|
385
408
|
console.log(`
|
|
386
|
-
${
|
|
409
|
+
${a.bold(a.green("create-vc-app"))} — Create VC Shell applications and modules
|
|
387
410
|
|
|
388
|
-
${
|
|
411
|
+
${a.bold("Usage:")}
|
|
389
412
|
create-vc-app [project-name] [options] Create a new project
|
|
390
413
|
create-vc-app add-module <module-name> Add a module to existing project
|
|
391
414
|
|
|
392
|
-
${
|
|
415
|
+
${a.bold("Options (create):")}
|
|
393
416
|
--type <type> Project type: standalone | dynamic-module
|
|
394
417
|
--name, --app-name <name> Application name
|
|
395
418
|
--package-name <name> npm package name
|
|
@@ -403,31 +426,31 @@ ${n.bold("Options (create):")}
|
|
|
403
426
|
--help, -h Show this help
|
|
404
427
|
--version, -v Show version
|
|
405
428
|
|
|
406
|
-
${
|
|
429
|
+
${a.bold("Examples:")}
|
|
407
430
|
create-vc-app my-app
|
|
408
431
|
create-vc-app my-app --type standalone --dashboard --mocks
|
|
409
432
|
create-vc-app my-module --type dynamic-module --module-name "Reviews"
|
|
410
433
|
create-vc-app add-module orders
|
|
411
434
|
|
|
412
|
-
${
|
|
435
|
+
${a.bold("Docs:")} https://docs.virtocommerce.org/platform/developer-guide/latest/custom-apps-development/vc-shell/vc-shell-overview/
|
|
413
436
|
`);
|
|
414
437
|
}
|
|
415
|
-
async function
|
|
416
|
-
const e =
|
|
438
|
+
async function ie() {
|
|
439
|
+
const e = B(V.slice(2), {
|
|
417
440
|
alias: { h: "help", v: "version" },
|
|
418
441
|
boolean: ["help", "version", "mocks", "overwrite", "tenant-routes", "ai-agent", "dashboard"],
|
|
419
442
|
string: ["type", "name", "app-name", "package-name", "module-name", "base-path"]
|
|
420
443
|
});
|
|
421
444
|
if (e.help) {
|
|
422
|
-
|
|
445
|
+
ce();
|
|
423
446
|
return;
|
|
424
447
|
}
|
|
425
448
|
if (e.version) {
|
|
426
|
-
console.log(`create-vc-app v${
|
|
449
|
+
console.log(`create-vc-app v${J.version}`);
|
|
427
450
|
return;
|
|
428
451
|
}
|
|
429
|
-
e._[0] === "add-module" ? await
|
|
452
|
+
e._[0] === "add-module" ? await se(e, E) : await ae(e, E);
|
|
430
453
|
}
|
|
431
|
-
|
|
432
|
-
console.error(
|
|
454
|
+
ie().catch((e) => {
|
|
455
|
+
console.error(a.red(e.message || String(e))), O(1);
|
|
433
456
|
});
|
|
@@ -18,14 +18,30 @@
|
|
|
18
18
|
@pagination-click="pagination.goToPage"
|
|
19
19
|
>
|
|
20
20
|
<!-- Add your columns here -->
|
|
21
|
-
<VcColumn
|
|
22
|
-
|
|
21
|
+
<VcColumn
|
|
22
|
+
id="name"
|
|
23
|
+
:title="$t('<%- ModuleNameScreamingSnake %>.PAGES.LIST.COLUMNS.NAME')"
|
|
24
|
+
sortable
|
|
25
|
+
/>
|
|
26
|
+
<VcColumn
|
|
27
|
+
id="createdDate"
|
|
28
|
+
:title="$t('<%- ModuleNameScreamingSnake %>.PAGES.LIST.COLUMNS.CREATED_DATE')"
|
|
29
|
+
type="datetime"
|
|
30
|
+
sortable
|
|
31
|
+
/>
|
|
23
32
|
</VcDataTable>
|
|
24
33
|
</VcBlade>
|
|
25
34
|
</template>
|
|
26
35
|
|
|
27
36
|
<script setup lang="ts">
|
|
28
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
useBlade,
|
|
39
|
+
useDataTableSort,
|
|
40
|
+
useTableSearch,
|
|
41
|
+
useDataTablePagination,
|
|
42
|
+
useFunctions,
|
|
43
|
+
type IBladeToolbar,
|
|
44
|
+
} from "@vc-shell/framework";
|
|
29
45
|
import { VcBlade, VcDataTable, VcColumn } from "@vc-shell/framework/ui";
|
|
30
46
|
import { ref, watch } from "vue";
|
|
31
47
|
import use<%- ModuleNamePascalCase %>List from "../composables/useList";
|
|
@@ -57,7 +73,11 @@ const { sortField, sortOrder, sortExpression } = useDataTableSort({
|
|
|
57
73
|
const { data, loading, totalCount, getItems } = use<%- ModuleNamePascalCase %>List();
|
|
58
74
|
|
|
59
75
|
const { searchValue } = useTableSearch({ stateKey: "<%- ModuleNameScreamingSnake %>" });
|
|
60
|
-
const pagination = useDataTablePagination({
|
|
76
|
+
const pagination = useDataTablePagination({
|
|
77
|
+
stateKey: "<%- ModuleNameScreamingSnake %>",
|
|
78
|
+
pageSize: PAGE_SIZE,
|
|
79
|
+
totalCount,
|
|
80
|
+
});
|
|
61
81
|
|
|
62
82
|
function load() {
|
|
63
83
|
return getItems({
|
|
@@ -25,7 +25,7 @@ interface SearchResult {
|
|
|
25
25
|
|
|
26
26
|
export type { MockedItem };
|
|
27
27
|
|
|
28
|
-
export default (options?: { pageSize?: number
|
|
28
|
+
export default (options?: { pageSize?: number; sort?: string }): useClassicAppList => {
|
|
29
29
|
const pageSize = options?.pageSize || 20;
|
|
30
30
|
const searchResult = ref<SearchResult>();
|
|
31
31
|
const searchQuery = ref<SearchQuery>({
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as List } from "./list.vue";
|
|
2
|
-
export {default as Details } from
|
|
2
|
+
export { default as Details } from "./details.vue";
|
|
@@ -75,7 +75,15 @@
|
|
|
75
75
|
|
|
76
76
|
<script lang="ts" setup>
|
|
77
77
|
import { ref, watch, computed } from "vue";
|
|
78
|
-
import {
|
|
78
|
+
import {
|
|
79
|
+
IBladeToolbar,
|
|
80
|
+
useBlade,
|
|
81
|
+
usePopup,
|
|
82
|
+
useDataTableSort,
|
|
83
|
+
useTableSearch,
|
|
84
|
+
useDataTablePagination,
|
|
85
|
+
useFunctions,
|
|
86
|
+
} from "@vc-shell/framework";
|
|
79
87
|
import type { TableAction } from "@vc-shell/framework";
|
|
80
88
|
import { VcColumn, VcDataTable, VcBlade } from "@vc-shell/framework/ui";
|
|
81
89
|
import { useI18n } from "vue-i18n";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
1
|
+
export * from "./constants";
|
|
2
|
+
export * from "./methods";
|
|
@@ -4,21 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
Messages must be matched by the following regex:
|
|
6
6
|
|
|
7
|
-
```
|
|
8
|
-
/^(revert: )?(feat|fix|docs|style|refactor|perf|test|workflow|ci|chore|types)(\(.+\))?: .{1,50}
|
|
7
|
+
```js
|
|
8
|
+
/^(revert: )?(feat|fix|docs|style|refactor|perf|test|workflow|ci|chore|types)(\(.+\))?: .{1,50}/;
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Examples
|
|
12
12
|
|
|
13
13
|
Appears under "Features" header, `ui-kit` subheader:
|
|
14
14
|
|
|
15
|
-
```
|
|
15
|
+
```text
|
|
16
16
|
feat(ui-kit): add 'comments' option
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Appears under "Bug Fixes" header, `shell` subheader, with a link to issue #28:
|
|
20
20
|
|
|
21
|
-
```
|
|
21
|
+
```text
|
|
22
22
|
fix(shell): handle events on blur
|
|
23
23
|
|
|
24
24
|
close #28
|
|
@@ -26,7 +26,7 @@ close #28
|
|
|
26
26
|
|
|
27
27
|
Appears under "Performance Improvements" header, and under "Breaking Changes" with the breaking change explanation:
|
|
28
28
|
|
|
29
|
-
```
|
|
29
|
+
```text
|
|
30
30
|
perf(api-client): improve vdom diffing by removing 'foo' option
|
|
31
31
|
|
|
32
32
|
BREAKING CHANGE: The 'foo' option has been removed.
|
|
@@ -34,7 +34,7 @@ BREAKING CHANGE: The 'foo' option has been removed.
|
|
|
34
34
|
|
|
35
35
|
The following commit and commit `667ecc1` do not appear in the changelog if they are under the same release. If not, the revert commit appears under the "Reverts" header.
|
|
36
36
|
|
|
37
|
-
```
|
|
37
|
+
```text
|
|
38
38
|
revert: feat(ui-kit): add 'comments' option
|
|
39
39
|
|
|
40
40
|
This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
|
|
@@ -42,9 +42,9 @@ This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
|
|
|
42
42
|
|
|
43
43
|
## Full Message Format
|
|
44
44
|
|
|
45
|
-
A commit message consists of a **header**, **body** and **footer**.
|
|
45
|
+
A commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**:
|
|
46
46
|
|
|
47
|
-
```
|
|
47
|
+
```text
|
|
48
48
|
<type>(<scope>): <subject>
|
|
49
49
|
<BLANK LINE>
|
|
50
50
|
<body>
|
|
@@ -68,15 +68,15 @@ Other prefixes are up to your discretion. Suggested prefixes are `docs`, `chore`
|
|
|
68
68
|
|
|
69
69
|
### Scope
|
|
70
70
|
|
|
71
|
-
The scope could be any valid workspace package name. For example `shell`, `ui-kit`, `api-client`, etc...
|
|
71
|
+
The scope could be any valid workspace package name. For example `shell`, `ui-kit`, `api-client`, etc...
|
|
72
72
|
|
|
73
73
|
### Subject
|
|
74
74
|
|
|
75
75
|
The subject contains succinct description of the change:
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
- use the imperative, present tense: "change" not "changed" nor "changes"
|
|
78
|
+
- don't capitalize first letter
|
|
79
|
+
- no dot (.) at the end
|
|
80
80
|
|
|
81
81
|
### Body
|
|
82
82
|
|
|
@@ -3,12 +3,7 @@
|
|
|
3
3
|
"source.fixAll.eslint": true
|
|
4
4
|
},
|
|
5
5
|
"files.eol": "\r\n",
|
|
6
|
-
"eslint.validate": [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
],
|
|
10
|
-
"i18n-ally.localesPaths": [
|
|
11
|
-
"src/locales",
|
|
12
|
-
],
|
|
13
|
-
"typescript.preferences.importModuleSpecifier": "relative",
|
|
6
|
+
"eslint.validate": ["vue", "javascript"],
|
|
7
|
+
"i18n-ally.localesPaths": ["src/locales"],
|
|
8
|
+
"typescript.preferences.importModuleSpecifier": "relative"
|
|
14
9
|
}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import pluginVue from "eslint-plugin-vue";
|
|
2
2
|
import vueTsEslintConfig from "@vue/eslint-config-typescript";
|
|
3
3
|
import vuePrettierConfig from "@vue/eslint-config-prettier";
|
|
4
|
+
import importPlugin from "eslint-plugin-import";
|
|
4
5
|
|
|
5
6
|
export default [
|
|
6
7
|
{
|
|
7
8
|
ignores: ["**/node_modules/**", "**/dist/**", "api-client.ts"],
|
|
8
9
|
},
|
|
9
10
|
|
|
11
|
+
importPlugin.flatConfigs.recommended,
|
|
12
|
+
|
|
13
|
+
importPlugin.flatConfigs.typescript,
|
|
14
|
+
|
|
10
15
|
...pluginVue.configs["flat/recommended"],
|
|
11
16
|
|
|
12
17
|
...vueTsEslintConfig(),
|
|
@@ -14,6 +19,14 @@ export default [
|
|
|
14
19
|
vuePrettierConfig,
|
|
15
20
|
|
|
16
21
|
{
|
|
22
|
+
settings: {
|
|
23
|
+
"import/resolver": {
|
|
24
|
+
typescript: {
|
|
25
|
+
alwaysTryTypes: true,
|
|
26
|
+
project: "./tsconfig.json",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
17
30
|
rules: {
|
|
18
31
|
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
|
19
32
|
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
|
@@ -26,6 +39,13 @@ export default [
|
|
|
26
39
|
"vue/require-default-prop": "off",
|
|
27
40
|
"vue/no-v-html": "off",
|
|
28
41
|
"vue/no-template-shadow": "off",
|
|
42
|
+
// Vite serves `public/` at the site root, so these are not module paths.
|
|
43
|
+
"import/no-unresolved": ["error", { ignore: ["^/assets/"] }],
|
|
44
|
+
// TypeScript already covers these, and the rules parse dependency
|
|
45
|
+
// sources with espree, which chokes on modern syntax in `dist` output.
|
|
46
|
+
"import/namespace": "off",
|
|
47
|
+
"import/default": "off",
|
|
48
|
+
"import/no-named-as-default-member": "off",
|
|
29
49
|
},
|
|
30
50
|
},
|
|
31
51
|
];
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
This guide describes the process of generating an API client to access the VC Platform API from your custom application.
|
|
6
6
|
|
|
7
7
|
!!! note
|
|
8
|
-
|
|
8
|
+
Platform Manager REST Client offers generated REST API methods that make it easy to interact with the existing VirtoCommerce Platform API.
|
|
9
9
|
|
|
10
10
|
## Prerequisites
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
- .NET Core 6.0, particularly if you are using MacOS or Linux.
|
|
13
13
|
|
|
14
14
|
## Generate TypeScript API clients
|
|
15
15
|
|
|
@@ -22,6 +22,7 @@ Using command
|
|
|
22
22
|
```bash
|
|
23
23
|
yarn add @vc-shell/api-client-generator cross-env
|
|
24
24
|
```
|
|
25
|
+
|
|
25
26
|
<br>
|
|
26
27
|
|
|
27
28
|
`cross-env` runs scripts that set and use environment variables across platforms.
|
|
@@ -44,44 +45,44 @@ Add the dependencies to your project's **package.json**:
|
|
|
44
45
|
|
|
45
46
|
2. Configure client generation in your project. Inside your project's **package.json** file, add a `"generate-api-client"` command to the list of scripts:
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
48
|
+
```title="vc-app-extend/package.json" linenums="1"
|
|
49
|
+
{
|
|
50
|
+
"scripts": {
|
|
51
|
+
...
|
|
52
|
+
"generate-api-client": cross-env api-client-generator --APP_PLATFORM_MODULES='[MarketplaceVendor,Catalog,Orders]' --APP_API_CLIENT_DIRECTORY=./src/api_client/
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The options are listed in the table below:
|
|
58
|
+
|
|
59
|
+
| Options | Description | Example |
|
|
60
|
+
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
61
|
+
| `--APP_PLATFORM_MODULES` | Platform modules to generate API client.<br>{==string[]==} <br> Customize the `--APP_PLATFORM_MODULES` list<br>to match your project's requirements. | `--APP_PLATFORM_MODULES='[MarketplaceVendor,Orders,Catalog]'` |
|
|
62
|
+
| `--APP_API_CLIENT_DIRECTORY` | Output directory for generated API clients. <br>{==string==} | `--APP_API_CLIENT_DIRECTORY=./src/api_client/` |
|
|
63
|
+
| `--APP_PLATFORM_URL` | Platform URL to obtain client API configs. <br>{==string==} | `--APP_PLATFORM_URL=https://vcmp-dev.govirto.com/` |
|
|
64
|
+
| `--APP_PACKAGE_NAME` | Package name for generated API clients. <br>{==string==} | `--APP_PACKAGE_NAME=vc-app-extend` |
|
|
65
|
+
| `--APP_PACKAGE_VERSION` | Package version for generated API clients. <br>{==string==} | `--APP_PACKAGE_VERSION=1.0.0` |
|
|
66
|
+
| `--APP_TYPE_STYLE` | Sets the type style for generated DTOs. Can be 'Class' or 'Interface'.<br>{==string==} | `--APP_TYPE_STYLE=Interface` |
|
|
67
|
+
| `--APP_OUT_DIR` | Output directory for generated API clients. <br>{==string==} | `--APP_OUT_DIR=./src/api_client/` |
|
|
68
|
+
| `--APP_BUILD_DIR` | Directory where TypeScript files will be compiled. <br>{==string==} | `--APP_BUILD_DIR=lib` (default is "dist") |
|
|
69
|
+
| `--SKIP_BUILD` | Skip build step. <br>{==boolean==} | `--SKIP_BUILD=true` |
|
|
70
|
+
| `--VERBOSE` | Enable verbose logging. <br>{==boolean==} | `--VERBOSE=true` |
|
|
70
71
|
|
|
71
72
|
3. Configure Platform URL to ensure your project can access the platform's API configurations. Add the platform URL to your project's **.env** file:
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
```title="vc-app-extend/.env"
|
|
75
|
+
APP_PLATFORM_URL=https://vcmp-dev.govirto.com/
|
|
76
|
+
```
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
!!! note
|
|
79
|
+
Alternatively, you can specify the Platform URL as a command option in the previous step when running the `"generate-api-client"` command.
|
|
79
80
|
|
|
80
81
|
4. Generate the API clients using the following command:
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
```
|
|
84
|
+
yarn generate-api-client
|
|
85
|
+
```
|
|
85
86
|
|
|
86
87
|
This command generates the required API clients for your custom application. Now you can effortlessly access the VC Platform API from your custom application using the generated API client.
|
|
87
88
|
|
|
@@ -112,7 +113,7 @@ API client now includes metadata to track the generation:
|
|
|
112
113
|
|
|
113
114
|
The generator handles multiple API clients effectively:
|
|
114
115
|
|
|
115
|
-
- Creates standardized exports with both short names (`./{moduleName}`) and full names (`./virtocommerce.{moduleName}`)
|
|
116
|
+
- Creates standardized exports with both short names (`./{moduleName}`) and full names (`./virtocommerce.{moduleName}`)
|
|
116
117
|
- Prevents duplicate module exports by intelligently merging with existing ones
|
|
117
118
|
- Automatically removes `module` and `types` fields that conflict with multiple exports
|
|
118
119
|
- Works properly with incremental generation (can add new APIs without breaking existing ones)
|
|
@@ -129,11 +130,11 @@ This enables both simple usage for single-API packages and proper subpath export
|
|
|
129
130
|
|
|
130
131
|
```js
|
|
131
132
|
// Single API package (using root export)
|
|
132
|
-
import { MyClient } from
|
|
133
|
+
import { MyClient } from "@myapp/api";
|
|
133
134
|
|
|
134
135
|
// Multi-API package (using subpath exports)
|
|
135
|
-
import { ClientA } from
|
|
136
|
-
import { ClientB } from
|
|
136
|
+
import { ClientA } from "@myapp/api/moduleA";
|
|
137
|
+
import { ClientB } from "@myapp/api/moduleB";
|
|
137
138
|
```
|
|
138
139
|
|
|
139
140
|
### Directory Creation
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
</template>
|
|
15
15
|
|
|
16
16
|
<script setup lang="ts">
|
|
17
|
-
// eslint-disable-next-line import/no-unresolved
|
|
18
17
|
import Welcome from "/assets/welcome.png";
|
|
19
18
|
</script>
|
|
20
19
|
|
|
@@ -40,7 +39,7 @@ import Welcome from "/assets/welcome.png";
|
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
&__welcome-description {
|
|
43
|
-
@apply tw-whitespace-break-spaces tw-text-
|
|
42
|
+
@apply tw-whitespace-break-spaces tw-text-sm tw-max-w-[90%] tw-mx-auto tw-leading-5 tw-font-semibold;
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
45
|
</style>
|
|
@@ -1,43 +1,40 @@
|
|
|
1
1
|
import { RouteRecordRaw } from "vue-router";
|
|
2
2
|
import App from "../pages/App.vue";
|
|
3
|
-
<% if (dashboard) {
|
|
3
|
+
<%_ if (dashboard) { -%>
|
|
4
4
|
import Dashboard from "../pages/Dashboard.vue";
|
|
5
|
-
<% }
|
|
5
|
+
<%_ } -%>
|
|
6
6
|
import { Invite, Login, ResetPassword, ForgotPassword, ChangePasswordPage } from "@vc-shell/framework";
|
|
7
|
-
// eslint-disable-next-line import/no-unresolved
|
|
8
7
|
import whiteLogoImage from "/assets/logo-white.svg";
|
|
9
|
-
|
|
10
|
-
import bgImage from "/assets/background.jpg";
|
|
8
|
+
<%_ if (tenantRoutes) { -%>
|
|
11
9
|
|
|
12
|
-
<% if (tenantRoutes) { %>
|
|
13
10
|
const tenantIdRegex = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
|
|
14
|
-
<% }
|
|
11
|
+
<%_ } -%>
|
|
15
12
|
|
|
16
13
|
export const routes: RouteRecordRaw[] = [
|
|
17
14
|
{
|
|
18
|
-
<% if (tenantRoutes) {
|
|
15
|
+
<%_ if (tenantRoutes) { -%>
|
|
19
16
|
path: `/:tenantId(${tenantIdRegex})?`,
|
|
20
|
-
<% } else {
|
|
17
|
+
<%_ } else { -%>
|
|
21
18
|
path: "/",
|
|
22
|
-
<% }
|
|
19
|
+
<%_ } -%>
|
|
23
20
|
component: App,
|
|
24
21
|
name: "App",
|
|
25
22
|
meta: {
|
|
26
23
|
root: true,
|
|
27
24
|
},
|
|
28
25
|
children: [
|
|
29
|
-
<% if (dashboard) {
|
|
26
|
+
<%_ if (dashboard) { -%>
|
|
30
27
|
{
|
|
31
28
|
name: "Dashboard",
|
|
32
29
|
path: "",
|
|
33
|
-
<% if (tenantRoutes) {
|
|
30
|
+
<%_ if (tenantRoutes) { -%>
|
|
34
31
|
alias: `/:tenantId(${tenantIdRegex})?`,
|
|
35
|
-
<% } else {
|
|
32
|
+
<%_ } else { -%>
|
|
36
33
|
alias: "/",
|
|
37
|
-
<% }
|
|
34
|
+
<%_ } -%>
|
|
38
35
|
component: Dashboard,
|
|
39
36
|
},
|
|
40
|
-
<% }
|
|
37
|
+
<%_ } -%>
|
|
41
38
|
],
|
|
42
39
|
},
|
|
43
40
|
{
|
|
@@ -4,14 +4,7 @@
|
|
|
4
4
|
"baseUrl": ".",
|
|
5
5
|
"outDir": "dist",
|
|
6
6
|
"rootDir": "src",
|
|
7
|
-
"types": [
|
|
8
|
-
"vite/client",
|
|
9
|
-
"@vc-shell/framework/globals"
|
|
10
|
-
]
|
|
7
|
+
"types": ["vite/client", "@vc-shell/framework/globals"]
|
|
11
8
|
},
|
|
12
|
-
"include": [
|
|
13
|
-
"./src/**/*.ts",
|
|
14
|
-
"./src/**/*.vue",
|
|
15
|
-
"./src/**/*.json"
|
|
16
|
-
]
|
|
9
|
+
"include": ["./src/**/*.ts", "./src/**/*.vue", "./src/**/*.json"]
|
|
17
10
|
}
|
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-
|
|
4
|
+
"version": "2.4.0-pr302.99e48e1",
|
|
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-
|
|
19
|
+
"@vc-shell/ts-config": "2.4.0-pr302.99e48e1",
|
|
20
20
|
"copyfiles": "^2.4.1",
|
|
21
21
|
"cross-env": "^7.0.3",
|
|
22
22
|
"shx": "^0.3.4",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"magicast": "^0.3.5",
|
|
28
28
|
"mri": "^1.2.0",
|
|
29
29
|
"picocolors": "^1.1.1",
|
|
30
|
+
"prettier": "^3.6.2",
|
|
30
31
|
"prompts": "^2.4.2",
|
|
31
32
|
"tslib": "^2.5.3",
|
|
32
33
|
"vite": "^6.3.3",
|