create-init-mtv-app 1.0.2 → 1.0.3

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.
Files changed (2) hide show
  1. package/dist/index.mjs +461 -98
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -8,6 +8,7 @@ import inquirer from "inquirer";
8
8
  let DB_PROVIDERS = /* @__PURE__ */ function(DB_PROVIDERS$1) {
9
9
  DB_PROVIDERS$1["SUPABASE"] = "Supabase";
10
10
  DB_PROVIDERS$1["DOCKER"] = "Docker";
11
+ DB_PROVIDERS$1["NONE"] = "None";
11
12
  return DB_PROVIDERS$1;
12
13
  }({});
13
14
 
@@ -16,6 +17,7 @@ let DB_PROVIDERS = /* @__PURE__ */ function(DB_PROVIDERS$1) {
16
17
  let DB_TOOLS = /* @__PURE__ */ function(DB_TOOLS$1) {
17
18
  DB_TOOLS$1["DRIZZLE_ORM"] = "Drizzle ORM";
18
19
  DB_TOOLS$1["SUPABASE_JS_SDK"] = "Supabase JS SDK";
20
+ DB_TOOLS$1["NONE"] = "None";
19
21
  return DB_TOOLS$1;
20
22
  }({});
21
23
 
@@ -40,8 +42,91 @@ let UI_LIB = /* @__PURE__ */ function(UI_LIB$1) {
40
42
  }({});
41
43
 
42
44
  //#endregion
43
- //#region src/installers/dependencies.ts
44
- async function installDependencies(projectName, dependencies) {
45
+ //#region src/installers/expressjs/expressjs.ts
46
+ async function createExpressApp(projectName) {
47
+ await fs.ensureDir(projectName);
48
+ await execa("npm", ["init", "-y"], {
49
+ cwd: projectName,
50
+ stdio: "inherit"
51
+ });
52
+ const dtosDir = path.join(projectName, "src", "dtos");
53
+ const handlersDir = path.join(projectName, "src", "handlers");
54
+ const repositoriesDir = path.join(projectName, "src", "repositories");
55
+ const servicesDir = path.join(projectName, "src", "services");
56
+ const routesDir = path.join(projectName, "src", "routes");
57
+ const middlewareDir = path.join(projectName, "src", "middleware");
58
+ await Promise.all([
59
+ fs.ensureDir(dtosDir),
60
+ fs.ensureDir(handlersDir),
61
+ fs.ensureDir(repositoriesDir),
62
+ fs.ensureDir(servicesDir),
63
+ fs.ensureDir(routesDir),
64
+ fs.ensureDir(middlewareDir)
65
+ ]);
66
+ const idParamDtoPath = path.join(dtosDir, "idParam.dto.ts");
67
+ const paginationDtoPath = path.join(dtosDir, "pagination.dto.ts");
68
+ const responseDtoPath = path.join(dtosDir, "response.dto.ts");
69
+ await Promise.all([
70
+ fs.ensureFile(idParamDtoPath),
71
+ fs.ensureFile(paginationDtoPath),
72
+ fs.ensureFile(responseDtoPath)
73
+ ]);
74
+ await Promise.all([
75
+ fs.writeFile(idParamDtoPath, idParamDtoTemplate),
76
+ fs.writeFile(paginationDtoPath, paginationDtoTemplate),
77
+ fs.writeFile(responseDtoPath, responseDtoTemplate)
78
+ ]);
79
+ const appFilePath = path.join(projectName, "src", "app.ts");
80
+ const indexFilePath = path.join(projectName, "index.ts");
81
+ await Promise.all([fs.ensureFile(appFilePath), fs.ensureFile(indexFilePath)]);
82
+ await Promise.all([fs.writeFile(appFilePath, appTemplate), fs.writeFile(indexFilePath, indexTemplate)]);
83
+ }
84
+ const appTemplate = `import express from "express";
85
+ import helmet from "helmet";
86
+ import cors from "cors";
87
+ import cookieParser from "cookie-parser";
88
+ import "dotenv/config";
89
+ import swaggerUi from "swagger-ui-express";
90
+ import swaggerDocument from "./swagger.json";
91
+ import morgan from "morgan";
92
+
93
+ const app = express();
94
+ app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument)); // mabe AI will help to generate the json file
95
+ app.use(helmet());
96
+ app.use(cors());
97
+ app.use(express.json());
98
+ app.use(express.urlencoded({ extended: true }));
99
+ app.use(cookieParser());
100
+ app.use(morgan("dev"));
101
+
102
+ app.get("/health", (_req, res) => {
103
+ res.json({ status: "ok" });
104
+ });
105
+
106
+ export default app;`;
107
+ const indexTemplate = `import app from "./src/app";
108
+
109
+ const port = process.env.PORT || 8080;
110
+ app.listen(port, () => {
111
+ console.log(\`Server is running on port \${ port }\`);
112
+ });`;
113
+ const idParamDtoTemplate = `export type IdParam = {
114
+ id: string;
115
+ };`;
116
+ const paginationDtoTemplate = `export type Pagination = {
117
+ page: number;
118
+ limit: number;
119
+ };`;
120
+ const responseDtoTemplate = `export type Response<T> = {
121
+ data?: T;
122
+ message: string;
123
+ statusCode: number;
124
+ success: boolean;
125
+ };`;
126
+
127
+ //#endregion
128
+ //#region src/installers/expressjs/dependencies.ts
129
+ async function installDependencies$1(projectName, dependencies) {
45
130
  await execa("npm", ["install", ...dependencies], {
46
131
  cwd: projectName,
47
132
  stdio: "inherit"
@@ -49,8 +134,8 @@ async function installDependencies(projectName, dependencies) {
49
134
  }
50
135
 
51
136
  //#endregion
52
- //#region src/installers/devDependencies.ts
53
- async function installDevDependencies(projectName, devDependencies) {
137
+ //#region src/installers/expressjs/devDependencies.ts
138
+ async function installDevDependencies$1(projectName, devDependencies) {
54
139
  await execa("npm", [
55
140
  "install",
56
141
  "-D",
@@ -62,19 +147,12 @@ async function installDevDependencies(projectName, devDependencies) {
62
147
  }
63
148
 
64
149
  //#endregion
65
- //#region src/installers/nexjs.ts
66
- async function createNextApp(projectName) {
150
+ //#region src/installers/nestjs.ts
151
+ async function createNestApp(projectName) {
67
152
  await execa("npx", [
68
- "create-next-app@latest",
69
- projectName,
70
- "--ts",
71
- "--tailwind",
72
- "--react-compiler",
73
- "--biome",
74
- "--app",
75
- "--src-dir",
76
- "--import-alias",
77
- "@/*"
153
+ "@nestjs/cli",
154
+ "new",
155
+ projectName
78
156
  ], { stdio: "inherit" });
79
157
  }
80
158
 
@@ -92,27 +170,7 @@ async function createReactApp(projectName) {
92
170
  }
93
171
 
94
172
  //#endregion
95
- //#region src/installers/expressjs.ts
96
- async function createNextExpressApp(projectName) {
97
- await execa("npx", [
98
- "create-next-app@latest",
99
- projectName,
100
- "--use-npm"
101
- ], { stdio: "inherit" });
102
- }
103
-
104
- //#endregion
105
- //#region src/installers/nestjs.ts
106
- async function createNestApp(projectName) {
107
- await execa("npx", [
108
- "@nestjs/cli",
109
- "new",
110
- projectName
111
- ], { stdio: "inherit" });
112
- }
113
-
114
- //#endregion
115
- //#region src/setups/husky_lint-staged.ts
173
+ //#region src/configs/husky_lint-staged.ts
116
174
  async function setupHuskyLintStaged(projectName) {
117
175
  const preCommitPath = path.join(projectName, ".husky", "pre-commit");
118
176
  const prePushPath = path.join(projectName, ".husky", "pre-push");
@@ -121,24 +179,27 @@ async function setupHuskyLintStaged(projectName) {
121
179
  const packageJsonPath = path.join(projectName, "package.json");
122
180
  const packageJson = await fs.readJson(packageJsonPath);
123
181
  packageJson["lint-staged"] = { "*.{ts,tsx,js,jsx,json,css}": ["npm run format", "npm run lint"] };
182
+ packageJson.scripts["prepare"] = "husky";
183
+ packageJson.scripts["lint"] = "biome check";
184
+ packageJson.scripts["format"] = "biome format --write";
124
185
  await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
125
186
  }
126
187
 
127
188
  //#endregion
128
- //#region src/setups/next_supabase_client.ts
129
- async function setupNextSupabaseClient(projectDir) {
189
+ //#region src/configs/nextjs/supabase_client.ts
190
+ async function setupSupabaseClient(projectDir) {
130
191
  const supabaseDir = path.join(projectDir, "src", "lib", "supabase");
131
192
  await fs.ensureDir(supabaseDir);
132
193
  const supabaseClientPath = path.join(supabaseDir, "client.ts");
133
194
  const supabaseServerPath = path.join(supabaseDir, "server.ts");
134
195
  const supabaseAdminPath = path.join(supabaseDir, "admin.ts");
135
196
  await Promise.all([
136
- fs.writeFile(supabaseClientPath, supabaseClientTemplate),
197
+ fs.writeFile(supabaseClientPath, supabaseClientTemplate$1),
137
198
  fs.writeFile(supabaseServerPath, supabaseServerTemplate),
138
- fs.writeFile(supabaseAdminPath, supabaseAdminTemplate)
199
+ fs.writeFile(supabaseAdminPath, supabaseAdminTemplate$1)
139
200
  ]);
140
201
  }
141
- const supabaseClientTemplate = `import { createBrowserClient } from "@supabase/ssr";
202
+ const supabaseClientTemplate$1 = `import { createBrowserClient } from "@supabase/ssr";
142
203
  import { sharedEnv } from "../../../env.shared";
143
204
 
144
205
  export function createClient() {
@@ -177,7 +238,7 @@ export async function createClient() {
177
238
  );
178
239
  }
179
240
  `.trimStart();
180
- const supabaseAdminTemplate = `import "server-only";
241
+ const supabaseAdminTemplate$1 = `import "server-only";
181
242
  import { createClient } from "@supabase/supabase-js";
182
243
  import { serverEnv } from "@/backend/env.server";
183
244
  import { sharedEnv } from "../../../env.shared";
@@ -196,8 +257,8 @@ export function createAdminClient() {
196
257
  `.trimStart();
197
258
 
198
259
  //#endregion
199
- //#region src/setups/next_env.ts
200
- async function setupNextEnv(projectName, isSupabase = false) {
260
+ //#region src/configs/nextjs/env.ts
261
+ async function setupEnv(projectName, isSupabase = false) {
201
262
  const sharedEnvPath = path.join(projectName, "env.shared.ts");
202
263
  const backendDir = path.join(projectName, "src", "backend");
203
264
  const serverEnvPath = path.join(backendDir, "env.server.ts");
@@ -252,7 +313,7 @@ export const sharedEnv = parsed.data;
252
313
  `.trimStart();
253
314
 
254
315
  //#endregion
255
- //#region src/setups/drizzle.ts
316
+ //#region src/configs/nextjs/drizzle.ts
256
317
  async function setupDrizzle(projectName) {
257
318
  const schemasDir = path.join(projectName, "src", "backend", "db", "schemas");
258
319
  const migrationsDir = path.join(projectName, "src", "backend", "db", "migrations");
@@ -262,7 +323,7 @@ async function setupDrizzle(projectName) {
262
323
  fs.ensureDir(migrationsDir),
263
324
  fs.ensureFile(drizzleConfigPath)
264
325
  ]);
265
- await fs.writeFile(drizzleConfigPath, drizzleConfigTemplate);
326
+ await fs.writeFile(drizzleConfigPath, drizzleConfigTemplate$1);
266
327
  const packageJsonPath = path.join(projectName, "package.json");
267
328
  const packageJson = await fs.readJson(packageJsonPath);
268
329
  packageJson.scripts["db:generate"] = "npx drizzle-kit generate --config=./src/backend/db/drizzle.config.ts";
@@ -272,7 +333,7 @@ async function setupDrizzle(projectName) {
272
333
  packageJson.scripts["db:check"] = "npx drizzle-kit check --config=./src/backend/db/drizzle.config.ts";
273
334
  await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
274
335
  }
275
- const drizzleConfigTemplate = `import "server-only";
336
+ const drizzleConfigTemplate$1 = `import "server-only";
276
337
  import { defineConfig } from "drizzle-kit";
277
338
  import { serverEnv } from "../env.server";
278
339
 
@@ -283,15 +344,19 @@ export default defineConfig({
283
344
  dbCredentials: {
284
345
  url: serverEnv.DATABASE_URL,
285
346
  },
347
+ verbose: true,
348
+ strict: true
286
349
  });
287
350
  `.trimStart();
288
351
 
289
352
  //#endregion
290
- //#region src/setups/shadcn.ts
353
+ //#region src/configs/nextjs/shadcn.ts
291
354
  async function setupShadcn(projectName) {
292
355
  await execa("npx", [
293
356
  "shadcn@latest",
294
357
  "init",
358
+ "-b",
359
+ "neutral",
295
360
  "dialog",
296
361
  "avatar",
297
362
  "button-group",
@@ -319,7 +384,7 @@ async function setupShadcn(projectName) {
319
384
  }
320
385
 
321
386
  //#endregion
322
- //#region src/setups/biome.ts
387
+ //#region src/configs/nextjs/biome.ts
323
388
  async function setupBiome(projectName, isShadcn) {
324
389
  const biomePath = path.join(projectName, "biome.json");
325
390
  const biomeConfig = await fs.readJson(biomePath);
@@ -330,9 +395,9 @@ async function setupBiome(projectName, isShadcn) {
330
395
  }
331
396
 
332
397
  //#endregion
333
- //#region src/setups/next_supabase_local.ts
334
- async function setupNextSupabaseLocal(projectDir) {
335
- execa("npx", ["supabase", "init"], {
398
+ //#region src/configs/nextjs/supabase_local.ts
399
+ async function setupSupabaseLocal(projectDir) {
400
+ await execa("npx", ["supabase", "init"], {
336
401
  cwd: projectDir,
337
402
  stdio: "inherit"
338
403
  });
@@ -345,21 +410,22 @@ async function setupNextSupabaseLocal(projectDir) {
345
410
  }
346
411
 
347
412
  //#endregion
348
- //#region src/setups/jest.ts
413
+ //#region src/configs/nextjs/jest.ts
349
414
  async function setupJest(projectName) {
350
415
  const jestConfigPath = path.join(projectName, "jest.config.ts");
351
416
  await fs.ensureFile(jestConfigPath);
352
- await fs.writeFile(jestConfigPath, jestConfigTemplate);
417
+ await fs.writeFile(jestConfigPath, jestConfigTemplate$1);
353
418
  const packageJsonPath = path.join(projectName, "package.json");
354
419
  const packageJson = await fs.readJson(packageJsonPath);
355
420
  packageJson.scripts["test:unit"] = "jest --testPathPatterns=unit";
356
421
  packageJson.scripts["test:integration"] = "jest --testPathPatterns=integration";
422
+ packageJson.scripts["test"] = "jest";
357
423
  await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
358
424
  const testUnitDir = path.join(projectName, "src", "backend", "test", "unit");
359
425
  const testIntegrationDir = path.join(projectName, "src", "backend", "test", "integration");
360
426
  await Promise.all([fs.ensureDir(testUnitDir), fs.ensureDir(testIntegrationDir)]);
361
427
  }
362
- const jestConfigTemplate = `import type { Config } from "jest";
428
+ const jestConfigTemplate$1 = `import type { Config } from "jest";
363
429
 
364
430
  const config: Config = {
365
431
  clearMocks: true,
@@ -383,7 +449,7 @@ export default config;
383
449
  `.trimStart();
384
450
 
385
451
  //#endregion
386
- //#region src/setups/docker_postges.ts
452
+ //#region src/configs/docker_postgres.ts
387
453
  async function setupDockerPostgres(projectName) {
388
454
  const dockerComposePath = path.join(projectName, "docker-compose.yml");
389
455
  await fs.ensureFile(dockerComposePath);
@@ -406,55 +472,353 @@ volumes:
406
472
  postgres_data:
407
473
  `;
408
474
 
475
+ //#endregion
476
+ //#region src/configs/expressjs/env.ts
477
+ async function configEnv(projectName, isSupabase = false) {
478
+ const envPath = path.join(projectName, "src", "env.ts");
479
+ await fs.ensureFile(envPath);
480
+ await fs.writeFile(envPath, envTemplate(isSupabase));
481
+ }
482
+ const envTemplate = (isSupabase) => `import { z } from "zod";
483
+
484
+ const envSchema = z.object({
485
+ NODE_ENV: z
486
+ .enum(["development", "production", "test"])
487
+ .default("development"),
488
+ DATABASE_URL: z.string().min(1, "Database URL is required"),
489
+ ${isSupabase ? "SUPABASE_SERVICE_ROLE_KEY: z.string().min(1, \"Supabase service role key is required\")," : ""}
490
+ ${isSupabase ? "SUPABASE_URL: z.string().min(1, \"Supabase URL is required\")," : ""}
491
+ ${isSupabase ? "SUPABASE_ANON_KEY: z.string().min(1, \"Supabase anon key is required\")," : ""}
492
+ });
493
+
494
+ const parsed = envSchema.safeParse(process.env);
495
+
496
+ if (!parsed.success) {
497
+ console.error("❌ Invalid environment variables:");
498
+ console.error(JSON.stringify(parsed.error.format(), null, 2));
499
+ throw new Error("Invalid environment variables");
500
+ }
501
+
502
+ export const env = parsed.data;
503
+ `.trimStart();
504
+
505
+ //#endregion
506
+ //#region src/configs/expressjs/supabase_client.ts
507
+ async function configSupabaseClient(projectName) {
508
+ const supabaseDir = path.join(projectName, "src", "db", "supabase");
509
+ await fs.ensureDir(supabaseDir);
510
+ const supabaseClientPath = path.join(supabaseDir, "client.ts");
511
+ const supabaseAdminPath = path.join(supabaseDir, "admin.ts");
512
+ await Promise.all([fs.ensureFile(supabaseClientPath), fs.ensureFile(supabaseAdminPath)]);
513
+ await Promise.all([fs.writeFile(supabaseClientPath, supabaseClientTemplate), fs.writeFile(supabaseAdminPath, supabaseAdminTemplate)]);
514
+ }
515
+ const supabaseClientTemplate = `import { createClient } from "@supabase/supabase-js";
516
+ import { env } from "../../env";
517
+
518
+ const supabase = createClient(env.SUPABASE_URL, env.SUPABASE_ANON_KEY);
519
+ export default supabase;
520
+ `;
521
+ const supabaseAdminTemplate = `import { createClient } from "@supabase/supabase-js";
522
+ import { env } from "../../env";
523
+
524
+ const supabaseAdmin = createClient(
525
+ env.SUPABASE_URL,
526
+ env.SUPABASE_SERVICE_ROLE_KEY,
527
+ {
528
+ auth: {
529
+ autoRefreshToken: false,
530
+ persistSession: false,
531
+ },
532
+ },
533
+ );
534
+ export default supabaseAdmin;
535
+ `;
536
+
537
+ //#endregion
538
+ //#region src/configs/expressjs/supabase_local.ts
539
+ async function configSupabaseLocal(projectDir) {
540
+ execa("npx", ["supabase", "init"], {
541
+ cwd: projectDir,
542
+ stdio: "inherit"
543
+ });
544
+ const migrationsDir = path.join(projectDir, "supabase", "migrations");
545
+ const schemaDir = path.join(projectDir, "supabase", "schemas");
546
+ const dbDir = path.join(schemaDir, "db");
547
+ const storageDir = path.join(schemaDir, "storage");
548
+ await Promise.all([fs.ensureDir(migrationsDir), fs.ensureDir(schemaDir)]);
549
+ await Promise.all([fs.ensureDir(dbDir), fs.ensureDir(storageDir)]);
550
+ }
551
+
552
+ //#endregion
553
+ //#region src/configs/expressjs/drizzle.ts
554
+ async function configDrizzle(projectName) {
555
+ const schemasDir = path.join(projectName, "src", "db", "schemas");
556
+ const migrationsDir = path.join(projectName, "src", "db", "migrations");
557
+ const drizzleConfigPath = path.join(projectName, "drizzle.config.ts");
558
+ await Promise.all([
559
+ fs.ensureDir(schemasDir),
560
+ fs.ensureDir(migrationsDir),
561
+ fs.ensureFile(drizzleConfigPath)
562
+ ]);
563
+ await fs.writeFile(drizzleConfigPath, drizzleConfigTemplate);
564
+ const packageJsonPath = path.join(projectName, "package.json");
565
+ const packageJson = await fs.readJson(packageJsonPath);
566
+ packageJson.scripts["db:generate"] = "npx drizzle-kit generate --config=./drizzle.config.ts";
567
+ packageJson.scripts["db:migrate"] = "npx drizzle-kit push --config=./drizzle.config.ts";
568
+ packageJson.scripts["db:studio"] = "npx drizzle-kit studio --verbose --config=./drizzle.config.ts";
569
+ packageJson.scripts["db:pull"] = "npx drizzle-kit pull --config=./drizzle.config.ts";
570
+ packageJson.scripts["db:check"] = "npx drizzle-kit check --config=./drizzle.config.ts";
571
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
572
+ }
573
+ const drizzleConfigTemplate = `import { defineConfig } from "drizzle-kit";
574
+ import { env } from "./src/env";
575
+
576
+ export default defineConfig({
577
+ dialect: "postgresql",
578
+ schema: "./src/db/schemas/*",
579
+ out: "./src/db/migrations",
580
+ dbCredentials: {
581
+ url: env.DATABASE_URL,
582
+ },
583
+ verbose: true,
584
+ strict: true,
585
+ });
586
+ `.trimStart();
587
+
588
+ //#endregion
589
+ //#region src/configs/expressjs/biome.ts
590
+ async function configBiome(projectName) {
591
+ execa("npx", ["biome", "init"], {
592
+ cwd: projectName,
593
+ stdio: "inherit"
594
+ });
595
+ }
596
+
597
+ //#endregion
598
+ //#region src/configs/expressjs/jest.ts
599
+ async function configJest(projectName) {
600
+ const jestConfigPath = path.join(projectName, "jest.config.mjs");
601
+ await fs.ensureFile(jestConfigPath);
602
+ await fs.writeFile(jestConfigPath, jestConfigTemplate);
603
+ const packageJsonPath = path.join(projectName, "package.json");
604
+ const packageJson = await fs.readJson(packageJsonPath);
605
+ packageJson.scripts["test:unit"] = "jest --testPathPatterns=unit";
606
+ packageJson.scripts["test:integration"] = "jest --testPathPatterns=integration";
607
+ packageJson.scripts["test"] = "jest";
608
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
609
+ const testUnitDir = path.join(projectName, "test", "unit");
610
+ const testIntegrationDir = path.join(projectName, "test", "integration");
611
+ await Promise.all([fs.ensureDir(testUnitDir), fs.ensureDir(testIntegrationDir)]);
612
+ }
613
+ const jestConfigTemplate = `/** @type {import('jest').Config} */
614
+
615
+ export default {
616
+ clearMocks: true,
617
+ coverageProvider: "v8",
618
+ moduleNameMapper: {
619
+ "^@/(.*)$": "<rootDir>/src/$1",
620
+ },
621
+ preset: "ts-jest/presets/default-esm",
622
+ testEnvironment: "node",
623
+ };
624
+ `.trimStart();
625
+
626
+ //#endregion
627
+ //#region src/configs/expressjs/typescript.ts
628
+ async function configTypescript(projectName) {
629
+ await execa("npx", ["tsc", "--init"], {
630
+ cwd: projectName,
631
+ stdio: "inherit"
632
+ });
633
+ const tsconfigPath = path.join(projectName, "tsconfig.json");
634
+ await fs.writeFile(tsconfigPath, tsconfigTemplate);
635
+ const packageJsonPath = path.join(projectName, "package.json");
636
+ const packageJson = await fs.readJson(packageJsonPath);
637
+ packageJson.scripts["start"] = "node ./dist/index.js";
638
+ packageJson.scripts["build"] = "tsc --build";
639
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
640
+ }
641
+ const tsconfigTemplate = `{
642
+ "compilerOptions": {
643
+ "rootDir": ".",
644
+ "outDir": "./dist",
645
+
646
+ "module": "CommonJS",
647
+ "target": "ES2022",
648
+ "esModuleInterop": true,
649
+ "resolveJsonModule": true,
650
+ "types": ["jest"],
651
+
652
+ "sourceMap": true,
653
+ "declaration": true,
654
+ "declarationMap": true,
655
+
656
+ "noUncheckedIndexedAccess": true,
657
+ "exactOptionalPropertyTypes": true,
658
+
659
+ "strict": true,
660
+ "isolatedModules": true,
661
+ "noUncheckedSideEffectImports": true,
662
+ "moduleDetection": "force",
663
+ "skipLibCheck": true
664
+ }
665
+ }`.trimStart();
666
+
667
+ //#endregion
668
+ //#region src/configs/expressjs/nodemon.ts
669
+ async function configNodemon(projectName) {
670
+ const packageJsonPath = path.join(projectName, "package.json");
671
+ const packageJson = await fs.readJson(packageJsonPath);
672
+ packageJson.scripts["dev"] = "nodemon index.ts";
673
+ await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
674
+ }
675
+
676
+ //#endregion
677
+ //#region src/setup/expressjs.ts
678
+ async function setupExpressjs(projectName, dbProvider, dbTool, isNeverThrow) {
679
+ await createExpressApp(projectName);
680
+ const dependencies = [
681
+ "cookie-parser",
682
+ "cors",
683
+ "dotenv",
684
+ "drizzle-orm",
685
+ "express",
686
+ "helmet",
687
+ "morgan",
688
+ "swagger-ui-express",
689
+ "zod"
690
+ ];
691
+ const devDependencies = [
692
+ "@biomejs/biome",
693
+ "@types/cookie-parser",
694
+ "@types/cors",
695
+ "@types/dotenv",
696
+ "@types/express",
697
+ "@types/helmet",
698
+ "@types/jest",
699
+ "@types/morgan",
700
+ "@types/swagger-ui-express",
701
+ "husky",
702
+ "jest",
703
+ "lint-staged",
704
+ "nodemon",
705
+ "ts-jest",
706
+ "ts-node",
707
+ "typescript"
708
+ ];
709
+ if (dbProvider === DB_PROVIDERS.SUPABASE) dependencies.push("@supabase/supabase-js");
710
+ if (dbTool === DB_TOOLS.DRIZZLE_ORM) {
711
+ dependencies.push("drizzle-orm", "postgres");
712
+ devDependencies.push("drizzle-kit");
713
+ }
714
+ if (isNeverThrow) dependencies.push("neverthrow");
715
+ await installDependencies$1(projectName, dependencies);
716
+ await installDevDependencies$1(projectName, devDependencies);
717
+ await setupHuskyLintStaged(projectName);
718
+ await configEnv(projectName, dbProvider === DB_PROVIDERS.SUPABASE);
719
+ if (dbProvider === DB_PROVIDERS.DOCKER) await setupDockerPostgres(projectName);
720
+ if (dbProvider === DB_PROVIDERS.SUPABASE) await configSupabaseClient(projectName);
721
+ if (dbTool === DB_TOOLS.SUPABASE_JS_SDK) await configSupabaseLocal(projectName);
722
+ if (dbTool === DB_TOOLS.DRIZZLE_ORM) await configDrizzle(projectName);
723
+ await configBiome(projectName);
724
+ await configJest(projectName);
725
+ await configTypescript(projectName);
726
+ await configNodemon(projectName);
727
+ }
728
+
729
+ //#endregion
730
+ //#region src/installers/nextjs/dependencies.ts
731
+ async function installDependencies(projectName, dependencies) {
732
+ await execa("npm", ["install", ...dependencies], {
733
+ cwd: projectName,
734
+ stdio: "inherit"
735
+ });
736
+ }
737
+
738
+ //#endregion
739
+ //#region src/installers/nextjs/devDependencies.ts
740
+ async function installDevDependencies(projectName, devDependencies) {
741
+ await execa("npm", [
742
+ "install",
743
+ "-D",
744
+ ...devDependencies
745
+ ], {
746
+ cwd: projectName,
747
+ stdio: "inherit"
748
+ });
749
+ }
750
+
751
+ //#endregion
752
+ //#region src/installers/nextjs/nexjs.ts
753
+ async function createNextApp(projectName) {
754
+ await execa("npx", [
755
+ "create-next-app@latest",
756
+ projectName,
757
+ "--ts",
758
+ "--tailwind",
759
+ "--react-compiler",
760
+ "--biome",
761
+ "--app",
762
+ "--src-dir",
763
+ "--import-alias",
764
+ "@/*"
765
+ ], { stdio: "inherit" });
766
+ }
767
+
768
+ //#endregion
769
+ //#region src/setup/nextjs.ts
770
+ async function setupNextjs(projectName, dbProvider, dbTool, uiLibrary, isNeverThrow) {
771
+ await createNextApp(projectName);
772
+ const dependencies = [
773
+ "react-hook-form",
774
+ "@hookform/resolvers",
775
+ "zod",
776
+ "server-only"
777
+ ];
778
+ const devDependencies = [
779
+ "husky",
780
+ "lint-staged",
781
+ "jest",
782
+ "@types/jest",
783
+ "ts-jest"
784
+ ];
785
+ if (dbProvider === DB_PROVIDERS.SUPABASE) dependencies.push("@supabase/ssr", "@supabase/supabase-js");
786
+ if (dbTool === DB_TOOLS.DRIZZLE_ORM) {
787
+ dependencies.push("drizzle-orm", "postgres");
788
+ devDependencies.push("drizzle-kit");
789
+ }
790
+ if (isNeverThrow) dependencies.push("neverthrow");
791
+ await installDependencies(projectName, dependencies);
792
+ await installDevDependencies(projectName, devDependencies);
793
+ await setupHuskyLintStaged(projectName);
794
+ await setupEnv(projectName, dbProvider === DB_PROVIDERS.SUPABASE);
795
+ if (dbProvider === DB_PROVIDERS.SUPABASE) await setupSupabaseClient(projectName);
796
+ if (dbProvider === DB_PROVIDERS.DOCKER) await setupDockerPostgres(projectName);
797
+ if (dbTool === DB_TOOLS.SUPABASE_JS_SDK) await setupSupabaseLocal(projectName);
798
+ if (dbTool === DB_TOOLS.DRIZZLE_ORM) await setupDrizzle(projectName);
799
+ if (uiLibrary === UI_LIB.SHADCN) await setupShadcn(projectName);
800
+ await setupBiome(projectName, uiLibrary === UI_LIB.SHADCN);
801
+ await setupJest(projectName);
802
+ }
803
+
409
804
  //#endregion
410
805
  //#region src/create.ts
411
806
  async function createProject(answers) {
412
- const { projectName, framework, dbProvider, dbTool, uiLibrary, useMonorepo } = answers;
807
+ const { projectName, framework, dbProvider, dbTool, uiLibrary, isNeverThrow } = answers;
413
808
  switch (framework) {
414
- case FRAMEWORKS.NEXT: {
415
- await createNextApp(projectName);
416
- const dependencies = [
417
- "react-hook-form",
418
- "@hookform/resolvers",
419
- "zod",
420
- "server-only"
421
- ];
422
- const devDependencies = [
423
- "husky",
424
- "lint-staged",
425
- "jest",
426
- "@types/jest",
427
- "ts-jest"
428
- ];
429
- if (dbProvider === DB_PROVIDERS.SUPABASE) dependencies.push("@supabase/ssr", "@supabase/supabase-js");
430
- if (dbTool === DB_TOOLS.DRIZZLE_ORM) {
431
- dependencies.push("drizzle-orm", "postgres");
432
- devDependencies.push("drizzle-kit");
433
- }
434
- await installDependencies(projectName, dependencies);
435
- await installDevDependencies(projectName, devDependencies);
436
- await setupHuskyLintStaged(projectName);
437
- await setupNextEnv(projectName, dbProvider === DB_PROVIDERS.SUPABASE);
438
- if (dbProvider === DB_PROVIDERS.SUPABASE) await setupNextSupabaseClient(projectName);
439
- if (dbProvider === DB_PROVIDERS.DOCKER) await setupDockerPostgres(projectName);
440
- if (dbTool === DB_TOOLS.SUPABASE_JS_SDK) await setupNextSupabaseLocal(projectName);
441
- if (dbTool === DB_TOOLS.DRIZZLE_ORM) await setupDrizzle(projectName);
442
- if (uiLibrary === UI_LIB.SHADCN) await setupShadcn(projectName);
443
- await setupBiome(projectName, uiLibrary === UI_LIB.SHADCN);
444
- await setupJest(projectName);
809
+ case FRAMEWORKS.NEXT:
810
+ await setupNextjs(projectName, dbProvider, dbTool, uiLibrary, isNeverThrow);
445
811
  break;
446
- }
447
812
  case FRAMEWORKS.NEXT_EXPRESS:
448
- createNextApp(projectName + "-fe");
449
- createNextExpressApp(projectName + "-be");
813
+ await Promise.all([setupNextjs(projectName + "-fe", DB_PROVIDERS.NONE, DB_TOOLS.NONE, uiLibrary, isNeverThrow), setupExpressjs(projectName + "-be", dbProvider, dbTool, isNeverThrow)]);
450
814
  break;
451
815
  case FRAMEWORKS.NEXT_NEST:
452
- createNextApp(projectName + "-fe");
816
+ await setupNextjs(projectName + "-fe", DB_PROVIDERS.NONE, DB_TOOLS.NONE, uiLibrary, isNeverThrow);
453
817
  createNestApp(projectName + "-be");
454
818
  break;
455
819
  case FRAMEWORKS.REACT_EXPRESS:
456
820
  createReactApp(projectName + "-fe");
457
- createNextExpressApp(projectName + "-be");
821
+ createExpressApp(projectName + "-be");
458
822
  break;
459
823
  case FRAMEWORKS.REACT_NEST:
460
824
  createReactApp(projectName + "-fe");
@@ -530,10 +894,9 @@ async function ask() {
530
894
  },
531
895
  {
532
896
  type: "confirm",
533
- name: "useMonorepo",
534
- message: "Do you want to use monorepo?",
535
- default: true,
536
- when: (answers) => ![FRAMEWORKS.NEXT, FRAMEWORKS.REACT].includes(answers.framework)
897
+ name: "isNeverThrow",
898
+ message: "Do you want to use nerverthrow?",
899
+ default: false
537
900
  }
538
901
  ]);
539
902
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-init-mtv-app",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "CLI for create init app",
5
5
  "keywords": [
6
6
  "create-init-app"