create-tigra 1.0.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/LICENSE +21 -0
- package/README.md +87 -0
- package/bin/create-tigra.js +292 -0
- package/package.json +41 -0
- package/template/.agent/rules/client/01-project-structure.md +326 -0
- package/template/.agent/rules/client/02-component-patterns.md +249 -0
- package/template/.agent/rules/client/03-typescript-rules.md +226 -0
- package/template/.agent/rules/client/04-state-management.md +474 -0
- package/template/.agent/rules/client/05-api-integration.md +129 -0
- package/template/.agent/rules/client/06-forms-validation.md +129 -0
- package/template/.agent/rules/client/07-common-patterns.md +150 -0
- package/template/.agent/rules/client/08-color-system.md +93 -0
- package/template/.agent/rules/client/09-security-rules.md +97 -0
- package/template/.agent/rules/client/10-testing-strategy.md +370 -0
- package/template/.agent/rules/global/ai-edit-safety.md +38 -0
- package/template/.agent/rules/server/01-db-and-migrations.md +242 -0
- package/template/.agent/rules/server/02-general-rules.md +111 -0
- package/template/.agent/rules/server/03-migrations.md +20 -0
- package/template/.agent/rules/server/04-pagination.md +130 -0
- package/template/.agent/rules/server/05-project-conventions.md +71 -0
- package/template/.agent/rules/server/06-response-handling.md +173 -0
- package/template/.agent/rules/server/07-testing-strategy.md +506 -0
- package/template/.agent/rules/server/08-observability.md +180 -0
- package/template/.agent/rules/server/09-api-documentation-v2.md +168 -0
- package/template/.agent/rules/server/10-background-jobs-v2.md +185 -0
- package/template/.agent/rules/server/11-rate-limiting-v2.md +210 -0
- package/template/.agent/rules/server/12-performance-optimization.md +567 -0
- package/template/.claude/rules/client-01-project-structure.md +327 -0
- package/template/.claude/rules/client-02-component-patterns.md +250 -0
- package/template/.claude/rules/client-03-typescript-rules.md +227 -0
- package/template/.claude/rules/client-04-state-management.md +475 -0
- package/template/.claude/rules/client-05-api-integration.md +130 -0
- package/template/.claude/rules/client-06-forms-validation.md +130 -0
- package/template/.claude/rules/client-07-common-patterns.md +151 -0
- package/template/.claude/rules/client-08-color-system.md +94 -0
- package/template/.claude/rules/client-09-security-rules.md +98 -0
- package/template/.claude/rules/client-10-testing-strategy.md +371 -0
- package/template/.claude/rules/global-ai-edit-safety.md +39 -0
- package/template/.claude/rules/server-01-db-and-migrations.md +243 -0
- package/template/.claude/rules/server-02-general-rules.md +112 -0
- package/template/.claude/rules/server-03-migrations.md +21 -0
- package/template/.claude/rules/server-04-pagination.md +131 -0
- package/template/.claude/rules/server-05-project-conventions.md +72 -0
- package/template/.claude/rules/server-06-response-handling.md +174 -0
- package/template/.claude/rules/server-07-testing-strategy.md +507 -0
- package/template/.claude/rules/server-08-observability.md +181 -0
- package/template/.claude/rules/server-09-api-documentation-v2.md +169 -0
- package/template/.claude/rules/server-10-background-jobs-v2.md +186 -0
- package/template/.claude/rules/server-11-rate-limiting-v2.md +211 -0
- package/template/.claude/rules/server-12-performance-optimization.md +568 -0
- package/template/.cursor/rules/client-01-project-structure.mdc +327 -0
- package/template/.cursor/rules/client-02-component-patterns.mdc +250 -0
- package/template/.cursor/rules/client-03-typescript-rules.mdc +227 -0
- package/template/.cursor/rules/client-04-state-management.mdc +475 -0
- package/template/.cursor/rules/client-05-api-integration.mdc +130 -0
- package/template/.cursor/rules/client-06-forms-validation.mdc +130 -0
- package/template/.cursor/rules/client-07-common-patterns.mdc +151 -0
- package/template/.cursor/rules/client-08-color-system.mdc +94 -0
- package/template/.cursor/rules/client-09-security-rules.mdc +98 -0
- package/template/.cursor/rules/client-10-testing-strategy.mdc +371 -0
- package/template/.cursor/rules/global-ai-edit-safety.mdc +39 -0
- package/template/.cursor/rules/server-01-db-and-migrations.mdc +243 -0
- package/template/.cursor/rules/server-02-general-rules.mdc +112 -0
- package/template/.cursor/rules/server-03-migrations.mdc +21 -0
- package/template/.cursor/rules/server-04-pagination.mdc +131 -0
- package/template/.cursor/rules/server-05-project-conventions.mdc +72 -0
- package/template/.cursor/rules/server-06-response-handling.mdc +174 -0
- package/template/.cursor/rules/server-07-testing-strategy.mdc +507 -0
- package/template/.cursor/rules/server-08-observability.mdc +181 -0
- package/template/.cursor/rules/server-09-api-documentation-v2.mdc +169 -0
- package/template/.cursor/rules/server-10-background-jobs-v2.mdc +186 -0
- package/template/.cursor/rules/server-11-rate-limiting-v2.mdc +211 -0
- package/template/.cursor/rules/server-12-performance-optimization.mdc +568 -0
- package/template/CLAUDE.md +207 -0
- package/template/server/.env.example +148 -0
- package/template/server/.tsc-aliasrc.json +12 -0
- package/template/server/README.md +175 -0
- package/template/server/SECURITY.md +190 -0
- package/template/server/biome.json +42 -0
- package/template/server/docker-compose.yml +111 -0
- package/template/server/package.json +83 -0
- package/template/server/postman_collection.json +733 -0
- package/template/server/prisma/schema.prisma +92 -0
- package/template/server/prisma/seed.ts +142 -0
- package/template/server/scripts/wait-for-db.js +60 -0
- package/template/server/src/app.ts +74 -0
- package/template/server/src/config/env.ts +101 -0
- package/template/server/src/hooks/request-timing.hook.ts +26 -0
- package/template/server/src/libs/auth/authenticate.middleware.ts +22 -0
- package/template/server/src/libs/auth/rbac.middleware.test.ts +134 -0
- package/template/server/src/libs/auth/rbac.middleware.ts +147 -0
- package/template/server/src/libs/db.ts +76 -0
- package/template/server/src/libs/error-handler.ts +89 -0
- package/template/server/src/libs/logger.ts +60 -0
- package/template/server/src/libs/queue.ts +79 -0
- package/template/server/src/libs/redis.ts +79 -0
- package/template/server/src/libs/swagger-schemas.ts +16 -0
- package/template/server/src/modules/admin/admin.controller.ts +122 -0
- package/template/server/src/modules/admin/admin.routes.ts +100 -0
- package/template/server/src/modules/admin/admin.schemas.ts +35 -0
- package/template/server/src/modules/admin/admin.service.ts +167 -0
- package/template/server/src/modules/auth/auth.controller.ts +141 -0
- package/template/server/src/modules/auth/auth.integration.test.ts +150 -0
- package/template/server/src/modules/auth/auth.repo.ts +218 -0
- package/template/server/src/modules/auth/auth.routes.ts +204 -0
- package/template/server/src/modules/auth/auth.schemas.ts +137 -0
- package/template/server/src/modules/auth/auth.service.test.ts +119 -0
- package/template/server/src/modules/auth/auth.service.ts +329 -0
- package/template/server/src/modules/auth/auth.types.ts +97 -0
- package/template/server/src/modules/resources/resources.controller.ts +218 -0
- package/template/server/src/modules/resources/resources.repo.ts +253 -0
- package/template/server/src/modules/resources/resources.routes.ts +355 -0
- package/template/server/src/modules/resources/resources.schemas.ts +146 -0
- package/template/server/src/modules/resources/resources.service.ts +218 -0
- package/template/server/src/modules/resources/resources.types.ts +73 -0
- package/template/server/src/plugins/rate-limit.plugin.ts +21 -0
- package/template/server/src/plugins/security.plugin.ts +21 -0
- package/template/server/src/plugins/swagger.plugin.ts +41 -0
- package/template/server/src/routes/health.routes.ts +31 -0
- package/template/server/src/server.ts +142 -0
- package/template/server/src/test/setup.ts +38 -0
- package/template/server/src/types/fastify.d.ts +36 -0
- package/template/server/src/utils/errors.ts +108 -0
- package/template/server/src/utils/pagination.ts +120 -0
- package/template/server/src/utils/response.ts +110 -0
- package/template/server/src/workers/file.worker.ts +106 -0
- package/template/server/tsconfig.build.json +30 -0
- package/template/server/tsconfig.build.tsbuildinfo +1 -0
- package/template/server/tsconfig.json +89 -0
- package/template/server/tsconfig.test.json +22 -0
- package/template/server/vitest.config.ts +98 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# create-tigra
|
|
2
|
+
|
|
3
|
+
Generate a **production-ready, robust API server** in seconds.
|
|
4
|
+
|
|
5
|
+
`create-tigra` scaffolds a modern, high-performance backend with built-in best practices, simplifying the setup of complex stacks so you can focus on building features.
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
* **Production-Ready Server**: A robust **Fastify + TypeScript** foundation designed for scale and performance.
|
|
10
|
+
* **Built-in Database & Caching**: Pre-configured **Database** (MySQL via Prisma) and **Redis** for caching and queues.
|
|
11
|
+
* **Docker Integration**: Full `docker-compose` setup included. Spin up your infrastructure (Database, Redis) instantly.
|
|
12
|
+
* **Management UIs Included**: Comes with containerized UIs for your database and Redis, making local development and debugging effortless.
|
|
13
|
+
* **Secured Authentication**: Implementation of robust authentication strategies out-of-the-box.
|
|
14
|
+
* **RBAC & Admin Routes**: Pre-built Role-Based Access Control system with dedicated, secured admin routes to manage your application.
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
Before using `create-tigra`, ensure you have the following installed:
|
|
19
|
+
|
|
20
|
+
* **Node.js**: Version 18.0.0 or higher.
|
|
21
|
+
* **Docker Desktop**: Required to run the initialized project (provides MySQL, Redis, and admin UIs).
|
|
22
|
+
* **npm** (or pnpm/yarn): To install dependencies.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
To create a new project, simply run:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx create-tigra <project-name>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Follow the interactive prompts to configure your new server.
|
|
33
|
+
|
|
34
|
+
## What's Inside?
|
|
35
|
+
|
|
36
|
+
When you generate a project with `create-tigra`, you get a fully structured codebase:
|
|
37
|
+
|
|
38
|
+
* **Framework**: Fastify (v4+)
|
|
39
|
+
* **Language**: TypeScript (Strict mode)
|
|
40
|
+
* **ORM**: Prisma
|
|
41
|
+
* **Validation**: Zod (Type-safe schemas)
|
|
42
|
+
* **Testing**: Vitest
|
|
43
|
+
* **Documentation**: Swagger / OpenAPI (automatically generated)
|
|
44
|
+
* **Infrastructure**: Docker Compose for MySQL, Redis, and administration UIs.
|
|
45
|
+
|
|
46
|
+
## Getting Started
|
|
47
|
+
|
|
48
|
+
1. **Generate the project**:
|
|
49
|
+
```bash
|
|
50
|
+
npx create-tigra my-app
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
2. **Install Dependencies**:
|
|
54
|
+
```bash
|
|
55
|
+
cd my-app/server
|
|
56
|
+
npm install
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
3. **Start Infrastructure**:
|
|
60
|
+
Make sure Docker is running, then start the services:
|
|
61
|
+
```bash
|
|
62
|
+
docker-compose up -d
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
4. **Initialize Database**:
|
|
66
|
+
This command waits for the database to be ready and runs migrations:
|
|
67
|
+
```bash
|
|
68
|
+
npm run db:init
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
5. **Seed Database (Optional)**:
|
|
72
|
+
Populate the database with an admin user and sample data:
|
|
73
|
+
```bash
|
|
74
|
+
npm run prisma:seed
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
6. **Build and Start**:
|
|
78
|
+
```bash
|
|
79
|
+
npm run build
|
|
80
|
+
npm run dev
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Your server will be running at `http://localhost:3000`.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import prompts from 'prompts';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import ora from 'ora';
|
|
7
|
+
import fs from 'fs-extra';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
|
|
14
|
+
// ==============================================
|
|
15
|
+
// Case Transformation Utilities
|
|
16
|
+
// ==============================================
|
|
17
|
+
|
|
18
|
+
function toKebabCase(str) {
|
|
19
|
+
return str
|
|
20
|
+
.toLowerCase()
|
|
21
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
22
|
+
.replace(/^-|-$/g, '');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function toSnakeCase(str) {
|
|
26
|
+
return str
|
|
27
|
+
.toLowerCase()
|
|
28
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
29
|
+
.replace(/^_|_$/g, '');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function toTitleCase(str) {
|
|
33
|
+
return str
|
|
34
|
+
.replace(/[^a-z0-9]+/gi, ' ')
|
|
35
|
+
.split(' ')
|
|
36
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
|
|
37
|
+
.join(' ');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ==============================================
|
|
41
|
+
// Template Variable Replacement
|
|
42
|
+
// ==============================================
|
|
43
|
+
|
|
44
|
+
function generateSecureSecret(length = 32) {
|
|
45
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*';
|
|
46
|
+
let result = '';
|
|
47
|
+
for (let i = 0; i < length; i++) {
|
|
48
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function replaceTemplateVariables(content, config) {
|
|
54
|
+
const replacements = {
|
|
55
|
+
'{{PROJECT_NAME}}': config.projectName,
|
|
56
|
+
'{{PROJECT_NAME_SNAKE}}': config.projectNameSnake,
|
|
57
|
+
'{{PROJECT_DISPLAY_NAME}}': config.projectDisplayName,
|
|
58
|
+
'{{PROJECT_DESCRIPTION}}': config.projectDescription,
|
|
59
|
+
'{{DATABASE_NAME}}': config.databaseName,
|
|
60
|
+
'{{DATABASE_USER}}': config.databaseUser,
|
|
61
|
+
'{{DATABASE_PASSWORD}}': config.databasePassword,
|
|
62
|
+
'{{AUTHOR_NAME}}': config.authorName,
|
|
63
|
+
'{{JWT_SECRET}}': config.jwtSecret,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
let result = content;
|
|
67
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
68
|
+
result = result.split(key).join(value);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ==============================================
|
|
75
|
+
// Files to Process (relative to project root)
|
|
76
|
+
// ==============================================
|
|
77
|
+
|
|
78
|
+
const filesToProcess = [
|
|
79
|
+
// Root files
|
|
80
|
+
'CLAUDE.md',
|
|
81
|
+
// Server files
|
|
82
|
+
'server/package.json',
|
|
83
|
+
'server/.env',
|
|
84
|
+
'server/.env.example',
|
|
85
|
+
'server/docker-compose.yml',
|
|
86
|
+
'server/README.md',
|
|
87
|
+
'server/src/config/env.ts',
|
|
88
|
+
'server/prisma/schema.prisma',
|
|
89
|
+
'server/Tigra-API.postman_collection.json',
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
// Files/folders to exclude from template
|
|
93
|
+
const excludePatterns = [
|
|
94
|
+
'node_modules',
|
|
95
|
+
'dist',
|
|
96
|
+
'.git',
|
|
97
|
+
'package-lock.json',
|
|
98
|
+
'pnpm-lock.yaml',
|
|
99
|
+
'yarn.lock',
|
|
100
|
+
'coverage',
|
|
101
|
+
'build-errors.txt',
|
|
102
|
+
'.env.local',
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
// ==============================================
|
|
106
|
+
// Main CLI
|
|
107
|
+
// ==============================================
|
|
108
|
+
|
|
109
|
+
const program = new Command();
|
|
110
|
+
|
|
111
|
+
program
|
|
112
|
+
.name('create-tigra')
|
|
113
|
+
.description('Create a production-ready Fastify + TypeScript + Prisma API server')
|
|
114
|
+
.version('1.0.0')
|
|
115
|
+
.argument('[project-name]', 'Name of the project')
|
|
116
|
+
.option('-y, --yes', 'Skip prompts and use defaults')
|
|
117
|
+
.action(async (projectNameArg, options) => {
|
|
118
|
+
console.log();
|
|
119
|
+
console.log(chalk.bold.cyan(' Create Tigra'));
|
|
120
|
+
console.log(chalk.gray(' Production-ready Fastify + TypeScript + Prisma'));
|
|
121
|
+
console.log();
|
|
122
|
+
|
|
123
|
+
let projectName = projectNameArg;
|
|
124
|
+
|
|
125
|
+
// If no project name provided, prompt for it
|
|
126
|
+
if (!projectName) {
|
|
127
|
+
const response = await prompts({
|
|
128
|
+
type: 'text',
|
|
129
|
+
name: 'projectName',
|
|
130
|
+
message: 'Project name:',
|
|
131
|
+
initial: 'my-project',
|
|
132
|
+
validate: (value) =>
|
|
133
|
+
/^[a-z][a-z0-9-]*$/.test(value) ||
|
|
134
|
+
'Must start with letter, lowercase letters, numbers, and hyphens only',
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (!response.projectName) {
|
|
138
|
+
console.log(chalk.red('Cancelled.'));
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
projectName = response.projectName;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Validate project name
|
|
145
|
+
projectName = toKebabCase(projectName);
|
|
146
|
+
|
|
147
|
+
// Check if directory exists
|
|
148
|
+
const targetDir = path.join(process.cwd(), projectName);
|
|
149
|
+
if (fs.existsSync(targetDir)) {
|
|
150
|
+
console.log(chalk.red(`Error: Directory "${projectName}" already exists.`));
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Gather additional info (or use defaults)
|
|
155
|
+
let config;
|
|
156
|
+
if (options.yes) {
|
|
157
|
+
config = {
|
|
158
|
+
projectName,
|
|
159
|
+
projectNameSnake: toSnakeCase(projectName),
|
|
160
|
+
projectDisplayName: toTitleCase(projectName),
|
|
161
|
+
projectDescription: 'A production-ready REST API server',
|
|
162
|
+
databaseName: toSnakeCase(projectName) + '_db',
|
|
163
|
+
databaseUser: 'root',
|
|
164
|
+
databasePassword: 'password',
|
|
165
|
+
authorName: '',
|
|
166
|
+
jwtSecret: generateSecureSecret(48),
|
|
167
|
+
};
|
|
168
|
+
} else {
|
|
169
|
+
const answers = await prompts([
|
|
170
|
+
{
|
|
171
|
+
type: 'text',
|
|
172
|
+
name: 'projectDisplayName',
|
|
173
|
+
message: 'Display name:',
|
|
174
|
+
initial: toTitleCase(projectName),
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
type: 'text',
|
|
178
|
+
name: 'projectDescription',
|
|
179
|
+
message: 'Description (optional):',
|
|
180
|
+
initial: '',
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
type: 'text',
|
|
184
|
+
name: 'authorName',
|
|
185
|
+
message: 'Author name (optional):',
|
|
186
|
+
initial: '',
|
|
187
|
+
},
|
|
188
|
+
]);
|
|
189
|
+
|
|
190
|
+
if (!answers.projectDisplayName) {
|
|
191
|
+
console.log(chalk.red('Cancelled.'));
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
config = {
|
|
196
|
+
projectName,
|
|
197
|
+
projectNameSnake: toSnakeCase(projectName),
|
|
198
|
+
projectDisplayName: answers.projectDisplayName,
|
|
199
|
+
projectDescription: answers.projectDescription || '',
|
|
200
|
+
databaseName: toSnakeCase(projectName) + '_db',
|
|
201
|
+
databaseUser: 'root',
|
|
202
|
+
databasePassword: 'password',
|
|
203
|
+
authorName: answers.authorName || '',
|
|
204
|
+
jwtSecret: generateSecureSecret(48),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Copy template
|
|
209
|
+
const spinner = ora('Creating project...').start();
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
const templateDir = path.join(__dirname, '..', 'template');
|
|
213
|
+
|
|
214
|
+
// Filter function to exclude unwanted files/folders
|
|
215
|
+
const filterFunc = (src) => {
|
|
216
|
+
const relativePath = path.relative(templateDir, src);
|
|
217
|
+
// Always include the root
|
|
218
|
+
if (!relativePath) return true;
|
|
219
|
+
// Check against exclude patterns
|
|
220
|
+
return !excludePatterns.some(
|
|
221
|
+
(pattern) =>
|
|
222
|
+
relativePath === pattern ||
|
|
223
|
+
relativePath.includes(`${path.sep}${pattern}`) ||
|
|
224
|
+
relativePath.includes(`${pattern}${path.sep}`) ||
|
|
225
|
+
relativePath.startsWith(`${pattern}${path.sep}`)
|
|
226
|
+
);
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// Copy entire template directory to target
|
|
230
|
+
await fs.copy(templateDir, targetDir, { filter: filterFunc });
|
|
231
|
+
|
|
232
|
+
spinner.text = 'Replacing template variables...';
|
|
233
|
+
|
|
234
|
+
// Process files with template variables
|
|
235
|
+
for (const file of filesToProcess) {
|
|
236
|
+
const filePath = path.join(targetDir, file);
|
|
237
|
+
if (await fs.pathExists(filePath)) {
|
|
238
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
239
|
+
const replaced = replaceTemplateVariables(content, config);
|
|
240
|
+
await fs.writeFile(filePath, replaced, 'utf8');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
spinner.succeed('Project created successfully!');
|
|
245
|
+
|
|
246
|
+
// Print next steps
|
|
247
|
+
console.log();
|
|
248
|
+
console.log(chalk.green(` Done! Created ${chalk.bold(projectName)}`));
|
|
249
|
+
console.log();
|
|
250
|
+
console.log(' Project structure:');
|
|
251
|
+
console.log(chalk.gray(` ${projectName}/`));
|
|
252
|
+
console.log(chalk.gray(' ├── server/ # Backend API'));
|
|
253
|
+
console.log(chalk.gray(' ├── .agent/ # AI agent rules'));
|
|
254
|
+
console.log(chalk.gray(' ├── .claude/ # Claude Code rules'));
|
|
255
|
+
console.log(chalk.gray(' ├── .cursor/ # Cursor IDE rules'));
|
|
256
|
+
console.log(chalk.gray(' └── CLAUDE.md # Project rules'));
|
|
257
|
+
console.log();
|
|
258
|
+
console.log(' Next steps:');
|
|
259
|
+
console.log();
|
|
260
|
+
console.log(chalk.cyan(` cd ${projectName}/server`));
|
|
261
|
+
console.log(chalk.cyan(' npm install'));
|
|
262
|
+
console.log();
|
|
263
|
+
console.log(chalk.yellow(' Start Docker services (Docker must be running):'));
|
|
264
|
+
console.log(chalk.cyan(' docker-compose up -d'));
|
|
265
|
+
console.log();
|
|
266
|
+
console.log(chalk.yellow(' Initialize database (waits for MySQL to be ready):'));
|
|
267
|
+
console.log(chalk.cyan(' npm run db:init # Waits for DB + runs migration'));
|
|
268
|
+
console.log(chalk.cyan(' npm run prisma:seed # Seed database with admin + sample data'));
|
|
269
|
+
console.log();
|
|
270
|
+
console.log(chalk.yellow(' Build and start:'));
|
|
271
|
+
console.log(chalk.cyan(' npm run build # Build the project'));
|
|
272
|
+
console.log(chalk.cyan(' npm run dev # Start development server'));
|
|
273
|
+
console.log();
|
|
274
|
+
console.log(chalk.yellow(' Note on Docker:'));
|
|
275
|
+
console.log(chalk.gray(` Containers will be named: ${projectName}-mysql, ${projectName}-redis, etc.`));
|
|
276
|
+
console.log(chalk.gray(' Default ports: 3306 (MySQL), 6379 (Redis), 8080 (phpMyAdmin), 8081 (Redis UI)'));
|
|
277
|
+
console.log(chalk.gray(' If ports conflict, edit docker-compose.yml or stop other containers first.'));
|
|
278
|
+
console.log();
|
|
279
|
+
console.log(chalk.gray(' URLs after starting:'));
|
|
280
|
+
console.log(chalk.gray(' API Server: http://localhost:3000'));
|
|
281
|
+
console.log(chalk.gray(' API Docs: http://localhost:3000/docs'));
|
|
282
|
+
console.log(chalk.gray(' phpMyAdmin: http://localhost:8080 (root / password)'));
|
|
283
|
+
console.log(chalk.gray(' Redis UI: http://localhost:8081'));
|
|
284
|
+
console.log();
|
|
285
|
+
} catch (error) {
|
|
286
|
+
spinner.fail('Failed to create project');
|
|
287
|
+
console.error(chalk.red(error.message));
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-tigra",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Create a production-ready Fastify + TypeScript + Prisma API server",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"create",
|
|
8
|
+
"generator",
|
|
9
|
+
"scaffold",
|
|
10
|
+
"fastify",
|
|
11
|
+
"typescript",
|
|
12
|
+
"prisma",
|
|
13
|
+
"api",
|
|
14
|
+
"rest",
|
|
15
|
+
"boilerplate",
|
|
16
|
+
"starter"
|
|
17
|
+
],
|
|
18
|
+
"author": "",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/Makinloot/create-tigra.git"
|
|
23
|
+
},
|
|
24
|
+
"bin": {
|
|
25
|
+
"create-tigra": "bin/create-tigra.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin",
|
|
29
|
+
"template"
|
|
30
|
+
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.0.0"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"chalk": "^5.3.0",
|
|
36
|
+
"commander": "^12.1.0",
|
|
37
|
+
"fs-extra": "^11.2.0",
|
|
38
|
+
"ora": "^8.0.1",
|
|
39
|
+
"prompts": "^2.4.2"
|
|
40
|
+
}
|
|
41
|
+
}
|