create-stackkit-app 0.4.4 → 0.4.5
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/README.md +1 -1
- package/dist/index.js +62 -4
- package/dist/lib/create-project.d.ts +20 -1
- package/dist/lib/create-project.js +133 -48
- package/dist/lib/utils/config-utils.js +56 -1
- package/dist/lib/utils/logger.d.ts +16 -0
- package/dist/lib/utils/logger.js +59 -0
- package/dist/lib/utils/module-utils.js +346 -196
- package/dist/lib/utils/package-utils.js +2 -2
- package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +6 -0
- package/modules/auth/authjs/files/lib/auth-client.ts +11 -0
- package/modules/auth/authjs/files/lib/auth.ts +41 -0
- package/modules/auth/authjs/files/schemas/prisma-schema.prisma +45 -0
- package/modules/auth/authjs/module.json +95 -0
- package/modules/auth/better-auth/files/lib/auth-client.ts +7 -0
- package/modules/auth/better-auth/files/lib/auth.ts +62 -0
- package/modules/auth/better-auth/files/lib/email-service.ts +34 -0
- package/modules/auth/better-auth/files/lib/email-templates.ts +89 -0
- package/modules/auth/better-auth/files/schemas/prisma-schema.prisma +1 -1
- package/modules/auth/better-auth/module.json +164 -27
- package/modules/database/mongoose/files/lib/db.ts +68 -0
- package/modules/database/{mongoose-mongodb → mongoose}/files/models/User.ts +0 -5
- package/modules/database/{mongoose-mongodb → mongoose}/module.json +9 -24
- package/modules/database/prisma/files/lib/prisma.ts +1 -3
- package/modules/database/prisma/files/prisma/schema.prisma +1 -1
- package/modules/database/prisma/files/prisma.config.ts +2 -2
- package/modules/database/prisma/module.json +5 -23
- package/package.json +1 -1
- package/templates/express/.env.example +0 -1
- package/templates/express/package.json +4 -4
- package/templates/express/src/app.ts +2 -2
- package/templates/express/src/features/health/health.controller.ts +18 -0
- package/templates/express/src/features/health/health.route.ts +9 -0
- package/templates/express/src/features/health/health.service.ts +6 -0
- package/templates/nextjs/lib/env.ts +8 -0
- package/templates/nextjs/package.json +7 -7
- package/templates/react-vite/.env.example +1 -2
- package/templates/react-vite/.prettierignore +4 -0
- package/templates/react-vite/.prettierrc +9 -0
- package/templates/react-vite/README.md +22 -0
- package/templates/react-vite/package.json +16 -16
- package/templates/react-vite/src/router.tsx +0 -12
- package/templates/react-vite/vite.config.ts +0 -6
- package/modules/auth/clerk/files/express/auth.ts +0 -7
- package/modules/auth/clerk/files/nextjs/auth-provider.tsx +0 -5
- package/modules/auth/clerk/files/nextjs/middleware.ts +0 -9
- package/modules/auth/clerk/files/react/auth-provider.tsx +0 -15
- package/modules/auth/clerk/module.json +0 -115
- package/modules/database/mongoose-mongodb/files/lib/db.ts +0 -78
- package/templates/express/src/features/auth/auth.controller.ts +0 -48
- package/templates/express/src/features/auth/auth.route.ts +0 -10
- package/templates/express/src/features/auth/auth.service.ts +0 -21
- package/templates/react-vite/src/api/services/user.service.ts +0 -18
- package/templates/react-vite/src/pages/UserProfile.tsx +0 -40
- package/templates/react-vite/src/types/user.d.ts +0 -6
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Interactive wizard helps you choose:
|
|
|
12
12
|
|
|
13
13
|
- **Framework**: Next.js, Express, or React + Vite
|
|
14
14
|
- **Database**: Prisma (PostgreSQL/MongoDB), Mongoose (MongoDB)
|
|
15
|
-
- **Authentication**: Better Auth,
|
|
15
|
+
- **Authentication**: Better Auth, Auth.js
|
|
16
16
|
- **Package manager**: pnpm, npm, or yarn
|
|
17
17
|
|
|
18
18
|
## Quick Start
|
package/dist/index.js
CHANGED
|
@@ -2,15 +2,73 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const create_project_1 = require("./lib/create-project");
|
|
5
|
+
const logger_1 = require("./lib/utils/logger");
|
|
6
|
+
function parseArgs(args) {
|
|
7
|
+
const options = {};
|
|
8
|
+
let projectName;
|
|
9
|
+
for (let i = 0; i < args.length; i++) {
|
|
10
|
+
const arg = args[i];
|
|
11
|
+
if (arg === '--help' || arg === '-h') {
|
|
12
|
+
showHelp();
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
15
|
+
if (arg.startsWith('--')) {
|
|
16
|
+
const key = arg.slice(2);
|
|
17
|
+
if (args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
18
|
+
options[key] = args[i + 1];
|
|
19
|
+
i++;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
options[key] = true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else if (arg.startsWith('-') && arg.length === 2) {
|
|
26
|
+
const key = arg.slice(1);
|
|
27
|
+
if (args[i + 1] && !args[i + 1].startsWith('-')) {
|
|
28
|
+
options[key] = args[i + 1];
|
|
29
|
+
i++;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
options[key] = true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (!projectName) {
|
|
36
|
+
projectName = arg;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { projectName, options };
|
|
40
|
+
}
|
|
41
|
+
function showHelp() {
|
|
42
|
+
logger_1.logger.log(`
|
|
43
|
+
Create StackKit App
|
|
44
|
+
|
|
45
|
+
Usage:
|
|
46
|
+
create-stackkit-app [project-name] [options]
|
|
47
|
+
|
|
48
|
+
Options:
|
|
49
|
+
-f, --framework <framework> Framework: nextjs, express, react-vite
|
|
50
|
+
-d, --database <database> Database: prisma-postgresql, prisma-mongodb, prisma-mysql, prisma-sqlite, mongoose-mongodb, none
|
|
51
|
+
-a, --auth <auth> Auth: better-auth, authjs, none
|
|
52
|
+
-l, --language <language> Language: typescript, javascript
|
|
53
|
+
-p, --package-manager <pm> Package manager: pnpm, npm, yarn, bun
|
|
54
|
+
--skip-install Skip dependency installation
|
|
55
|
+
--no-git Skip git initialization
|
|
56
|
+
-y, --yes Use default options
|
|
57
|
+
-h, --help Show this help
|
|
58
|
+
|
|
59
|
+
Examples:
|
|
60
|
+
create-stackkit-app my-app --framework nextjs --database prisma-postgresql --auth better-auth
|
|
61
|
+
create-stackkit-app --help
|
|
62
|
+
`);
|
|
63
|
+
}
|
|
5
64
|
async function main() {
|
|
6
65
|
const args = process.argv.slice(2);
|
|
7
|
-
const projectName = args
|
|
66
|
+
const { projectName, options } = parseArgs(args);
|
|
8
67
|
try {
|
|
9
|
-
await (0, create_project_1.createProject)(projectName);
|
|
68
|
+
await (0, create_project_1.createProject)(projectName, options);
|
|
10
69
|
}
|
|
11
70
|
catch (error) {
|
|
12
|
-
|
|
13
|
-
console.error("Error:", error.message);
|
|
71
|
+
logger_1.logger.error(`Error: ${error.message}`);
|
|
14
72
|
process.exit(1);
|
|
15
73
|
}
|
|
16
74
|
}
|
|
@@ -1 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
interface CliOptions {
|
|
2
|
+
framework?: string;
|
|
3
|
+
f?: string;
|
|
4
|
+
database?: string;
|
|
5
|
+
d?: string;
|
|
6
|
+
auth?: string;
|
|
7
|
+
a?: string;
|
|
8
|
+
language?: string;
|
|
9
|
+
l?: string;
|
|
10
|
+
packageManager?: string;
|
|
11
|
+
p?: string;
|
|
12
|
+
install?: boolean;
|
|
13
|
+
'skip-install'?: boolean;
|
|
14
|
+
git?: boolean;
|
|
15
|
+
'no-git'?: boolean;
|
|
16
|
+
yes?: boolean;
|
|
17
|
+
y?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function createProject(projectName?: string, options?: CliOptions): Promise<void>;
|
|
20
|
+
export {};
|
|
@@ -8,30 +8,111 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
8
8
|
const child_process_1 = require("child_process");
|
|
9
9
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
10
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
11
|
-
const ora_1 = __importDefault(require("ora"));
|
|
12
11
|
const path_1 = __importDefault(require("path"));
|
|
13
12
|
const validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
14
13
|
const file_utils_1 = require("./utils/file-utils");
|
|
15
14
|
const git_utils_1 = require("./utils/git-utils");
|
|
16
15
|
const js_conversion_1 = require("./utils/js-conversion");
|
|
16
|
+
const logger_1 = require("./utils/logger");
|
|
17
17
|
const module_utils_1 = require("./utils/module-utils");
|
|
18
18
|
const package_utils_1 = require("./utils/package-utils");
|
|
19
|
-
async function createProject(projectName) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
async function createProject(projectName, options) {
|
|
20
|
+
logger_1.logger.newLine();
|
|
21
|
+
logger_1.logger.log(chalk_1.default.bold.cyan("Create StackKit App"));
|
|
22
|
+
logger_1.logger.newLine();
|
|
23
|
+
const config = await getProjectConfig(projectName, options);
|
|
23
24
|
const targetDir = path_1.default.join(process.cwd(), config.projectName);
|
|
24
25
|
if (await fs_extra_1.default.pathExists(targetDir)) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// eslint-disable-next-line no-console
|
|
28
|
-
console.log(chalk_1.default.gray("Please choose a different name or remove the existing directory.\n"));
|
|
26
|
+
logger_1.logger.error(`Directory "${config.projectName}" already exists`);
|
|
27
|
+
logger_1.logger.log(chalk_1.default.gray("Please choose a different name or remove the existing directory.\n"));
|
|
29
28
|
process.exit(1);
|
|
30
29
|
}
|
|
31
|
-
await generateProject(config, targetDir);
|
|
30
|
+
await generateProject(config, targetDir, options);
|
|
32
31
|
showNextSteps(config);
|
|
33
32
|
}
|
|
34
|
-
async function getProjectConfig(projectName) {
|
|
33
|
+
async function getProjectConfig(projectName, options) {
|
|
34
|
+
if (options && Object.keys(options).length > 0) {
|
|
35
|
+
if (options.yes || options.y) {
|
|
36
|
+
return {
|
|
37
|
+
projectName: projectName || "my-app",
|
|
38
|
+
framework: "nextjs",
|
|
39
|
+
database: "prisma",
|
|
40
|
+
dbProvider: "postgresql",
|
|
41
|
+
auth: "better-auth",
|
|
42
|
+
language: "typescript",
|
|
43
|
+
packageManager: "pnpm",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Validate options
|
|
47
|
+
const validFrameworks = ['nextjs', 'express', 'react-vite'];
|
|
48
|
+
const framework = options.framework || options.f;
|
|
49
|
+
if (framework && !validFrameworks.includes(framework)) {
|
|
50
|
+
throw new Error(`Invalid framework: ${framework}. Valid options: ${validFrameworks.join(', ')}`);
|
|
51
|
+
}
|
|
52
|
+
const validDatabases = ['prisma-postgresql', 'prisma-mongodb', 'prisma-mysql', 'prisma-sqlite', 'mongoose-mongodb', 'none'];
|
|
53
|
+
const db = options.database || options.d;
|
|
54
|
+
if (db && !validDatabases.includes(db)) {
|
|
55
|
+
throw new Error(`Invalid database: ${db}. Valid options: ${validDatabases.join(', ')}`);
|
|
56
|
+
}
|
|
57
|
+
const validAuth = ['better-auth', 'authjs', 'none'];
|
|
58
|
+
const authOpt = options.auth || options.a;
|
|
59
|
+
if (authOpt && !validAuth.includes(authOpt)) {
|
|
60
|
+
throw new Error(`Invalid auth: ${authOpt}. Valid options: ${validAuth.join(', ')}`);
|
|
61
|
+
}
|
|
62
|
+
const validLanguages = ['typescript', 'javascript'];
|
|
63
|
+
const language = options.language || options.l;
|
|
64
|
+
if (language && !validLanguages.includes(language)) {
|
|
65
|
+
throw new Error(`Invalid language: ${language}. Valid options: ${validLanguages.join(', ')}`);
|
|
66
|
+
}
|
|
67
|
+
const validPackageManagers = ['pnpm', 'npm', 'yarn', 'bun'];
|
|
68
|
+
const pm = options.packageManager || options.p;
|
|
69
|
+
if (pm && !validPackageManagers.includes(pm)) {
|
|
70
|
+
throw new Error(`Invalid package manager: ${pm}. Valid options: ${validPackageManagers.join(', ')}`);
|
|
71
|
+
}
|
|
72
|
+
let database = "none";
|
|
73
|
+
let dbProvider;
|
|
74
|
+
if (db && db !== "none") {
|
|
75
|
+
if (db.startsWith("prisma-")) {
|
|
76
|
+
database = "prisma";
|
|
77
|
+
const provider = db.split("-")[1];
|
|
78
|
+
if (!["postgresql", "mongodb", "mysql", "sqlite"].includes(provider)) {
|
|
79
|
+
throw new Error(`Invalid Prisma provider: ${provider}`);
|
|
80
|
+
}
|
|
81
|
+
dbProvider = provider;
|
|
82
|
+
}
|
|
83
|
+
else if (db === "mongoose-mongodb") {
|
|
84
|
+
database = "mongoose";
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
throw new Error(`Unsupported database: ${db}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
let auth = "none";
|
|
91
|
+
if (authOpt && authOpt !== "none") {
|
|
92
|
+
auth = authOpt;
|
|
93
|
+
}
|
|
94
|
+
const finalFramework = (framework || "nextjs");
|
|
95
|
+
if (finalFramework === "react-vite") {
|
|
96
|
+
database = "none";
|
|
97
|
+
dbProvider = undefined;
|
|
98
|
+
}
|
|
99
|
+
// Validate auth compatibility
|
|
100
|
+
if (auth === "authjs" && (database !== "prisma" || finalFramework !== "nextjs")) {
|
|
101
|
+
throw new Error("Auth.js is only supported with Next.js and Prisma database");
|
|
102
|
+
}
|
|
103
|
+
if (auth === "better-auth" && database === "none" && finalFramework !== "react-vite") {
|
|
104
|
+
throw new Error("Better Auth requires a database for server frameworks");
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
projectName: projectName || "my-app",
|
|
108
|
+
framework: finalFramework,
|
|
109
|
+
database,
|
|
110
|
+
dbProvider,
|
|
111
|
+
auth,
|
|
112
|
+
language: (language || "typescript"),
|
|
113
|
+
packageManager: (pm || "pnpm"),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
35
116
|
const answers = (await inquirer_1.default.prompt([
|
|
36
117
|
{
|
|
37
118
|
type: "input",
|
|
@@ -67,7 +148,7 @@ async function getProjectConfig(projectName) {
|
|
|
67
148
|
when: (answers) => answers.framework !== "react-vite",
|
|
68
149
|
choices: [
|
|
69
150
|
{ name: "Prisma", value: "prisma" },
|
|
70
|
-
{ name: "Mongoose
|
|
151
|
+
{ name: "Mongoose (MongoDB)", value: "mongoose" },
|
|
71
152
|
{ name: "None", value: "none" },
|
|
72
153
|
],
|
|
73
154
|
},
|
|
@@ -87,32 +168,33 @@ async function getProjectConfig(projectName) {
|
|
|
87
168
|
type: "list",
|
|
88
169
|
name: "auth",
|
|
89
170
|
message: "Select authentication:",
|
|
90
|
-
when: (answers) => answers.database !== "none" || answers.framework === "react-vite",
|
|
171
|
+
when: (answers) => (answers.database !== "none" || answers.framework === "react-vite") && answers.database !== "mongoose",
|
|
91
172
|
choices: (answers) => {
|
|
92
173
|
if (answers.framework === "react-vite") {
|
|
93
174
|
return [
|
|
94
175
|
{ name: "Better Auth", value: "better-auth" },
|
|
95
|
-
{ name: "Clerk", value: "clerk" },
|
|
96
176
|
{ name: "None", value: "none" },
|
|
97
177
|
];
|
|
98
178
|
}
|
|
99
|
-
|
|
100
|
-
|
|
179
|
+
if (answers.database === "mongoose") {
|
|
180
|
+
return [
|
|
181
|
+
{ name: "Better Auth", value: "better-auth" },
|
|
182
|
+
{ name: "None", value: "none" },
|
|
183
|
+
];
|
|
184
|
+
}
|
|
185
|
+
if (answers.framework === "nextjs" && answers.database === "prisma") {
|
|
101
186
|
return [
|
|
102
187
|
{ name: "Better Auth", value: "better-auth" },
|
|
103
|
-
{ name: "
|
|
188
|
+
{ name: "Auth.js", value: "authjs" },
|
|
104
189
|
{ name: "None", value: "none" },
|
|
105
190
|
];
|
|
106
191
|
}
|
|
107
|
-
|
|
108
|
-
if (answers.framework === "express") {
|
|
192
|
+
if (answers.framework === "express" && answers.database === "prisma") {
|
|
109
193
|
return [
|
|
110
194
|
{ name: "Better Auth", value: "better-auth" },
|
|
111
|
-
{ name: "Clerk", value: "clerk" },
|
|
112
195
|
{ name: "None", value: "none" },
|
|
113
196
|
];
|
|
114
197
|
}
|
|
115
|
-
// Default - no auth
|
|
116
198
|
return [{ name: "None", value: "none" }];
|
|
117
199
|
},
|
|
118
200
|
},
|
|
@@ -146,13 +228,13 @@ async function getProjectConfig(projectName) {
|
|
|
146
228
|
? "none"
|
|
147
229
|
: answers.database),
|
|
148
230
|
dbProvider: answers.dbProvider,
|
|
149
|
-
auth: answers.auth || "none",
|
|
231
|
+
auth: answers.database === "mongoose" ? "better-auth" : (answers.auth || "none"),
|
|
150
232
|
language: answers.language,
|
|
151
233
|
packageManager: answers.packageManager,
|
|
152
234
|
};
|
|
153
235
|
}
|
|
154
|
-
async function generateProject(config, targetDir) {
|
|
155
|
-
const copySpinner =
|
|
236
|
+
async function generateProject(config, targetDir, options) {
|
|
237
|
+
const copySpinner = logger_1.logger.startSpinner("Creating project files...");
|
|
156
238
|
let postInstallCommands = [];
|
|
157
239
|
try {
|
|
158
240
|
postInstallCommands = await composeTemplate(config, targetDir);
|
|
@@ -163,18 +245,20 @@ async function generateProject(config, targetDir) {
|
|
|
163
245
|
throw error;
|
|
164
246
|
}
|
|
165
247
|
// Install dependencies
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
248
|
+
if (options?.install !== false && !options?.['skip-install']) {
|
|
249
|
+
const installSpinner = logger_1.logger.startSpinner("Installing dependencies...");
|
|
250
|
+
try {
|
|
251
|
+
await (0, package_utils_1.installDependencies)(targetDir, config.packageManager);
|
|
252
|
+
installSpinner.succeed("Dependencies installed");
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
installSpinner.fail("Failed to install dependencies");
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
174
258
|
}
|
|
175
259
|
// Run post-install commands
|
|
176
260
|
if (postInstallCommands.length > 0) {
|
|
177
|
-
const postInstallSpinner =
|
|
261
|
+
const postInstallSpinner = logger_1.logger.startSpinner("Running post-install commands...");
|
|
178
262
|
try {
|
|
179
263
|
for (const command of postInstallCommands) {
|
|
180
264
|
(0, child_process_1.execSync)(command, { cwd: targetDir, stdio: "pipe" });
|
|
@@ -187,13 +271,15 @@ async function generateProject(config, targetDir) {
|
|
|
187
271
|
}
|
|
188
272
|
}
|
|
189
273
|
// Initialize git
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
274
|
+
if (options?.git !== false && !options?.['no-git']) {
|
|
275
|
+
const gitSpinner = logger_1.logger.startSpinner("Initializing git repository...");
|
|
276
|
+
try {
|
|
277
|
+
await (0, git_utils_1.initGit)(targetDir);
|
|
278
|
+
gitSpinner.succeed("Git repository initialized");
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
gitSpinner.warn("Failed to initialize git repository");
|
|
282
|
+
}
|
|
197
283
|
}
|
|
198
284
|
}
|
|
199
285
|
async function composeTemplate(config, targetDir) {
|
|
@@ -232,12 +318,11 @@ async function composeTemplate(config, targetDir) {
|
|
|
232
318
|
return postInstallCommands;
|
|
233
319
|
}
|
|
234
320
|
function showNextSteps(config) {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
console.log(chalk_1.default.cyan(` ${config.packageManager} run dev\n`));
|
|
321
|
+
logger_1.logger.newLine();
|
|
322
|
+
logger_1.logger.success(`Created ${config.projectName}`);
|
|
323
|
+
logger_1.logger.newLine();
|
|
324
|
+
logger_1.logger.log("Next steps:");
|
|
325
|
+
logger_1.logger.log(` cd ${config.projectName}`);
|
|
326
|
+
logger_1.logger.log(` ${config.packageManager} run dev`);
|
|
327
|
+
logger_1.logger.newLine();
|
|
243
328
|
}
|
|
@@ -23,11 +23,66 @@ async function applyFrameworkPatches(targetDir, patches) {
|
|
|
23
23
|
for (const [filename, patchConfig] of Object.entries(patches)) {
|
|
24
24
|
const filePath = (0, path_1.join)(targetDir, filename);
|
|
25
25
|
if (await fs_extra_1.default.pathExists(filePath)) {
|
|
26
|
-
const fileContent = await fs_extra_1.default.readJson(filePath);
|
|
27
26
|
if (patchConfig && typeof patchConfig === "object" && "merge" in patchConfig) {
|
|
27
|
+
const fileContent = await fs_extra_1.default.readJson(filePath);
|
|
28
28
|
const merged = deepMerge(fileContent, patchConfig.merge);
|
|
29
29
|
await fs_extra_1.default.writeJson(filePath, merged, { spaces: 2 });
|
|
30
30
|
}
|
|
31
|
+
else if (patchConfig && typeof patchConfig === "object" && "replace" in patchConfig) {
|
|
32
|
+
let fileContent = await fs_extra_1.default.readFile(filePath, "utf-8");
|
|
33
|
+
const replaceConfig = patchConfig;
|
|
34
|
+
for (const [oldStr, newStr] of Object.entries(replaceConfig.replace)) {
|
|
35
|
+
fileContent = fileContent.replace(new RegExp(oldStr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), newStr);
|
|
36
|
+
}
|
|
37
|
+
await fs_extra_1.default.writeFile(filePath, fileContent);
|
|
38
|
+
}
|
|
39
|
+
else if (patchConfig &&
|
|
40
|
+
typeof patchConfig === "object" &&
|
|
41
|
+
("operations" in patchConfig ||
|
|
42
|
+
("type" in patchConfig && patchConfig.type === "patch-file"))) {
|
|
43
|
+
let fileContent = await fs_extra_1.default.readFile(filePath, "utf-8");
|
|
44
|
+
const operations = patchConfig.operations;
|
|
45
|
+
for (const operation of operations) {
|
|
46
|
+
if (operation && typeof operation === "object" && "type" in operation) {
|
|
47
|
+
const op = operation;
|
|
48
|
+
if (op.type === "add-import" && "imports" in op && Array.isArray(op.imports)) {
|
|
49
|
+
const imports = op.imports;
|
|
50
|
+
// Add imports at the top after existing imports
|
|
51
|
+
const importLines = imports.join("\n");
|
|
52
|
+
// Find the last import statement
|
|
53
|
+
const lines = fileContent.split("\n");
|
|
54
|
+
let lastImportIndex = -1;
|
|
55
|
+
for (let i = 0; i < lines.length; i++) {
|
|
56
|
+
if (lines[i].trim().startsWith("import")) {
|
|
57
|
+
lastImportIndex = i;
|
|
58
|
+
}
|
|
59
|
+
else if (lines[i].trim() !== "" && !lines[i].trim().startsWith("//")) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (lastImportIndex >= 0) {
|
|
64
|
+
lines.splice(lastImportIndex + 1, 0, "", importLines);
|
|
65
|
+
fileContent = lines.join("\n");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (op.type === "add-code" && "after" in op && "code" in op) {
|
|
69
|
+
const after = op.after;
|
|
70
|
+
const code = op.code;
|
|
71
|
+
const afterIndex = fileContent.indexOf(after);
|
|
72
|
+
if (afterIndex >= 0) {
|
|
73
|
+
const insertPos = afterIndex + after.length;
|
|
74
|
+
fileContent = fileContent.slice(0, insertPos) + code + fileContent.slice(insertPos);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else if (op.type === "replace" && "oldString" in op && "newString" in op) {
|
|
78
|
+
const oldString = op.oldString;
|
|
79
|
+
const newString = op.newString;
|
|
80
|
+
fileContent = fileContent.replace(oldString, newString);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
await fs_extra_1.default.writeFile(filePath, fileContent);
|
|
85
|
+
}
|
|
31
86
|
}
|
|
32
87
|
}
|
|
33
88
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Ora } from "ora";
|
|
2
|
+
export declare class Logger {
|
|
3
|
+
private spinner;
|
|
4
|
+
info(message: string): void;
|
|
5
|
+
success(message: string): void;
|
|
6
|
+
error(message: string): void;
|
|
7
|
+
warn(message: string): void;
|
|
8
|
+
log(message: string): void;
|
|
9
|
+
newLine(): void;
|
|
10
|
+
startSpinner(text: string): Ora;
|
|
11
|
+
stopSpinner(success?: boolean, text?: string): void;
|
|
12
|
+
updateSpinner(text: string): void;
|
|
13
|
+
header(text: string): void;
|
|
14
|
+
footer(): void;
|
|
15
|
+
}
|
|
16
|
+
export declare const logger: Logger;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.logger = exports.Logger = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
class Logger {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.spinner = null;
|
|
12
|
+
}
|
|
13
|
+
info(message) {
|
|
14
|
+
process.stdout.write(chalk_1.default.blue("ℹ") + " " + message + "\n");
|
|
15
|
+
}
|
|
16
|
+
success(message) {
|
|
17
|
+
process.stdout.write(chalk_1.default.green("✔") + " " + message + "\n");
|
|
18
|
+
}
|
|
19
|
+
error(message) {
|
|
20
|
+
process.stderr.write(chalk_1.default.red("✖") + " " + message + "\n");
|
|
21
|
+
}
|
|
22
|
+
warn(message) {
|
|
23
|
+
process.stdout.write(chalk_1.default.yellow("⚠") + " " + message + "\n");
|
|
24
|
+
}
|
|
25
|
+
log(message) {
|
|
26
|
+
process.stdout.write(message + "\n");
|
|
27
|
+
}
|
|
28
|
+
newLine() {
|
|
29
|
+
process.stdout.write("\n");
|
|
30
|
+
}
|
|
31
|
+
startSpinner(text) {
|
|
32
|
+
this.spinner = (0, ora_1.default)(text).start();
|
|
33
|
+
return this.spinner;
|
|
34
|
+
}
|
|
35
|
+
stopSpinner(success = true, text) {
|
|
36
|
+
if (this.spinner) {
|
|
37
|
+
if (success) {
|
|
38
|
+
this.spinner.succeed(text);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
this.spinner.fail(text);
|
|
42
|
+
}
|
|
43
|
+
this.spinner = null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
updateSpinner(text) {
|
|
47
|
+
if (this.spinner) {
|
|
48
|
+
this.spinner.text = text;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
header(text) {
|
|
52
|
+
process.stdout.write(chalk_1.default.bold.cyan(text) + "\n");
|
|
53
|
+
}
|
|
54
|
+
footer() {
|
|
55
|
+
process.stdout.write("\n");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.Logger = Logger;
|
|
59
|
+
exports.logger = new Logger();
|