@svton/cli 1.0.5 → 1.0.7
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/index.js +148 -75
- package/dist/index.mjs +148 -75
- package/package.json +1 -2
- package/templates/apps/admin/next-env.d.ts +0 -2
- package/templates/apps/admin/next.config.js +0 -15
- package/templates/apps/admin/package.json.tpl +0 -54
- package/templates/apps/admin/postcss.config.js +0 -6
- package/templates/apps/admin/src/app/globals.css +0 -37
- package/templates/apps/admin/src/app/layout.tsx +0 -19
- package/templates/apps/admin/src/app/login/page.tsx +0 -96
- package/templates/apps/admin/src/app/page.tsx +0 -8
- package/templates/apps/admin/src/app/users/page.tsx +0 -165
- package/templates/apps/admin/src/components/ui/switch.tsx +0 -29
- package/templates/apps/admin/src/hooks/useAPI.ts +0 -130
- package/templates/apps/admin/src/lib/api-client.ts +0 -100
- package/templates/apps/admin/tailwind.config.js +0 -54
- package/templates/apps/admin/tsconfig.json +0 -22
- package/templates/apps/backend/.env.example +0 -14
- package/templates/apps/backend/nest-cli.json +0 -8
- package/templates/apps/backend/package.json.tpl +0 -57
- package/templates/apps/backend/prisma/schema.prisma +0 -72
- package/templates/apps/backend/prisma/seed.ts +0 -32
- package/templates/apps/backend/src/app.controller.ts +0 -15
- package/templates/apps/backend/src/app.module.ts +0 -19
- package/templates/apps/backend/src/app.service.ts +0 -12
- package/templates/apps/backend/src/auth/auth.controller.ts +0 -31
- package/templates/apps/backend/src/auth/auth.module.ts +0 -27
- package/templates/apps/backend/src/auth/auth.service.ts +0 -89
- package/templates/apps/backend/src/auth/jwt-auth.guard.ts +0 -5
- package/templates/apps/backend/src/auth/jwt.strategy.ts +0 -27
- package/templates/apps/backend/src/main.ts +0 -40
- package/templates/apps/backend/src/prisma/prisma.module.ts +0 -9
- package/templates/apps/backend/src/prisma/prisma.service.ts +0 -13
- package/templates/apps/backend/src/user/user.controller.ts +0 -50
- package/templates/apps/backend/src/user/user.module.ts +0 -12
- package/templates/apps/backend/src/user/user.service.ts +0 -117
- package/templates/apps/backend/tsconfig.json +0 -23
- package/templates/apps/mobile/babel.config.js +0 -8
- package/templates/apps/mobile/config/index.ts +0 -65
- package/templates/apps/mobile/package.json.tpl +0 -48
- package/templates/apps/mobile/project.config.json.tpl +0 -17
- package/templates/apps/mobile/src/app.config.ts +0 -9
- package/templates/apps/mobile/src/app.scss +0 -4
- package/templates/apps/mobile/src/app.ts +0 -8
- package/templates/apps/mobile/src/pages/index/index.scss +0 -7
- package/templates/apps/mobile/src/pages/index/index.tsx +0 -49
- package/templates/apps/mobile/tsconfig.json +0 -21
- package/templates/packages/types/package.json.tpl +0 -16
- package/templates/packages/types/src/api.ts +0 -88
- package/templates/packages/types/src/common.ts +0 -89
- package/templates/packages/types/src/index.ts +0 -3
- package/templates/packages/types/tsconfig.json +0 -16
package/dist/index.mjs
CHANGED
|
@@ -13,12 +13,12 @@ import { Command } from "commander";
|
|
|
13
13
|
import inquirer from "inquirer";
|
|
14
14
|
import chalk2 from "chalk";
|
|
15
15
|
import ora from "ora";
|
|
16
|
-
import
|
|
17
|
-
import
|
|
16
|
+
import fs4 from "fs-extra";
|
|
17
|
+
import path3 from "path";
|
|
18
18
|
import validateNpmPackageName from "validate-npm-package-name";
|
|
19
19
|
|
|
20
20
|
// src/utils/template.ts
|
|
21
|
-
import
|
|
21
|
+
import fs3 from "fs-extra";
|
|
22
22
|
|
|
23
23
|
// src/utils/logger.ts
|
|
24
24
|
import chalk from "chalk";
|
|
@@ -43,22 +43,84 @@ var logger = {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
// src/utils/copy-template.ts
|
|
46
|
+
import fs2 from "fs-extra";
|
|
47
|
+
import path2 from "path";
|
|
48
|
+
|
|
49
|
+
// src/utils/github-template.ts
|
|
46
50
|
import fs from "fs-extra";
|
|
47
51
|
import path from "path";
|
|
52
|
+
import { execSync } from "child_process";
|
|
53
|
+
import os from "os";
|
|
54
|
+
var GITHUB_REPO = "751848178/svton";
|
|
55
|
+
var GITHUB_BRANCH = "main";
|
|
56
|
+
async function downloadTemplateFromGitHub(options = {}) {
|
|
57
|
+
const repo = options.repo || GITHUB_REPO;
|
|
58
|
+
const branch = options.branch || GITHUB_BRANCH;
|
|
59
|
+
const tempDir = path.join(os.tmpdir(), `svton-template-${Date.now()}`);
|
|
60
|
+
const archiveUrl = `https://github.com/${repo}/archive/refs/heads/${branch}.tar.gz`;
|
|
61
|
+
logger.debug(`Downloading template from GitHub: ${archiveUrl}`);
|
|
62
|
+
try {
|
|
63
|
+
await fs.ensureDir(tempDir);
|
|
64
|
+
const tarFile = path.join(tempDir, "template.tar.gz");
|
|
65
|
+
execSync(`curl -sL "${archiveUrl}" -o "${tarFile}"`, {
|
|
66
|
+
stdio: "pipe"
|
|
67
|
+
});
|
|
68
|
+
execSync(`tar -xzf "${tarFile}" -C "${tempDir}"`, {
|
|
69
|
+
stdio: "pipe"
|
|
70
|
+
});
|
|
71
|
+
await fs.remove(tarFile);
|
|
72
|
+
const repoName = repo.split("/")[1];
|
|
73
|
+
const extractedDir = path.join(tempDir, `${repoName}-${branch}`);
|
|
74
|
+
const templateDir = path.join(extractedDir, "templates");
|
|
75
|
+
if (await fs.pathExists(templateDir)) {
|
|
76
|
+
logger.debug(`Template downloaded to: ${templateDir}`);
|
|
77
|
+
return templateDir;
|
|
78
|
+
}
|
|
79
|
+
throw new Error("Templates directory not found in downloaded repository");
|
|
80
|
+
} catch (error) {
|
|
81
|
+
await fs.remove(tempDir).catch(() => {
|
|
82
|
+
});
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function cleanupTemplateDir(templateDir) {
|
|
87
|
+
try {
|
|
88
|
+
const tempRoot = path.dirname(path.dirname(templateDir));
|
|
89
|
+
if (tempRoot.includes("svton-template-")) {
|
|
90
|
+
await fs.remove(tempRoot);
|
|
91
|
+
logger.debug(`Cleaned up temp directory: ${tempRoot}`);
|
|
92
|
+
}
|
|
93
|
+
} catch (error) {
|
|
94
|
+
logger.debug(`Failed to cleanup temp directory: ${error}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/utils/copy-template.ts
|
|
48
99
|
async function copyTemplateFiles(config) {
|
|
49
100
|
const { template, projectPath } = config;
|
|
50
|
-
|
|
51
|
-
let
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
101
|
+
let templateDir = null;
|
|
102
|
+
let needCleanup = false;
|
|
103
|
+
const cliPackageRoot = path2.dirname(__dirname);
|
|
104
|
+
const frameworkRoot = path2.dirname(path2.dirname(cliPackageRoot));
|
|
105
|
+
const localTemplateDir = path2.join(frameworkRoot, "templates");
|
|
106
|
+
if (await fs2.pathExists(localTemplateDir)) {
|
|
107
|
+
templateDir = localTemplateDir;
|
|
108
|
+
logger.debug(`Using local template directory: ${templateDir}`);
|
|
55
109
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
110
|
+
if (!templateDir) {
|
|
111
|
+
logger.info("Downloading templates from GitHub...");
|
|
112
|
+
try {
|
|
113
|
+
templateDir = await downloadTemplateFromGitHub();
|
|
114
|
+
needCleanup = true;
|
|
115
|
+
logger.info("Templates downloaded successfully");
|
|
116
|
+
} catch (error) {
|
|
117
|
+
logger.warn(`Failed to download templates from GitHub: ${error}`);
|
|
118
|
+
logger.warn("Using built-in minimal templates");
|
|
119
|
+
await copyBuiltInTemplates(config);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
61
122
|
}
|
|
123
|
+
logger.debug(`Copying template files from: ${templateDir}`);
|
|
62
124
|
const originalCwd = process.cwd();
|
|
63
125
|
process.chdir(projectPath);
|
|
64
126
|
try {
|
|
@@ -67,32 +129,35 @@ async function copyTemplateFiles(config) {
|
|
|
67
129
|
await copyBackendTemplate(templateDir, config);
|
|
68
130
|
await copyAdminTemplate(templateDir, config);
|
|
69
131
|
await copyMobileTemplate(templateDir, config);
|
|
70
|
-
await
|
|
132
|
+
await copySharedPackages(templateDir, config);
|
|
71
133
|
break;
|
|
72
134
|
case "backend-only":
|
|
73
135
|
await copyBackendTemplate(templateDir, config);
|
|
74
|
-
await
|
|
136
|
+
await copySharedPackages(templateDir, config);
|
|
75
137
|
break;
|
|
76
138
|
case "admin-only":
|
|
77
139
|
await copyAdminTemplate(templateDir, config);
|
|
78
|
-
await
|
|
140
|
+
await copySharedPackages(templateDir, config);
|
|
79
141
|
break;
|
|
80
142
|
case "mobile-only":
|
|
81
143
|
await copyMobileTemplate(templateDir, config);
|
|
82
|
-
await
|
|
144
|
+
await copySharedPackages(templateDir, config);
|
|
83
145
|
break;
|
|
84
146
|
}
|
|
85
147
|
} finally {
|
|
86
148
|
process.chdir(originalCwd);
|
|
149
|
+
if (needCleanup && templateDir) {
|
|
150
|
+
await cleanupTemplateDir(templateDir);
|
|
151
|
+
}
|
|
87
152
|
}
|
|
88
153
|
}
|
|
89
154
|
async function copyBackendTemplate(sourceDir, config) {
|
|
90
|
-
const sourcePath =
|
|
155
|
+
const sourcePath = path2.join(sourceDir, "apps/backend");
|
|
91
156
|
const destPath = "apps/backend";
|
|
92
|
-
await
|
|
93
|
-
await
|
|
157
|
+
await fs2.ensureDir(destPath);
|
|
158
|
+
await fs2.copy(sourcePath, destPath, {
|
|
94
159
|
filter: (src) => {
|
|
95
|
-
const relativePath =
|
|
160
|
+
const relativePath = path2.relative(sourcePath, src);
|
|
96
161
|
return !relativePath.includes("node_modules") && !relativePath.includes("dist") && !relativePath.includes(".env") && !relativePath.includes(".env.local");
|
|
97
162
|
}
|
|
98
163
|
});
|
|
@@ -100,12 +165,12 @@ async function copyBackendTemplate(sourceDir, config) {
|
|
|
100
165
|
logger.debug("Backend template copied");
|
|
101
166
|
}
|
|
102
167
|
async function copyAdminTemplate(sourceDir, config) {
|
|
103
|
-
const sourcePath =
|
|
168
|
+
const sourcePath = path2.join(sourceDir, "apps/admin");
|
|
104
169
|
const destPath = "apps/admin";
|
|
105
|
-
await
|
|
106
|
-
await
|
|
170
|
+
await fs2.ensureDir(destPath);
|
|
171
|
+
await fs2.copy(sourcePath, destPath, {
|
|
107
172
|
filter: (src) => {
|
|
108
|
-
const relativePath =
|
|
173
|
+
const relativePath = path2.relative(sourcePath, src);
|
|
109
174
|
return !relativePath.includes("node_modules") && !relativePath.includes(".next") && !relativePath.includes(".env.local");
|
|
110
175
|
}
|
|
111
176
|
});
|
|
@@ -113,44 +178,52 @@ async function copyAdminTemplate(sourceDir, config) {
|
|
|
113
178
|
logger.debug("Admin template copied");
|
|
114
179
|
}
|
|
115
180
|
async function copyMobileTemplate(sourceDir, config) {
|
|
116
|
-
const sourcePath =
|
|
181
|
+
const sourcePath = path2.join(sourceDir, "apps/mobile");
|
|
117
182
|
const destPath = "apps/mobile";
|
|
118
|
-
await
|
|
119
|
-
await
|
|
183
|
+
await fs2.ensureDir(destPath);
|
|
184
|
+
await fs2.copy(sourcePath, destPath, {
|
|
120
185
|
filter: (src) => {
|
|
121
|
-
const relativePath =
|
|
186
|
+
const relativePath = path2.relative(sourcePath, src);
|
|
122
187
|
return !relativePath.includes("node_modules") && !relativePath.includes("dist");
|
|
123
188
|
}
|
|
124
189
|
});
|
|
125
190
|
await replacePackageNames(destPath, config);
|
|
126
191
|
logger.debug("Mobile template copied");
|
|
127
192
|
}
|
|
128
|
-
async function
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
await
|
|
132
|
-
await
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
193
|
+
async function copySharedPackages(sourceDir, config) {
|
|
194
|
+
const packagesSourceDir = path2.join(sourceDir, "packages");
|
|
195
|
+
const packagesDestDir = "packages";
|
|
196
|
+
await fs2.ensureDir(packagesDestDir);
|
|
197
|
+
const packages = await fs2.readdir(packagesSourceDir, { withFileTypes: true });
|
|
198
|
+
for (const pkg of packages) {
|
|
199
|
+
if (pkg.isDirectory()) {
|
|
200
|
+
const sourcePath = path2.join(packagesSourceDir, pkg.name);
|
|
201
|
+
const destPath = path2.join(packagesDestDir, pkg.name);
|
|
202
|
+
await fs2.ensureDir(destPath);
|
|
203
|
+
await fs2.copy(sourcePath, destPath, {
|
|
204
|
+
filter: (src) => {
|
|
205
|
+
const relativePath = path2.relative(sourcePath, src);
|
|
206
|
+
return !relativePath.includes("node_modules") && !relativePath.includes("dist");
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
await replacePackageNames(destPath, config);
|
|
210
|
+
logger.debug(`Package ${pkg.name} copied`);
|
|
136
211
|
}
|
|
137
|
-
}
|
|
138
|
-
await replacePackageNames(destPath, config);
|
|
139
|
-
logger.debug("Types package copied");
|
|
212
|
+
}
|
|
140
213
|
}
|
|
141
214
|
async function replacePackageNames(directory, config) {
|
|
142
215
|
const { projectName, orgName } = config;
|
|
143
216
|
const filesToUpdate = await findFilesToUpdate(directory);
|
|
144
217
|
for (const filePath of filesToUpdate) {
|
|
145
218
|
try {
|
|
146
|
-
let content = await
|
|
147
|
-
content = content.replace(/\{\{ORG_NAME\}\}/g, orgName).replace(/\{\{PROJECT_NAME\}\}/g, projectName)
|
|
219
|
+
let content = await fs2.readFile(filePath, "utf8");
|
|
220
|
+
content = content.replace(/\{\{ORG_NAME\}\}/g, orgName).replace(/\{\{PROJECT_NAME\}\}/g, projectName);
|
|
148
221
|
if (filePath.endsWith(".tpl")) {
|
|
149
222
|
const newPath = filePath.replace(/\.tpl$/, "");
|
|
150
|
-
await
|
|
151
|
-
await
|
|
223
|
+
await fs2.writeFile(newPath, content);
|
|
224
|
+
await fs2.remove(filePath);
|
|
152
225
|
} else {
|
|
153
|
-
await
|
|
226
|
+
await fs2.writeFile(filePath, content);
|
|
154
227
|
}
|
|
155
228
|
} catch (error) {
|
|
156
229
|
logger.debug(`Failed to update file ${filePath}: ${error}`);
|
|
@@ -160,13 +233,13 @@ async function replacePackageNames(directory, config) {
|
|
|
160
233
|
async function findFilesToUpdate(directory) {
|
|
161
234
|
const files = [];
|
|
162
235
|
const traverse = async (dir) => {
|
|
163
|
-
const entries = await
|
|
236
|
+
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
164
237
|
for (const entry of entries) {
|
|
165
|
-
const fullPath =
|
|
238
|
+
const fullPath = path2.join(dir, entry.name);
|
|
166
239
|
if (entry.isDirectory()) {
|
|
167
240
|
await traverse(fullPath);
|
|
168
241
|
} else if (entry.isFile()) {
|
|
169
|
-
const ext =
|
|
242
|
+
const ext = path2.extname(entry.name);
|
|
170
243
|
const shouldUpdate = [".json", ".ts", ".tsx", ".js", ".jsx", ".md", ".yaml", ".yml", ".env.example", ".tpl"].includes(ext) || entry.name.endsWith(".tpl");
|
|
171
244
|
if (shouldUpdate) {
|
|
172
245
|
files.push(fullPath);
|
|
@@ -193,7 +266,7 @@ async function copyBuiltInTemplates(config) {
|
|
|
193
266
|
}
|
|
194
267
|
async function createMinimalBackend(config) {
|
|
195
268
|
const dir = "apps/backend";
|
|
196
|
-
await
|
|
269
|
+
await fs2.ensureDir(dir);
|
|
197
270
|
const packageJson = {
|
|
198
271
|
name: `${config.orgName}/backend`,
|
|
199
272
|
version: "1.0.0",
|
|
@@ -218,11 +291,11 @@ async function createMinimalBackend(config) {
|
|
|
218
291
|
"typescript": "^5.3.0"
|
|
219
292
|
}
|
|
220
293
|
};
|
|
221
|
-
await
|
|
294
|
+
await fs2.writeJson(path2.join(dir, "package.json"), packageJson, { spaces: 2 });
|
|
222
295
|
}
|
|
223
296
|
async function createMinimalAdmin(config) {
|
|
224
297
|
const dir = "apps/admin";
|
|
225
|
-
await
|
|
298
|
+
await fs2.ensureDir(dir);
|
|
226
299
|
const packageJson = {
|
|
227
300
|
name: `${config.orgName}/admin`,
|
|
228
301
|
version: "1.0.0",
|
|
@@ -246,11 +319,11 @@ async function createMinimalAdmin(config) {
|
|
|
246
319
|
"typescript": "^5.7.3"
|
|
247
320
|
}
|
|
248
321
|
};
|
|
249
|
-
await
|
|
322
|
+
await fs2.writeJson(path2.join(dir, "package.json"), packageJson, { spaces: 2 });
|
|
250
323
|
}
|
|
251
324
|
async function createMinimalMobile(config) {
|
|
252
325
|
const dir = "apps/mobile";
|
|
253
|
-
await
|
|
326
|
+
await fs2.ensureDir(dir);
|
|
254
327
|
const packageJson = {
|
|
255
328
|
name: `${config.orgName}/mobile`,
|
|
256
329
|
version: "1.0.0",
|
|
@@ -275,13 +348,13 @@ async function createMinimalMobile(config) {
|
|
|
275
348
|
"typescript": "^5.3.3"
|
|
276
349
|
}
|
|
277
350
|
};
|
|
278
|
-
await
|
|
351
|
+
await fs2.writeJson(path2.join(dir, "package.json"), packageJson, { spaces: 2 });
|
|
279
352
|
}
|
|
280
353
|
async function createMinimalTypes(config) {
|
|
281
354
|
const dir = "packages/types";
|
|
282
|
-
await
|
|
355
|
+
await fs2.ensureDir(dir);
|
|
283
356
|
const packageJson = {
|
|
284
|
-
name:
|
|
357
|
+
name: `@${config.orgName}/types`,
|
|
285
358
|
version: "1.0.0",
|
|
286
359
|
description: "Shared type definitions",
|
|
287
360
|
main: "./dist/index.js",
|
|
@@ -296,7 +369,7 @@ async function createMinimalTypes(config) {
|
|
|
296
369
|
"typescript": "^5.3.3"
|
|
297
370
|
}
|
|
298
371
|
};
|
|
299
|
-
await
|
|
372
|
+
await fs2.writeJson(path2.join(dir, "package.json"), packageJson, { spaces: 2 });
|
|
300
373
|
}
|
|
301
374
|
|
|
302
375
|
// src/utils/template.ts
|
|
@@ -339,12 +412,12 @@ async function createRootFiles(config) {
|
|
|
339
412
|
pnpm: ">=8.0.0"
|
|
340
413
|
}
|
|
341
414
|
};
|
|
342
|
-
await
|
|
415
|
+
await fs3.writeJson("package.json", packageJson, { spaces: 2 });
|
|
343
416
|
const workspaceConfig = `packages:
|
|
344
417
|
- 'apps/*'
|
|
345
418
|
- 'packages/*'
|
|
346
419
|
`;
|
|
347
|
-
await
|
|
420
|
+
await fs3.writeFile("pnpm-workspace.yaml", workspaceConfig);
|
|
348
421
|
const turboConfig = {
|
|
349
422
|
"$schema": "https://turbo.build/schema.json",
|
|
350
423
|
pipeline: {
|
|
@@ -368,7 +441,7 @@ async function createRootFiles(config) {
|
|
|
368
441
|
}
|
|
369
442
|
}
|
|
370
443
|
};
|
|
371
|
-
await
|
|
444
|
+
await fs3.writeJson("turbo.json", turboConfig, { spaces: 2 });
|
|
372
445
|
const gitignore = `# Dependencies
|
|
373
446
|
node_modules/
|
|
374
447
|
.pnpm-store/
|
|
@@ -406,11 +479,11 @@ coverage/
|
|
|
406
479
|
# Misc
|
|
407
480
|
*.tsbuildinfo
|
|
408
481
|
`;
|
|
409
|
-
await
|
|
482
|
+
await fs3.writeFile(".gitignore", gitignore);
|
|
410
483
|
const npmrc = `auto-install-peers=true
|
|
411
484
|
strict-peer-dependencies=false
|
|
412
485
|
`;
|
|
413
|
-
await
|
|
486
|
+
await fs3.writeFile(".npmrc", npmrc);
|
|
414
487
|
const dockerCompose = `version: '3.8'
|
|
415
488
|
|
|
416
489
|
services:
|
|
@@ -442,9 +515,9 @@ volumes:
|
|
|
442
515
|
mysql_data:
|
|
443
516
|
redis_data:
|
|
444
517
|
`;
|
|
445
|
-
await
|
|
518
|
+
await fs3.writeFile("docker-compose.yml", dockerCompose);
|
|
446
519
|
const readme = await generateReadme(config);
|
|
447
|
-
await
|
|
520
|
+
await fs3.writeFile("README.md", readme);
|
|
448
521
|
}
|
|
449
522
|
async function generateReadme(config) {
|
|
450
523
|
const { projectName, orgName, template } = config;
|
|
@@ -529,12 +602,12 @@ Generated with \`create-svton-app\`
|
|
|
529
602
|
}
|
|
530
603
|
|
|
531
604
|
// src/utils/install.ts
|
|
532
|
-
import { execSync } from "child_process";
|
|
605
|
+
import { execSync as execSync2 } from "child_process";
|
|
533
606
|
async function installDependencies(packageManager) {
|
|
534
607
|
try {
|
|
535
608
|
const command = getInstallCommand(packageManager);
|
|
536
609
|
logger.debug(`Running: ${command}`);
|
|
537
|
-
|
|
610
|
+
execSync2(command, {
|
|
538
611
|
stdio: "inherit",
|
|
539
612
|
cwd: process.cwd()
|
|
540
613
|
});
|
|
@@ -556,18 +629,18 @@ function getInstallCommand(packageManager) {
|
|
|
556
629
|
}
|
|
557
630
|
|
|
558
631
|
// src/utils/git.ts
|
|
559
|
-
import { execSync as
|
|
632
|
+
import { execSync as execSync3 } from "child_process";
|
|
560
633
|
async function initGit(projectName) {
|
|
561
634
|
try {
|
|
562
635
|
try {
|
|
563
|
-
|
|
636
|
+
execSync3("git status", { stdio: "ignore" });
|
|
564
637
|
logger.debug("Git repository already exists, skipping initialization");
|
|
565
638
|
return;
|
|
566
639
|
} catch {
|
|
567
640
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
641
|
+
execSync3("git init", { stdio: "ignore" });
|
|
642
|
+
execSync3("git add .", { stdio: "ignore" });
|
|
643
|
+
execSync3(`git commit -m "feat: initialize ${projectName} project"`, {
|
|
571
644
|
stdio: "ignore"
|
|
572
645
|
});
|
|
573
646
|
logger.debug("Git repository initialized successfully");
|
|
@@ -588,8 +661,8 @@ async function createProject(projectName, options = {}) {
|
|
|
588
661
|
}
|
|
589
662
|
process.exit(1);
|
|
590
663
|
}
|
|
591
|
-
const projectPath =
|
|
592
|
-
if (await
|
|
664
|
+
const projectPath = path3.resolve(process.cwd(), projectName);
|
|
665
|
+
if (await fs4.pathExists(projectPath)) {
|
|
593
666
|
logger.error(`Directory ${projectName} already exists!`);
|
|
594
667
|
process.exit(1);
|
|
595
668
|
}
|
|
@@ -707,7 +780,7 @@ async function createProject(projectName, options = {}) {
|
|
|
707
780
|
async function createProjectFromTemplate(config) {
|
|
708
781
|
const spinner = ora("Creating project...").start();
|
|
709
782
|
try {
|
|
710
|
-
await
|
|
783
|
+
await fs4.ensureDir(config.projectPath);
|
|
711
784
|
process.chdir(config.projectPath);
|
|
712
785
|
spinner.text = "Generating project files...";
|
|
713
786
|
await generateFromTemplate(config);
|
|
@@ -727,7 +800,7 @@ async function createProjectFromTemplate(config) {
|
|
|
727
800
|
}
|
|
728
801
|
|
|
729
802
|
// package.json
|
|
730
|
-
var version = "1.0.
|
|
803
|
+
var version = "1.0.7";
|
|
731
804
|
|
|
732
805
|
// src/index.ts
|
|
733
806
|
async function cli() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svton/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Svton CLI - Create full-stack applications with NestJS, Next.js, and Taro",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
"files": [
|
|
31
31
|
"dist",
|
|
32
32
|
"bin",
|
|
33
|
-
"templates",
|
|
34
33
|
"README.md",
|
|
35
34
|
"LICENSE"
|
|
36
35
|
],
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/** @type {import('next').NextConfig} */
|
|
2
|
-
const nextConfig = {
|
|
3
|
-
reactStrictMode: true,
|
|
4
|
-
transpilePackages: ['@svton/hooks'],
|
|
5
|
-
images: {
|
|
6
|
-
remotePatterns: [
|
|
7
|
-
{
|
|
8
|
-
protocol: 'https',
|
|
9
|
-
hostname: '**',
|
|
10
|
-
},
|
|
11
|
-
],
|
|
12
|
-
},
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
module.exports = nextConfig;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "{{ORG_NAME}}/admin",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "{{PROJECT_NAME}} 管理后台",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"dev": "next dev -p 3001",
|
|
7
|
-
"build": "next build",
|
|
8
|
-
"start": "next start -p 3001",
|
|
9
|
-
"lint": "next lint",
|
|
10
|
-
"type-check": "tsc --noEmit",
|
|
11
|
-
"clean": "rm -rf .next"
|
|
12
|
-
},
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"@hookform/resolvers": "^3.3.3",
|
|
15
|
-
"@radix-ui/react-avatar": "^1.0.4",
|
|
16
|
-
"@radix-ui/react-dialog": "^1.0.5",
|
|
17
|
-
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
|
18
|
-
"@radix-ui/react-label": "^2.0.2",
|
|
19
|
-
"@radix-ui/react-select": "^2.0.0",
|
|
20
|
-
"@radix-ui/react-separator": "^1.0.3",
|
|
21
|
-
"@radix-ui/react-slot": "^1.0.2",
|
|
22
|
-
"@radix-ui/react-switch": "^1.2.6",
|
|
23
|
-
"@radix-ui/react-tabs": "^1.0.4",
|
|
24
|
-
"@radix-ui/react-toast": "^1.1.5",
|
|
25
|
-
"@svton/api-client": "^1.0.0",
|
|
26
|
-
"@svton/hooks": "^1.0.0",
|
|
27
|
-
"@svton/types": "^1.0.0",
|
|
28
|
-
"axios": "^1.7.9",
|
|
29
|
-
"class-variance-authority": "^0.7.1",
|
|
30
|
-
"clsx": "^2.1.1",
|
|
31
|
-
"dayjs": "^1.11.13",
|
|
32
|
-
"lucide-react": "^0.462.0",
|
|
33
|
-
"next": "^15.0.0",
|
|
34
|
-
"react": "^19.0.0",
|
|
35
|
-
"react-dom": "^19.0.0",
|
|
36
|
-
"react-hook-form": "^7.49.0",
|
|
37
|
-
"swr": "^2.2.5",
|
|
38
|
-
"tailwind-merge": "^3.0.0",
|
|
39
|
-
"zod": "^3.22.4",
|
|
40
|
-
"zustand": "^5.0.0"
|
|
41
|
-
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"@types/node": "^22.0.0",
|
|
44
|
-
"@types/react": "^19.0.0",
|
|
45
|
-
"@types/react-dom": "^19.0.0",
|
|
46
|
-
"autoprefixer": "^10.4.22",
|
|
47
|
-
"eslint": "^9.0.0",
|
|
48
|
-
"eslint-config-next": "^15.0.0",
|
|
49
|
-
"postcss": "^8.5.0",
|
|
50
|
-
"tailwindcss": "^3.4.0",
|
|
51
|
-
"tailwindcss-animate": "^1.0.7",
|
|
52
|
-
"typescript": "^5.7.0"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
@layer base {
|
|
6
|
-
:root {
|
|
7
|
-
--background: 0 0% 100%;
|
|
8
|
-
--foreground: 222.2 84% 4.9%;
|
|
9
|
-
--card: 0 0% 100%;
|
|
10
|
-
--card-foreground: 222.2 84% 4.9%;
|
|
11
|
-
--popover: 0 0% 100%;
|
|
12
|
-
--popover-foreground: 222.2 84% 4.9%;
|
|
13
|
-
--primary: 222.2 47.4% 11.2%;
|
|
14
|
-
--primary-foreground: 210 40% 98%;
|
|
15
|
-
--secondary: 210 40% 96.1%;
|
|
16
|
-
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
17
|
-
--muted: 210 40% 96.1%;
|
|
18
|
-
--muted-foreground: 215.4 16.3% 46.9%;
|
|
19
|
-
--accent: 210 40% 96.1%;
|
|
20
|
-
--accent-foreground: 222.2 47.4% 11.2%;
|
|
21
|
-
--destructive: 0 84.2% 60.2%;
|
|
22
|
-
--destructive-foreground: 210 40% 98%;
|
|
23
|
-
--border: 214.3 31.8% 91.4%;
|
|
24
|
-
--input: 214.3 31.8% 91.4%;
|
|
25
|
-
--ring: 222.2 84% 4.9%;
|
|
26
|
-
--radius: 0.5rem;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
@layer base {
|
|
31
|
-
* {
|
|
32
|
-
@apply border-border;
|
|
33
|
-
}
|
|
34
|
-
body {
|
|
35
|
-
@apply bg-background text-foreground;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { Metadata } from 'next';
|
|
2
|
-
import './globals.css';
|
|
3
|
-
|
|
4
|
-
export const metadata: Metadata = {
|
|
5
|
-
title: '管理后台',
|
|
6
|
-
description: '项目管理后台',
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export default function RootLayout({
|
|
10
|
-
children,
|
|
11
|
-
}: {
|
|
12
|
-
children: React.ReactNode;
|
|
13
|
-
}) {
|
|
14
|
-
return (
|
|
15
|
-
<html lang="zh-CN">
|
|
16
|
-
<body>{children}</body>
|
|
17
|
-
</html>
|
|
18
|
-
);
|
|
19
|
-
}
|