create-fastpress 1.2.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/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.2.0] - 2026-03-12
9
+
10
+ ### Added
11
+ - Interactive CLI with user-friendly prompts using @clack/prompts
12
+ - Database adapter selection (PostgreSQL, MySQL/MariaDB, SQLite)
13
+ - Automatic FastPress configuration generation based on selected adapter
14
+ - Environment variables template generation
15
+ - Prisma schema provider configuration
16
+ - Complete project template with sample module
17
+
18
+ ### Changed
19
+ - Enhanced project creation workflow with better user experience
20
+ - Improved error handling and validation
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 create-fastpress
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,110 @@
1
+ # create-fastpress
2
+
3
+ [![npm version](https://img.shields.io/npm/v/create-fastpress.svg)](https://www.npmjs.com/package/create-fastpress)
4
+ [![npm downloads](https://img.shields.io/npm/dm/create-fastpress.svg)](https://www.npmjs.com/package/create-fastpress)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ Official CLI tool for **[FastPress](https://www.npmjs.com/package/@cristianrg/fastpress)** - The simple and fast backend framework for building backend applications with TypeScript and Prisma.
8
+
9
+ ## 🚀 Quick Start
10
+
11
+ Create a new FastPress project in seconds:
12
+
13
+ ```bash
14
+ npx create-fastpress
15
+ ```
16
+
17
+ That's it! The CLI will guide you through the setup process interactively.
18
+
19
+ ![fastpress-cli](resources/fastpress-cli.gif)
20
+
21
+ ## ✨ Features
22
+
23
+ - 🎯 **Interactive CLI** - User-friendly prompts guide you through project setup
24
+ - 🗄️ **Database Adapter Selection** - Choose from PostgreSQL, MySQL/MariaDB, or SQLite
25
+ - 📦 **Ready-to-use Template** - Complete project structure with best practices
26
+ - ⚡ **Quick Setup** - Get started in seconds with sensible defaults
27
+ - 🔧 **Pre-configured** - Prisma, TypeScript, and FastPress configured out of the box
28
+
29
+ ## 📋 Prerequisites
30
+
31
+ - **Node.js** >= 18.0.0
32
+ - **npm**, **pnpm**, or **yarn**
33
+
34
+ ## 🎨 What You'll Get
35
+
36
+ Running `npx create-fastpress` will create a new project with:
37
+
38
+ - ✅ Complete FastPress project structure
39
+ - ✅ TypeScript configuration
40
+ - ✅ Prisma ORM setup with your chosen database adapter
41
+ - ✅ Sample module (controller, service, and Zod schemas)
42
+ - ✅ Environment variables template (.env)
43
+ - ✅ FastPress configuration file
44
+ - ✅ Ready-to-use scripts (dev, build, setup)
45
+
46
+ ## 🛠️ Usage
47
+
48
+ ### Interactive Mode (Recommended)
49
+
50
+ Simply run:
51
+
52
+ ```bash
53
+ npx create-fastpress
54
+ ```
55
+
56
+ The CLI will prompt you for:
57
+ 1. **Project name** - Your new project directory name
58
+ 2. **Database adapter** - Choose your preferred database:
59
+ - PostgreSQL
60
+ - MySQL/MariaDB
61
+ - SQLite
62
+ - Skip adapter setup (configure later)
63
+
64
+ ### Next Steps
65
+
66
+ After creating your project:
67
+
68
+ ```bash
69
+ # 1. Navigate to your project
70
+ cd your-project-name
71
+
72
+ # 2. Install dependencies
73
+ npm install
74
+
75
+ # 3. Configure your database connection in .env file
76
+ # (Already templated with sensible defaults)
77
+
78
+ # 4. Run database setup
79
+ npm run setup
80
+
81
+ # 5. Start development server
82
+ npm run dev
83
+ ```
84
+
85
+ Your FastPress API will be running! 🎉
86
+
87
+ ## 📚 Documentation
88
+
89
+ For more information about FastPress framework:
90
+
91
+ - **NPM Package**: [@cristianrg/fastpress](https://www.npmjs.com/package/@cristianrg/fastpress)
92
+ - **GitHub**: [FastPress Repository](https://github.com/CristianRG/fastpress#readme)
93
+
94
+ ## 🤝 Contributing
95
+
96
+ Contributions, issues, and feature requests are welcome! Feel free to check the [issues page](https://github.com/CristianRG/create-fastpress/issues).
97
+
98
+ ## 📝 License
99
+
100
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
101
+
102
+ ## 👨‍💻 Author
103
+
104
+ Created with 💙 by **Cristian Alexander Rizo Gómez**
105
+
106
+ - GitHub: [@CristianRG](https://github.com/CristianRG)
107
+
108
+ ## ⭐ Support
109
+
110
+ If you find this project useful, please consider giving it a star on [GitHub](https://github.com/CristianRG/create-fastpress)!
package/dist/index.js ADDED
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import chalk from 'chalk';
4
+ import * as p from '@clack/prompts';
5
+ import { readFileSync, writeFileSync } from 'fs';
6
+ import { join } from 'path';
7
+ import { __project_dirname } from './utils.js';
8
+ import { existsSync, mkdirSync, copyFileSync, readdirSync, statSync } from 'fs';
9
+ const packageJson = JSON.parse(readFileSync(join(__project_dirname, '../package.json'), 'utf-8'));
10
+ const program = new Command();
11
+ const copyFolder = (src, dest, excludeFiles = []) => {
12
+ if (!existsSync(dest)) {
13
+ mkdirSync(dest);
14
+ }
15
+ const entries = readdirSync(src, { withFileTypes: true });
16
+ for (const entry of entries) {
17
+ // Skip excluded files
18
+ if (excludeFiles.includes(entry.name)) {
19
+ continue;
20
+ }
21
+ const srcPath = join(src, entry.name);
22
+ const destPath = join(dest, entry.name);
23
+ const stats = statSync(srcPath);
24
+ if (stats.isDirectory()) {
25
+ copyFolder(srcPath, destPath, excludeFiles);
26
+ }
27
+ else if (stats.isFile()) {
28
+ copyFileSync(srcPath, destPath);
29
+ }
30
+ }
31
+ };
32
+ const getAdapterProvider = (adapterName) => {
33
+ const providerMap = {
34
+ '@prisma/adapter-pg': 'postgresql',
35
+ '@prisma/adapter-mariadb': 'mysql',
36
+ '@prisma/adapter-better-sqlite3': 'sqlite'
37
+ };
38
+ return providerMap[adapterName] || 'sqlite';
39
+ };
40
+ const generateFastpressConfig = (adapterName) => {
41
+ const configs = {
42
+ '@prisma/adapter-pg': {
43
+ import: 'import { PrismaPg } from "@prisma/adapter-pg";',
44
+ className: 'PrismaPg',
45
+ config: 'new PrismaPg({ connectionString: process.env["DATABASE_URL"] || "postgresql://user:password@localhost:5432/mydb" })',
46
+ docUrl: 'https://www.prisma.io/docs/orm/core-concepts/supported-databases/postgresql#using-driver-adapters'
47
+ },
48
+ '@prisma/adapter-mariadb': {
49
+ import: 'import { PrismaMariaDb } from "@prisma/adapter-mariadb";',
50
+ className: 'PrismaMariaDb',
51
+ config: `new PrismaMariaDb({
52
+ host: process.env["DATABASE_HOST"] || "localhost",
53
+ port: parseInt(process.env["DATABASE_PORT"] || "3306"),
54
+ connectionLimit: 5,
55
+ })`,
56
+ docUrl: 'https://www.prisma.io/docs/orm/core-concepts/supported-databases/mysql#using-driver-adapters'
57
+ },
58
+ '@prisma/adapter-better-sqlite3': {
59
+ import: 'import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";',
60
+ className: 'PrismaBetterSqlite3',
61
+ config: 'new PrismaBetterSqlite3({ url: process.env["DATABASE_URL"] || "file:./prisma/dev.db" })',
62
+ docUrl: 'https://www.prisma.io/docs/orm/core-concepts/supported-databases/sqlite#using-driver-adapters'
63
+ }
64
+ };
65
+ const adapterConfig = configs[adapterName];
66
+ if (!adapterConfig) {
67
+ // No adapter selected
68
+ return `import { defineFastPressConfig } from "@cristianrg/fastpress";
69
+
70
+ export default defineFastPressConfig({
71
+ server: {
72
+ // Configure your Prisma adapter here
73
+ // See: https://www.prisma.io/docs/orm/core-concepts/supported-databases
74
+ }
75
+ })`;
76
+ }
77
+ return `import { defineFastPressConfig } from "@cristianrg/fastpress";
78
+ ${adapterConfig.import}
79
+
80
+ // For more information about this adapter, visit:
81
+ // ${adapterConfig.docUrl}
82
+
83
+ export default defineFastPressConfig({
84
+ server: {
85
+ prismaAdapter: ${adapterConfig.config}
86
+ }
87
+ })`;
88
+ };
89
+ const generateEnvFile = (adapterName) => {
90
+ const envConfigs = {
91
+ '@prisma/adapter-pg': 'DATABASE_URL=postgresql://user:password@localhost:5432/mydb',
92
+ '@prisma/adapter-mariadb': 'DATABASE_URL=mysql://user:password@localhost:3306/mydb',
93
+ '@prisma/adapter-better-sqlite3': 'DATABASE_URL=file:./prisma/dev.db'
94
+ };
95
+ return envConfigs[adapterName] || 'DATABASE_URL=sqlite:./dev.db';
96
+ };
97
+ const createProject = async (projectName, adapter) => {
98
+ const projectDir = join(process.cwd(), projectName);
99
+ if (!existsSync(projectDir)) {
100
+ mkdirSync(projectDir);
101
+ }
102
+ else {
103
+ console.error(chalk.red(`Directory ${projectName} already exists. Please choose a different name or remove the existing directory.`));
104
+ process.exit(1);
105
+ }
106
+ const templateDir = join(__project_dirname, '..', 'src', 'template');
107
+ if (existsSync(templateDir) && statSync(templateDir).isDirectory()) {
108
+ const files = readdirSync(templateDir);
109
+ copyFolder(templateDir, projectDir, ['fastpress.config.ts', '.env']);
110
+ }
111
+ else {
112
+ console.error(chalk.red('Template directory not found. Please ensure the template files are in place.'));
113
+ process.exit(1);
114
+ }
115
+ const fastpressConfigPath = join(projectDir, 'fastpress.config.ts');
116
+ const fastpressConfigContent = generateFastpressConfig(adapter.name);
117
+ writeFileSync(fastpressConfigPath, fastpressConfigContent);
118
+ const envPath = join(projectDir, '.env');
119
+ const envContent = generateEnvFile(adapter.name);
120
+ writeFileSync(envPath, envContent);
121
+ const schemaPath = join(projectDir, 'prisma', 'schema.prisma');
122
+ if (existsSync(schemaPath)) {
123
+ const schemaContent = readFileSync(schemaPath, 'utf-8');
124
+ const provider = getAdapterProvider(adapter.name);
125
+ const updatedSchema = schemaContent.replace(/(datasource\s+db\s*\{[^}]*provider\s*=\s*)"[^"]+"/, `$1"${provider}"`);
126
+ writeFileSync(schemaPath, updatedSchema);
127
+ }
128
+ const projectPackageJsonPath = join(projectDir, 'package.json');
129
+ if (existsSync(projectPackageJsonPath)) {
130
+ const projectPackageJson = JSON.parse(readFileSync(projectPackageJsonPath, 'utf-8'));
131
+ projectPackageJson.dependencies['@cristianrg/fastpress'] = `^${packageJson.version}`;
132
+ projectPackageJson.name = projectName;
133
+ if (adapter.name !== 'none') {
134
+ projectPackageJson.dependencies[adapter.name] = adapter.version;
135
+ }
136
+ writeFileSync(projectPackageJsonPath, JSON.stringify(projectPackageJson, null, 2));
137
+ }
138
+ else {
139
+ console.error(chalk.red('package.json not found in the template. Please ensure the template files are in place.'));
140
+ process.exit(1);
141
+ }
142
+ console.log(chalk.green(`Project ${projectName} created successfully!`));
143
+ console.log(chalk.green(`Next steps:`));
144
+ console.log(chalk.green(`1. Navigate to your project directory: cd ${projectName}`));
145
+ console.log(chalk.green(`2. Install dependencies: npm install`));
146
+ console.log(chalk.green(`3. Set up your database connection string in the .env file`));
147
+ console.log(chalk.green(`4. Run Setup script to initialize the database: npm run setup`));
148
+ console.log(chalk.green(`5. Start the development server: npm run dev`));
149
+ };
150
+ const createFastpress = async () => {
151
+ console.log(chalk.green(`Welcome to Fastpress ${packageJson.version}!`));
152
+ console.log(chalk.gray(`Current directory: ${process.cwd()}`));
153
+ p.intro(chalk.green('Let\'s create your Fastpress project!'));
154
+ const project = await p.group({
155
+ path: () => p.text({
156
+ message: 'What is the name of your project?',
157
+ placeholder: 'my-fastpress-app',
158
+ validate: (value) => {
159
+ if (!value)
160
+ return 'Project name is required';
161
+ if (value.includes(' '))
162
+ return 'Project name cannot contain spaces';
163
+ },
164
+ }),
165
+ type: ({ results }) => p.select({
166
+ message: 'Select your prisma adapter',
167
+ options: [
168
+ { value: '@prisma/adapter-pg', label: 'PostgreSQL' },
169
+ { value: '@prisma/adapter-mariadb', label: 'MySQL/MariaDB' },
170
+ { value: '@prisma/adapter-better-sqlite3', label: 'SQLite' },
171
+ { value: 'none', label: 'Skip adapter setup' }
172
+ ]
173
+ })
174
+ }, {
175
+ onCancel: () => {
176
+ p.cancel('Project creation cancelled.');
177
+ process.exit(0);
178
+ }
179
+ });
180
+ p.outro(chalk.green(`Creating project ${project.path}${project.type !== 'none' ? ` with adapter ${project.type}` : ''}...`));
181
+ await createProject(project.path, { name: project.type, version: 'latest' });
182
+ };
183
+ program
184
+ .version(packageJson.version)
185
+ .description('Create a new Fastpress project')
186
+ .action(() => {
187
+ createFastpress();
188
+ });
189
+ if (process.argv.length === 2) {
190
+ createFastpress();
191
+ }
192
+ else {
193
+ program.parse(process.argv);
194
+ }
package/dist/utils.js ADDED
@@ -0,0 +1,5 @@
1
+ import { dirname } from 'path';
2
+ import { fileURLToPath } from 'url';
3
+ const __filename = fileURLToPath(import.meta.url);
4
+ const __project_dirname = dirname(__filename);
5
+ export { __project_dirname };
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "create-fastpress",
3
+ "version": "1.2.0",
4
+ "description": "Official CLI for FastPress, the simple and fast backend framework for building backend applications with TypeScript and Prisma.",
5
+ "main": "dist/index.js",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/CristianRG/create-fastpress.git"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/CristianRG/create-fastpress/issues"
12
+ },
13
+ "homepage": "https://github.com/CristianRG/create-fastpress#readme",
14
+ "bin": {
15
+ "create-fastpress": "dist/index.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "src/template",
20
+ "README.md",
21
+ "LICENSE",
22
+ "CHANGELOG.md"
23
+ ],
24
+ "engines": {
25
+ "node": ">=18.0.0"
26
+ },
27
+ "keywords": [
28
+ "fastpress",
29
+ "cli",
30
+ "typescript",
31
+ "prisma",
32
+ "api",
33
+ "backend",
34
+ "framework",
35
+ "scaffold",
36
+ "generator",
37
+ "create-app",
38
+ "boilerplate"
39
+ ],
40
+ "type": "module",
41
+ "author": "Cristian Alexander Rizo Gómez",
42
+ "license": "MIT",
43
+ "devDependencies": {
44
+ "@types/node": "25.3.0",
45
+ "tsc-alias": "1.8.16",
46
+ "typescript": "5.9.3"
47
+ },
48
+ "dependencies": {
49
+ "@clack/prompts": "1.0.1",
50
+ "chalk": "5.6.2",
51
+ "commander": "14.0.3"
52
+ },
53
+ "scripts": {
54
+ "build": "tsc && tsc-alias",
55
+ "start": "node dist/index.js",
56
+ "pack:check": "npm pack --dry-run"
57
+ }
58
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "my-fastpress-app",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "build": "tsc",
8
+ "start": "node dist/index.js",
9
+ "dev": "nodemon --watch src --ext ts --exec \"npm run build && npm start\"",
10
+ "setup": "npx prisma migrate dev --name init && npx prisma generate"
11
+ },
12
+ "dependencies": {
13
+ "@cristianrg/fastpress": "^1.2.0",
14
+ "@prisma/client": ">=5.0.0",
15
+ "zod": "4.3.6"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^25.3.3",
19
+ "prisma": ">=5.0.0",
20
+ "typescript": "^5.9.3",
21
+ "nodemon": "^3.1.11"
22
+ }
23
+ }
@@ -0,0 +1,32 @@
1
+ // This is your Prisma schema file,
2
+ // learn more about it in the docs: https://pris.ly/d/prisma-schema
3
+
4
+ // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
5
+ // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
6
+
7
+ generator client {
8
+ provider = "prisma-client-js"
9
+ }
10
+
11
+ datasource db {
12
+ provider = "sqlite"
13
+ }
14
+
15
+ model User {
16
+ id String @id @default(uuid())
17
+ name String
18
+ email String @unique
19
+ password String
20
+
21
+ sessions Session[]
22
+ }
23
+
24
+ model Session {
25
+ id String @id @default(uuid())
26
+ userId String
27
+ token String @unique
28
+ createdAt DateTime @default(now())
29
+ expiresAt DateTime
30
+
31
+ user User @relation(fields: [userId], references: [id])
32
+ }
@@ -0,0 +1,14 @@
1
+ // This file was generated by Prisma, and assumes you have installed the following:
2
+ // npm install --save-dev prisma dotenv
3
+ import "dotenv/config";
4
+ import { defineConfig } from "prisma/config";
5
+
6
+ export default defineConfig({
7
+ schema: "prisma/schema.prisma",
8
+ migrations: {
9
+ path: "prisma/migrations",
10
+ },
11
+ datasource: {
12
+ url: process.env["DATABASE_URL"],
13
+ },
14
+ });
@@ -0,0 +1,20 @@
1
+ import { createServer } from "@cristianrg/fastpress";
2
+
3
+ // You can register your controllers, services, and other modules here if needed.
4
+ // Remember all .controller.ts files in the src/modules directory are automatically registered as controllers by FastPress, so you don't need to manually import them here unless you want to customize their registration
5
+ // or if you want to register internal modules by fastpress that are not in the src/modules directory.
6
+ // For example:
7
+
8
+ /*
9
+ import { createServer, AuthController } from '@cristianrg/fastpress';
10
+
11
+ await createServer({
12
+ controllers: [AuthController],
13
+ });
14
+
15
+ */
16
+
17
+ createServer((app) => {
18
+ console.log("Your FastPress server is running!");
19
+ console.log("Visit http://localhost:3000/hello to see the Hello World controller in action.");
20
+ });
@@ -0,0 +1,7 @@
1
+ import z from "zod";
2
+
3
+ const HelloWorldSchema = z.object({
4
+ who: z.string().optional()
5
+ });
6
+
7
+ export { HelloWorldSchema };
@@ -0,0 +1,29 @@
1
+ import { Controller, Get, Post, Body, ZodValidationPipe, ServerResponse } from "@cristianrg/fastpress";
2
+ import { HelloWorldSchema } from "./helloword.zod";
3
+ import z from "zod";
4
+ import { HelloWorldService } from "./helloworld.service";
5
+
6
+ @Controller("/hello")
7
+ class HelloworldController {
8
+
9
+ @Get("/")
10
+ async getHelloWorld() {
11
+ const message = HelloWorldService.getHelloWorld();
12
+ return new ServerResponse(200, message);
13
+ }
14
+
15
+ /*
16
+ * This endpoint demonstrates how to use Zod for validating request bodies in FastPress.
17
+ * It accepts an optional "who" parameter in the request body, which defaults to "World" if not provided.
18
+ */
19
+ @Post("/")
20
+ async postHelloWorld(
21
+ @Body(undefined, new ZodValidationPipe(HelloWorldSchema)) body: z.infer<typeof HelloWorldSchema>
22
+ ) {
23
+ const who = body.who || "World";
24
+ const message = `Hello, ${who}!`;
25
+ return new ServerResponse(200, message);
26
+ }
27
+ }
28
+
29
+ export default HelloworldController;
@@ -0,0 +1,8 @@
1
+ class HelloWorldService {
2
+
3
+ static getHelloWorld(): string {
4
+ return "Hello, World!";
5
+ }
6
+ }
7
+
8
+ export { HelloWorldService }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "experimentalDecorators": true,
15
+ "emitDecoratorMetadata": true,
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }