better-ts-stack 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -0
- package/dist/builder/configGenerator.d.ts +6 -0
- package/dist/builder/configGenerator.d.ts.map +1 -0
- package/dist/builder/configGenerator.js +110 -0
- package/dist/builder/configGenerator.js.map +1 -0
- package/dist/builder/dependencyInstaller.d.ts +3 -0
- package/dist/builder/dependencyInstaller.d.ts.map +1 -0
- package/dist/builder/dependencyInstaller.js +39 -0
- package/dist/builder/dependencyInstaller.js.map +1 -0
- package/dist/builder/fileProcessor.d.ts +6 -0
- package/dist/builder/fileProcessor.d.ts.map +1 -0
- package/dist/builder/fileProcessor.js +108 -0
- package/dist/builder/fileProcessor.js.map +1 -0
- package/dist/builder/gitInitializer.d.ts +2 -0
- package/dist/builder/gitInitializer.d.ts.map +1 -0
- package/dist/builder/gitInitializer.js +52 -0
- package/dist/builder/gitInitializer.js.map +1 -0
- package/dist/builder/index.d.ts +3 -0
- package/dist/builder/index.d.ts.map +1 -0
- package/dist/builder/index.js +126 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/builder/moduleSelector.d.ts +9 -0
- package/dist/builder/moduleSelector.d.ts.map +1 -0
- package/dist/builder/moduleSelector.js +29 -0
- package/dist/builder/moduleSelector.js.map +1 -0
- package/dist/builder/templateContext.d.ts +21 -0
- package/dist/builder/templateContext.d.ts.map +1 -0
- package/dist/builder/templateContext.js +47 -0
- package/dist/builder/templateContext.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/intro.d.ts +2 -0
- package/dist/intro.d.ts.map +1 -0
- package/dist/intro.js +27 -0
- package/dist/intro.js.map +1 -0
- package/dist/modules/registry.d.ts +6 -0
- package/dist/modules/registry.d.ts.map +1 -0
- package/dist/modules/registry.js +64 -0
- package/dist/modules/registry.js.map +1 -0
- package/dist/output/nextSteps.d.ts +4 -0
- package/dist/output/nextSteps.d.ts.map +1 -0
- package/dist/output/nextSteps.js +87 -0
- package/dist/output/nextSteps.js.map +1 -0
- package/dist/prompts/backend/index.d.ts +3 -0
- package/dist/prompts/backend/index.d.ts.map +1 -0
- package/dist/prompts/backend/index.js +128 -0
- package/dist/prompts/backend/index.js.map +1 -0
- package/dist/prompts/frontend/index.d.ts +3 -0
- package/dist/prompts/frontend/index.d.ts.map +1 -0
- package/dist/prompts/frontend/index.js +111 -0
- package/dist/prompts/frontend/index.js.map +1 -0
- package/dist/prompts/index.d.ts +4 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +82 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/types/index.d.ts +157 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +81 -0
- package/dist/types/index.js.map +1 -0
- package/dist/validators/index.d.ts +5 -0
- package/dist/validators/index.d.ts.map +1 -0
- package/dist/validators/index.js +73 -0
- package/dist/validators/index.js.map +1 -0
- package/package.json +66 -0
- package/templates/backend/express/.eslintrc.js +24 -0
- package/templates/backend/express/.prettierignore +52 -0
- package/templates/backend/express/.prettierrc +16 -0
- package/templates/backend/express/config.json +42 -0
- package/templates/backend/express/eslint.config.mjs +31 -0
- package/templates/backend/express/gitignore +39 -0
- package/templates/backend/express/src/index.ts +46 -0
- package/templates/backend/express/src/routes/health.ts +12 -0
- package/templates/backend/express/tsconfig.eslint.json +9 -0
- package/templates/backend/express/tsconfig.json +23 -0
- package/templates/frontend/nextjs/app/globals.css +99 -0
- package/templates/frontend/nextjs/app/layout.tsx +34 -0
- package/templates/frontend/nextjs/app/page.tsx.hbs +98 -0
- package/templates/frontend/nextjs/components/ui/button.tsx +51 -0
- package/templates/frontend/nextjs/components/ui/card.tsx +60 -0
- package/templates/frontend/nextjs/components/ui/field.tsx +67 -0
- package/templates/frontend/nextjs/components/ui/input.tsx +18 -0
- package/templates/frontend/nextjs/components.json +19 -0
- package/templates/frontend/nextjs/config.json +33 -0
- package/templates/frontend/nextjs/eslint.config.mjs +11 -0
- package/templates/frontend/nextjs/gitignore +41 -0
- package/templates/frontend/nextjs/lib/utils.ts +6 -0
- package/templates/frontend/nextjs/next.config.ts +8 -0
- package/templates/frontend/nextjs/postcss.config.mjs +7 -0
- package/templates/frontend/nextjs/proxy.ts.hbs +23 -0
- package/templates/frontend/nextjs/public/file.svg +1 -0
- package/templates/frontend/nextjs/public/globe.svg +1 -0
- package/templates/frontend/nextjs/public/next.svg +1 -0
- package/templates/frontend/nextjs/public/vercel.svg +1 -0
- package/templates/frontend/nextjs/public/window.svg +1 -0
- package/templates/frontend/nextjs/tsconfig.json +21 -0
- package/templates/modules/auth/express/config.json +1 -0
- package/templates/modules/auth/express/src/controllers/authController.ts.hbs +81 -0
- package/templates/modules/auth/express/src/lib/jwt.ts.hbs +27 -0
- package/templates/modules/auth/express/src/middleware/requireAuth.ts.hbs +26 -0
- package/templates/modules/auth/express/src/routes/auth.ts.hbs +19 -0
- package/templates/modules/auth/express/src/services/userStore.ts.hbs +107 -0
- package/templates/modules/auth/nextjs/app/api/auth/[...all]/route.ts +4 -0
- package/templates/modules/auth/nextjs/app/dashboard/page.tsx +96 -0
- package/templates/modules/auth/nextjs/app/sign-in/page.tsx +35 -0
- package/templates/modules/auth/nextjs/app/sign-up/page.tsx +35 -0
- package/templates/modules/auth/nextjs/components/auth/sign-in-form.tsx +132 -0
- package/templates/modules/auth/nextjs/components/auth/sign-out-button.tsx +50 -0
- package/templates/modules/auth/nextjs/components/auth/sign-up-form.tsx +152 -0
- package/templates/modules/auth/nextjs/config.json +31 -0
- package/templates/modules/auth/nextjs/lib/auth-client.ts +3 -0
- package/templates/modules/auth/nextjs/lib/auth-schema.ts +39 -0
- package/templates/modules/auth/nextjs/lib/auth.ts.hbs +35 -0
- package/templates/modules/docker/.dockerignore +13 -0
- package/templates/modules/docker/Dockerfile.hbs +71 -0
- package/templates/modules/docker/config.json +16 -0
- package/templates/modules/docker/docker-compose.yml.hbs +10 -0
- package/templates/modules/drizzle/nextjs/config.json +21 -0
- package/templates/modules/drizzle/nextjs/drizzle.config.ts +13 -0
- package/templates/modules/drizzle/nextjs/lib/db.ts +11 -0
- package/templates/modules/drizzle/nextjs/lib/schema.ts.hbs +84 -0
- package/templates/modules/mongoose/config.json +16 -0
- package/templates/modules/mongoose/src/lib/db.ts +43 -0
- package/templates/modules/mongoose/src/lib/db.ts.hbs +56 -0
- package/templates/modules/mongoose/src/models/User.ts +47 -0
- package/templates/modules/prisma/express/config.json +21 -0
- package/templates/modules/prisma/express/prisma/schema.prisma +23 -0
- package/templates/modules/prisma/express/prisma.config.ts +13 -0
- package/templates/modules/prisma/express/src/lib/prisma.ts +37 -0
- package/templates/modules/prisma/nextjs/config.json +23 -0
- package/templates/modules/prisma/nextjs/lib/prisma.ts +18 -0
- package/templates/modules/prisma/nextjs/prisma/schema.prisma.hbs +90 -0
- package/templates/modules/prisma/nextjs/prisma.config.ts +12 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.collectFrontendChoices = void 0;
|
|
4
|
+
const prompts_1 = require("@clack/prompts");
|
|
5
|
+
const types_1 = require("../../types");
|
|
6
|
+
const collectFrontendChoices = async () => {
|
|
7
|
+
const project = await (0, prompts_1.group)({
|
|
8
|
+
framework: async () => {
|
|
9
|
+
// Auto-select Next.js since it's the only option
|
|
10
|
+
return Promise.resolve("nextjs");
|
|
11
|
+
},
|
|
12
|
+
databaseType: async () => {
|
|
13
|
+
const selection = await (0, prompts_1.select)({
|
|
14
|
+
message: "Select a database:",
|
|
15
|
+
options: types_1.databaseTypeOptions,
|
|
16
|
+
initialValue: "none",
|
|
17
|
+
});
|
|
18
|
+
if ((0, prompts_1.isCancel)(selection)) {
|
|
19
|
+
(0, prompts_1.cancel)("Operation cancelled.");
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
return selection;
|
|
23
|
+
},
|
|
24
|
+
orm: async ({ results }) => {
|
|
25
|
+
// Type guard to narrow the databaseType from unknown to DatabaseType
|
|
26
|
+
const dbType = results.databaseType;
|
|
27
|
+
// Skip ORM selection if no database type was selected
|
|
28
|
+
if (dbType === "none") {
|
|
29
|
+
return "none";
|
|
30
|
+
}
|
|
31
|
+
// Select ORM based on database type
|
|
32
|
+
if (dbType !== "mongodb" && dbType !== "postgresql") {
|
|
33
|
+
return "none";
|
|
34
|
+
}
|
|
35
|
+
const ormOptions = dbType === "mongodb" ? types_1.mongodbOrmOptions : types_1.postgresqlOrmOptions;
|
|
36
|
+
const selection = await (0, prompts_1.select)({
|
|
37
|
+
message: `Select an ORM for ${dbType}:`,
|
|
38
|
+
options: ormOptions,
|
|
39
|
+
initialValue: "prisma",
|
|
40
|
+
});
|
|
41
|
+
if ((0, prompts_1.isCancel)(selection)) {
|
|
42
|
+
(0, prompts_1.cancel)("Operation cancelled.");
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
return selection;
|
|
46
|
+
},
|
|
47
|
+
packageManager: async () => {
|
|
48
|
+
const selection = await (0, prompts_1.select)({
|
|
49
|
+
message: "Select a package manager:",
|
|
50
|
+
options: types_1.packageManagerOptions,
|
|
51
|
+
initialValue: "npm",
|
|
52
|
+
});
|
|
53
|
+
if ((0, prompts_1.isCancel)(selection)) {
|
|
54
|
+
(0, prompts_1.cancel)("Operation cancelled.");
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
return selection;
|
|
58
|
+
},
|
|
59
|
+
useDocker: () => (0, prompts_1.confirm)({
|
|
60
|
+
message: "Use Docker?",
|
|
61
|
+
initialValue: false,
|
|
62
|
+
}),
|
|
63
|
+
useAuth: async ({ results }) => {
|
|
64
|
+
// Better Auth template requires a database-backed adapter
|
|
65
|
+
if (results.databaseType === "none") {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const selection = await (0, prompts_1.select)({
|
|
69
|
+
message: "Add Better Auth?",
|
|
70
|
+
options: types_1.authOptions,
|
|
71
|
+
initialValue: false,
|
|
72
|
+
});
|
|
73
|
+
if ((0, prompts_1.isCancel)(selection)) {
|
|
74
|
+
(0, prompts_1.cancel)("Operation cancelled.");
|
|
75
|
+
process.exit(0);
|
|
76
|
+
}
|
|
77
|
+
return selection;
|
|
78
|
+
},
|
|
79
|
+
initGit: () => (0, prompts_1.confirm)({
|
|
80
|
+
message: "Initialize a git repository?",
|
|
81
|
+
initialValue: true,
|
|
82
|
+
}),
|
|
83
|
+
installDeps: () => (0, prompts_1.confirm)({
|
|
84
|
+
message: "Install dependencies now?",
|
|
85
|
+
initialValue: false,
|
|
86
|
+
}),
|
|
87
|
+
}, {
|
|
88
|
+
onCancel: () => {
|
|
89
|
+
(0, prompts_1.cancel)("Operation cancelled.");
|
|
90
|
+
process.exit(0);
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
// Transform the group result into the proper typed object
|
|
94
|
+
// Validate orm using type guard
|
|
95
|
+
if (!(0, types_1.isValidOrmOption)(project.orm)) {
|
|
96
|
+
throw new Error(`Invalid ORM option: ${String(project.orm)}`);
|
|
97
|
+
}
|
|
98
|
+
const result = {
|
|
99
|
+
framework: project.framework,
|
|
100
|
+
databaseType: project.databaseType,
|
|
101
|
+
orm: project.orm,
|
|
102
|
+
packageManager: project.packageManager,
|
|
103
|
+
useDocker: Boolean(project.useDocker),
|
|
104
|
+
useAuth: Boolean(project.useAuth),
|
|
105
|
+
initGit: Boolean(project.initGit),
|
|
106
|
+
installDeps: Boolean(project.installDeps),
|
|
107
|
+
};
|
|
108
|
+
return result;
|
|
109
|
+
};
|
|
110
|
+
exports.collectFrontendChoices = collectFrontendChoices;
|
|
111
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/prompts/frontend/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,aAAa,EACd,MAAM,UAAU,CAAC;AAMlB,wBAAsB,kBAAkB,2BA4CvC;AAGD,wBAAsB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAiC1E"}
|
|
@@ -0,0 +1,82 @@
|
|
|
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.collectUserChoices = collectUserChoices;
|
|
7
|
+
exports.confirmBuild = confirmBuild;
|
|
8
|
+
const prompts_1 = require("@clack/prompts");
|
|
9
|
+
const consola_1 = __importDefault(require("consola"));
|
|
10
|
+
const types_1 = require("../types");
|
|
11
|
+
const validators_1 = require("../validators");
|
|
12
|
+
const backend_1 = require("./backend");
|
|
13
|
+
const frontend_1 = require("./frontend");
|
|
14
|
+
// Collects user input via interactive prompts
|
|
15
|
+
async function collectUserChoices() {
|
|
16
|
+
const projectName = await (0, prompts_1.text)({
|
|
17
|
+
message: "Project name:",
|
|
18
|
+
placeholder: "my-awesome-project",
|
|
19
|
+
validate: (value) => (0, validators_1.validateProjectName)(value),
|
|
20
|
+
});
|
|
21
|
+
if ((0, prompts_1.isCancel)(projectName)) {
|
|
22
|
+
(0, prompts_1.cancel)("Operation cancelled.");
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
const applicationType = await (0, prompts_1.select)({
|
|
26
|
+
message: "Application type:",
|
|
27
|
+
options: types_1.applicationTypeOptions,
|
|
28
|
+
initialValue: "backend",
|
|
29
|
+
});
|
|
30
|
+
if ((0, prompts_1.isCancel)(applicationType)) {
|
|
31
|
+
(0, prompts_1.cancel)("Operation cancelled.");
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
let userChoices;
|
|
35
|
+
if (applicationType === "backend") {
|
|
36
|
+
userChoices = await (0, backend_1.collectBackendChoices)();
|
|
37
|
+
}
|
|
38
|
+
else if (applicationType === "fullstack") {
|
|
39
|
+
userChoices = await (0, frontend_1.collectFrontendChoices)();
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
(0, prompts_1.cancel)("Invalid application type selected.");
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
// Derive database field from databaseType + orm for backward compatibility
|
|
46
|
+
const database = (0, types_1.deriveDatabase)(userChoices.databaseType, userChoices.orm);
|
|
47
|
+
const choices = {
|
|
48
|
+
projectName,
|
|
49
|
+
applicationType,
|
|
50
|
+
...userChoices,
|
|
51
|
+
database,
|
|
52
|
+
};
|
|
53
|
+
return choices;
|
|
54
|
+
}
|
|
55
|
+
// Displays a summary and asks for final confirmation before building
|
|
56
|
+
async function confirmBuild(config, targetDir) {
|
|
57
|
+
consola_1.default.info("Project Summary:");
|
|
58
|
+
const appTypeLabel = config.applicationType === "backend" ? "Backend API" : "Full-stack App";
|
|
59
|
+
consola_1.default.box(`Project Name: ${config.projectName}\n` +
|
|
60
|
+
`Target Dir: ${targetDir}\n` +
|
|
61
|
+
`App Type: ${appTypeLabel}\n` +
|
|
62
|
+
`Framework: ${config.framework}\n` +
|
|
63
|
+
`Database: ${config.database}\n` +
|
|
64
|
+
`Auth: ${config.useAuth ? "Yes" : "No"}\n` +
|
|
65
|
+
`Docker: ${config.useDocker ? "Yes" : "No"}\n` +
|
|
66
|
+
`Package Mgr: ${config.packageManager}\n` +
|
|
67
|
+
`Git Init: ${config.initGit ? "Yes" : "No"}\n` +
|
|
68
|
+
`Install Deps: ${config.installDeps ? "Yes" : "No"}`);
|
|
69
|
+
const shouldContinue = await (0, prompts_1.confirm)({
|
|
70
|
+
message: "Looks good? Ready to build?",
|
|
71
|
+
initialValue: true,
|
|
72
|
+
});
|
|
73
|
+
if ((0, prompts_1.isCancel)(shouldContinue)) {
|
|
74
|
+
(0, prompts_1.cancel)("Operation cancelled.");
|
|
75
|
+
process.exit(0);
|
|
76
|
+
}
|
|
77
|
+
if (!shouldContinue) {
|
|
78
|
+
(0, prompts_1.cancel)("Building cancelled by user.");
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export type PackageManager = "npm" | "pnpm" | "bun";
|
|
2
|
+
export type DatabaseType = "mongodb" | "postgresql" | "none";
|
|
3
|
+
export type OrmOption = "prisma" | "mongoose" | "drizzle" | "none";
|
|
4
|
+
export type DatabaseOption = "none" | "prisma" | "mongoose" | "drizzle";
|
|
5
|
+
export type ApplicationType = "backend" | "fullstack";
|
|
6
|
+
export type ModuleType = "base" | "database" | "feature";
|
|
7
|
+
export interface Dependencies {
|
|
8
|
+
[packageName: string]: string;
|
|
9
|
+
}
|
|
10
|
+
export type BackendFramework = "express" | "nestjs";
|
|
11
|
+
export type FrontendFramework = "nextjs";
|
|
12
|
+
export interface ProjectConfig {
|
|
13
|
+
projectName: string;
|
|
14
|
+
applicationType: ApplicationType;
|
|
15
|
+
framework: BackendFramework | FrontendFramework;
|
|
16
|
+
databaseType: DatabaseType;
|
|
17
|
+
orm: OrmOption;
|
|
18
|
+
database: DatabaseOption;
|
|
19
|
+
useDocker: boolean;
|
|
20
|
+
useAuth: boolean;
|
|
21
|
+
packageManager: PackageManager;
|
|
22
|
+
initGit: boolean;
|
|
23
|
+
installDeps: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Shared type for prompt choices (used by both frontend and backend collectors).
|
|
27
|
+
* This is essentially ProjectConfig without the derived/initial fields.
|
|
28
|
+
*/
|
|
29
|
+
export type PromptChoices = Omit<ProjectConfig, "projectName" | "applicationType" | "database">;
|
|
30
|
+
/** Type guard to validate OrmOption values */
|
|
31
|
+
export declare function isValidOrmOption(value: unknown): value is OrmOption;
|
|
32
|
+
/**
|
|
33
|
+
* Derives the database option from database type and ORM selection.
|
|
34
|
+
* Returns "none" if either is "none", otherwise returns the ORM which
|
|
35
|
+
* must be a valid DatabaseOption (prisma, mongoose, or drizzle).
|
|
36
|
+
*/
|
|
37
|
+
export declare function deriveDatabase(databaseType: DatabaseType, orm: OrmOption): DatabaseOption;
|
|
38
|
+
export interface ModuleConfig {
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
description: string;
|
|
42
|
+
type: ModuleType;
|
|
43
|
+
dependencies: Dependencies;
|
|
44
|
+
devDependencies: Dependencies;
|
|
45
|
+
scripts: Record<string, string>;
|
|
46
|
+
envVars: Record<string, string>;
|
|
47
|
+
templateFiles: string[];
|
|
48
|
+
}
|
|
49
|
+
export interface Module {
|
|
50
|
+
config: ModuleConfig;
|
|
51
|
+
path: string;
|
|
52
|
+
}
|
|
53
|
+
export interface MergedConfig {
|
|
54
|
+
dependencies: Dependencies;
|
|
55
|
+
devDependencies: Dependencies;
|
|
56
|
+
scripts: Record<string, string>;
|
|
57
|
+
envVars: Record<string, string>;
|
|
58
|
+
}
|
|
59
|
+
export interface BuildResult {
|
|
60
|
+
success: boolean;
|
|
61
|
+
projectPath: string;
|
|
62
|
+
nextSteps: string[];
|
|
63
|
+
}
|
|
64
|
+
export interface BuildError extends Error {
|
|
65
|
+
code: string;
|
|
66
|
+
exitCode: number;
|
|
67
|
+
}
|
|
68
|
+
export declare function buildError(errorOrMessage: unknown, code: string, context?: string, exitCode?: number): BuildError;
|
|
69
|
+
export interface TemplateContext {
|
|
70
|
+
projectName: string;
|
|
71
|
+
packageManager: string;
|
|
72
|
+
database: string;
|
|
73
|
+
framework: string;
|
|
74
|
+
port: number;
|
|
75
|
+
useDocker: boolean;
|
|
76
|
+
useAuth: boolean;
|
|
77
|
+
helpers: {
|
|
78
|
+
lowercase: (str: string) => string;
|
|
79
|
+
uppercase: (str: string) => string;
|
|
80
|
+
kebabCase: (str: string) => string;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export declare const applicationTypeOptions: ({
|
|
84
|
+
value: "backend";
|
|
85
|
+
label: string;
|
|
86
|
+
} | {
|
|
87
|
+
value: "fullstack";
|
|
88
|
+
label: string;
|
|
89
|
+
})[];
|
|
90
|
+
export declare const backendFrameworkOptions: ({
|
|
91
|
+
value: "express";
|
|
92
|
+
label: string;
|
|
93
|
+
hint?: undefined;
|
|
94
|
+
} | {
|
|
95
|
+
value: "nestjs";
|
|
96
|
+
label: string;
|
|
97
|
+
hint: string;
|
|
98
|
+
})[];
|
|
99
|
+
export declare const frontendFrameworkOptions: {
|
|
100
|
+
value: "nextjs";
|
|
101
|
+
label: string;
|
|
102
|
+
}[];
|
|
103
|
+
export declare const databaseTypeOptions: ({
|
|
104
|
+
value: "none";
|
|
105
|
+
label: string;
|
|
106
|
+
} | {
|
|
107
|
+
value: "mongodb";
|
|
108
|
+
label: string;
|
|
109
|
+
} | {
|
|
110
|
+
value: "postgresql";
|
|
111
|
+
label: string;
|
|
112
|
+
})[];
|
|
113
|
+
export declare const mongodbOrmOptions: ({
|
|
114
|
+
value: "prisma";
|
|
115
|
+
label: string;
|
|
116
|
+
} | {
|
|
117
|
+
value: "mongoose";
|
|
118
|
+
label: string;
|
|
119
|
+
})[];
|
|
120
|
+
export declare const postgresqlOrmOptions: ({
|
|
121
|
+
value: "prisma";
|
|
122
|
+
label: string;
|
|
123
|
+
} | {
|
|
124
|
+
value: "drizzle";
|
|
125
|
+
label: string;
|
|
126
|
+
})[];
|
|
127
|
+
export declare const databaseOptions: ({
|
|
128
|
+
value: "none";
|
|
129
|
+
label: string;
|
|
130
|
+
} | {
|
|
131
|
+
value: "prisma";
|
|
132
|
+
label: string;
|
|
133
|
+
} | {
|
|
134
|
+
value: "mongoose";
|
|
135
|
+
label: string;
|
|
136
|
+
} | {
|
|
137
|
+
value: "drizzle";
|
|
138
|
+
label: string;
|
|
139
|
+
})[];
|
|
140
|
+
export declare const packageManagerOptions: ({
|
|
141
|
+
value: "npm";
|
|
142
|
+
label: string;
|
|
143
|
+
} | {
|
|
144
|
+
value: "pnpm";
|
|
145
|
+
label: string;
|
|
146
|
+
} | {
|
|
147
|
+
value: "bun";
|
|
148
|
+
label: string;
|
|
149
|
+
})[];
|
|
150
|
+
export declare const authOptions: ({
|
|
151
|
+
value: false;
|
|
152
|
+
label: string;
|
|
153
|
+
} | {
|
|
154
|
+
value: true;
|
|
155
|
+
label: string;
|
|
156
|
+
})[];
|
|
157
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Core type definitions for the CLI builder
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.authOptions = exports.packageManagerOptions = exports.databaseOptions = exports.postgresqlOrmOptions = exports.mongodbOrmOptions = exports.databaseTypeOptions = exports.frontendFrameworkOptions = exports.backendFrameworkOptions = exports.applicationTypeOptions = void 0;
|
|
5
|
+
exports.isValidOrmOption = isValidOrmOption;
|
|
6
|
+
exports.deriveDatabase = deriveDatabase;
|
|
7
|
+
exports.buildError = buildError;
|
|
8
|
+
/** Type guard to validate OrmOption values */
|
|
9
|
+
function isValidOrmOption(value) {
|
|
10
|
+
return (value === "prisma" ||
|
|
11
|
+
value === "mongoose" ||
|
|
12
|
+
value === "drizzle" ||
|
|
13
|
+
value === "none");
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Derives the database option from database type and ORM selection.
|
|
17
|
+
* Returns "none" if either is "none", otherwise returns the ORM which
|
|
18
|
+
* must be a valid DatabaseOption (prisma, mongoose, or drizzle).
|
|
19
|
+
*/
|
|
20
|
+
function deriveDatabase(databaseType, orm) {
|
|
21
|
+
if (databaseType === "none" || orm === "none") {
|
|
22
|
+
return "none";
|
|
23
|
+
}
|
|
24
|
+
// At this point, orm must be one of: prisma, mongoose, drizzle
|
|
25
|
+
// which are all valid DatabaseOption values
|
|
26
|
+
return orm;
|
|
27
|
+
}
|
|
28
|
+
// Unified error creation function
|
|
29
|
+
function buildError(errorOrMessage, code, context, exitCode = 1) {
|
|
30
|
+
const message = errorOrMessage instanceof Error
|
|
31
|
+
? errorOrMessage.message
|
|
32
|
+
: String(errorOrMessage);
|
|
33
|
+
const fullMessage = context ? `${context}: ${message}` : message;
|
|
34
|
+
const error = new Error(fullMessage);
|
|
35
|
+
return Object.assign(error, { code, exitCode });
|
|
36
|
+
}
|
|
37
|
+
// Type-safe option definitions
|
|
38
|
+
exports.applicationTypeOptions = [
|
|
39
|
+
{ value: "backend", label: "Backend API (Express/NestJS)" },
|
|
40
|
+
{ value: "fullstack", label: "Full-stack App (Next.js)" },
|
|
41
|
+
];
|
|
42
|
+
exports.backendFrameworkOptions = [
|
|
43
|
+
{ value: "express", label: "Express" },
|
|
44
|
+
{ value: "nestjs", label: "NestJS", hint: "(Coming Soon)" },
|
|
45
|
+
];
|
|
46
|
+
exports.frontendFrameworkOptions = [
|
|
47
|
+
{ value: "nextjs", label: "Next.js 16 (App Router)" },
|
|
48
|
+
];
|
|
49
|
+
// Database type options (what database system)
|
|
50
|
+
exports.databaseTypeOptions = [
|
|
51
|
+
{ value: "none", label: "None (Skip database setup)" },
|
|
52
|
+
{ value: "mongodb", label: "MongoDB" },
|
|
53
|
+
{ value: "postgresql", label: "PostgreSQL" },
|
|
54
|
+
];
|
|
55
|
+
// ORM options for MongoDB
|
|
56
|
+
exports.mongodbOrmOptions = [
|
|
57
|
+
{ value: "prisma", label: "Prisma (Type-safe ORM)" },
|
|
58
|
+
{ value: "mongoose", label: "Mongoose (MongoDB ODM)" },
|
|
59
|
+
];
|
|
60
|
+
// ORM options for PostgreSQL
|
|
61
|
+
exports.postgresqlOrmOptions = [
|
|
62
|
+
{ value: "prisma", label: "Prisma (Type-safe ORM)" },
|
|
63
|
+
{ value: "drizzle", label: "Drizzle (Lightweight ORM)" },
|
|
64
|
+
];
|
|
65
|
+
// Legacy database options (for backward compatibility)
|
|
66
|
+
exports.databaseOptions = [
|
|
67
|
+
{ value: "none", label: "None (Skip database setup)" },
|
|
68
|
+
{ value: "prisma", label: "Prisma (Type-safe ORM)" },
|
|
69
|
+
{ value: "mongoose", label: "Mongoose (Standard MongoDB ODM)" },
|
|
70
|
+
{ value: "drizzle", label: "Drizzle (Lightweight ORM)" },
|
|
71
|
+
];
|
|
72
|
+
exports.packageManagerOptions = [
|
|
73
|
+
{ value: "npm", label: "npm" },
|
|
74
|
+
{ value: "pnpm", label: "pnpm" },
|
|
75
|
+
{ value: "bun", label: "bun" },
|
|
76
|
+
];
|
|
77
|
+
exports.authOptions = [
|
|
78
|
+
{ value: false, label: "No" },
|
|
79
|
+
{ value: true, label: "Yes" },
|
|
80
|
+
];
|
|
81
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const projectNameSchema: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>;
|
|
3
|
+
export declare function validateProjectName(name: string): string | undefined;
|
|
4
|
+
export declare function validateDirectoryEmpty(dirPath: string): Promise<string | null>;
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validators/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,iBAAiB,uGAc3B,CAAC;AAGJ,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUpE;AAGD,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,0BAgB3D"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.projectNameSchema = void 0;
|
|
37
|
+
exports.validateProjectName = validateProjectName;
|
|
38
|
+
exports.validateDirectoryEmpty = validateDirectoryEmpty;
|
|
39
|
+
const fs = __importStar(require("fs-extra"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const zod_1 = require("zod");
|
|
42
|
+
// Validates project name: lowercase letters, numbers, and hyphens
|
|
43
|
+
exports.projectNameSchema = zod_1.z
|
|
44
|
+
.string()
|
|
45
|
+
.min(1, "Project name is required")
|
|
46
|
+
.refine((name) => /^[a-z0-9-]+$/.test(name), "Project name must be lowercase and can contain only letters, numbers, and hyphens")
|
|
47
|
+
.refine((name) => !name.startsWith("-") && !name.endsWith("-"), "Project name cannot start or end with a hyphen")
|
|
48
|
+
.refine((name) => name.length <= 214, "Project name must be 214 characters or less (npm package name limit)");
|
|
49
|
+
// Checks if a project name follows npm naming conventions
|
|
50
|
+
function validateProjectName(name) {
|
|
51
|
+
const result = exports.projectNameSchema.safeParse(name);
|
|
52
|
+
if (result.success) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
// Return the first error message
|
|
56
|
+
const firstError = result.error.errors[0];
|
|
57
|
+
return firstError.message;
|
|
58
|
+
}
|
|
59
|
+
// Ensures a directory is empty or does not exist before starting build
|
|
60
|
+
async function validateDirectoryEmpty(dirPath) {
|
|
61
|
+
const exists = await fs.pathExists(dirPath);
|
|
62
|
+
if (!exists)
|
|
63
|
+
return null;
|
|
64
|
+
const stats = await fs.stat(dirPath);
|
|
65
|
+
if (!stats.isDirectory()) {
|
|
66
|
+
return `Path "${dirPath}" exists but is not a directory`;
|
|
67
|
+
}
|
|
68
|
+
const files = await fs.readdir(dirPath);
|
|
69
|
+
if (files.length === 0)
|
|
70
|
+
return null;
|
|
71
|
+
return `Directory "${path.basename(dirPath)}" already exists and is not empty`;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validators/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,kDAUC;AAGD,wDAgBC;AAnDD,6CAA+B;AAC/B,2CAA6B;AAC7B,6BAAwB;AAExB,kEAAkE;AACrD,QAAA,iBAAiB,GAAG,OAAC;KAC/B,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,EAAE,0BAA0B,CAAC;KAClC,MAAM,CACL,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EACnC,mFAAmF,CACpF;KACA,MAAM,CACL,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EACtD,gDAAgD,CACjD;KACA,MAAM,CACL,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,EAC5B,sEAAsE,CACvE,CAAC;AAEJ,0DAA0D;AAC1D,SAAgB,mBAAmB,CAAC,IAAY;IAC9C,MAAM,MAAM,GAAG,yBAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAEjD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,iCAAiC;IACjC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1C,OAAO,UAAU,CAAC,OAAO,CAAC;AAC5B,CAAC;AAED,uEAAuE;AAChE,KAAK,UAAU,sBAAsB,CAAC,OAAe;IAC1D,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAE5C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAErC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACzB,OAAO,SAAS,OAAO,iCAAiC,CAAC;IAC3D,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAExC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,OAAO,cAAc,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,mCAAmC,CAAC;AACjF,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "better-ts-stack",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A powerful CLI tool that generates fully configured TypeScript projects with backend, frontend, database integration, Docker support, and more--all through an interactive setup.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cli",
|
|
7
|
+
"builder",
|
|
8
|
+
"backend",
|
|
9
|
+
"typescript",
|
|
10
|
+
"express",
|
|
11
|
+
"prisma",
|
|
12
|
+
"template"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://better-ts-stack.abdullahtech.me",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/Abdullah-dev0/better-ts-stack/issues"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/Abdullah-dev0/better-ts-stack.git"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "Abdullah",
|
|
24
|
+
"type": "commonjs",
|
|
25
|
+
"main": "dist/index.js",
|
|
26
|
+
"bin": {
|
|
27
|
+
"better-ts-stack": "dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"templates"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"dev": "tsx src/index.ts",
|
|
35
|
+
"build": "tsc",
|
|
36
|
+
"postbuild": "node -e \"const fs=require('fs');const p='dist/index.js';fs.writeFileSync(p,'#!/usr/bin/env node\\n'+fs.readFileSync(p,'utf8'))\"",
|
|
37
|
+
"prepack": "npm run build",
|
|
38
|
+
"start": "node dist/index.js",
|
|
39
|
+
"lint": "eslint src",
|
|
40
|
+
"lint:fix": "eslint src --fix",
|
|
41
|
+
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,mdx,css}\"",
|
|
42
|
+
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,mdx,css}\"",
|
|
43
|
+
"type:check": "tsc --noEmit"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@clack/prompts": "^0.11.0",
|
|
47
|
+
"consola": "^3.2.3",
|
|
48
|
+
"fs-extra": "^11.1.1",
|
|
49
|
+
"handlebars": "^4.7.8",
|
|
50
|
+
"zod": "^3.22.4"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@better-ts-stack/eslint-config": "*",
|
|
54
|
+
"@better-ts-stack/prettier-config": "*",
|
|
55
|
+
"@types/fs-extra": "^11.0.4",
|
|
56
|
+
"@types/node": "^20.10.5",
|
|
57
|
+
"eslint": "^9.17.0",
|
|
58
|
+
"prettier": "^3.1.1",
|
|
59
|
+
"tsx": "^4.7.0",
|
|
60
|
+
"typescript": "^5.3.3"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=18.0.0"
|
|
64
|
+
},
|
|
65
|
+
"prettier": "@better-ts-stack/prettier-config"
|
|
66
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
parser: '@typescript-eslint/parser',
|
|
3
|
+
parserOptions: {
|
|
4
|
+
ecmaVersion: 2020,
|
|
5
|
+
sourceType: 'module',
|
|
6
|
+
project: './tsconfig.json',
|
|
7
|
+
},
|
|
8
|
+
extends: [
|
|
9
|
+
'eslint:recommended',
|
|
10
|
+
'plugin:@typescript-eslint/recommended',
|
|
11
|
+
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
|
12
|
+
'prettier',
|
|
13
|
+
],
|
|
14
|
+
plugins: ['@typescript-eslint'],
|
|
15
|
+
env: {
|
|
16
|
+
node: true,
|
|
17
|
+
es2020: true,
|
|
18
|
+
},
|
|
19
|
+
rules: {
|
|
20
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
21
|
+
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
22
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
23
|
+
},
|
|
24
|
+
};
|