scaffy-tool 0.2.0 → 1.0.1
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 +21 -26
- package/cli.js +18 -41
- package/core/detector.js +5 -31
- package/core/executor.js +5 -27
- package/core/interviewer.js +15 -19
- package/core/plugin-validator.js +1 -1
- package/core/registry.js +47 -28
- package/core/utils.js +2 -19
- package/package.json +11 -11
- package/registry/go/gin/plugin.json +23 -0
- package/registry/go/gin/v1/questions.js +19 -0
- package/registry/go/gin/v1/scaffold.js +196 -0
- package/registry/index.json +4 -4
- package/registry/javascript/expressjs/plugin.json +44 -0
- package/registry/javascript/expressjs/v4/questions.js +43 -0
- package/registry/javascript/expressjs/v4/scaffold.js +236 -0
- package/registry/javascript/nestjs/plugin.json +2 -2
- package/registry/javascript/nestjs/v10/questions.js +6 -4
- package/registry/javascript/nestjs/v10/scaffold.js +1 -1
- package/registry/javascript/nestjs/v11/questions.js +61 -0
- package/registry/javascript/nestjs/v11/scaffold.js +94 -0
- package/registry/javascript/nextjs/plugin.json +44 -0
- package/registry/javascript/nextjs/v14/questions.js +44 -0
- package/registry/javascript/nextjs/v14/scaffold.js +57 -0
- package/registry/javascript/vuejs/v3/questions.js +5 -3
- package/registry/javascript/vuejs/v3/scaffold.js +3 -10
- package/registry/php/laravel/plugin.json +2 -2
- package/registry/php/laravel/v11/questions.js +3 -3
- package/registry/php/laravel/v11/scaffold.js +1 -1
- package/registry/php/laravel/v12/questions.js +45 -0
- package/registry/php/laravel/v12/scaffold.js +46 -0
- package/registry/php/laravel/v13/questions.js +28 -0
- package/registry/php/laravel/v13/scaffold.js +46 -0
- package/registry/php/laravel/v13/test/.gitkeep +0 -0
- package/registry/php/laravel/v13/test/questions.test.js +48 -0
- package/registry/php/laravel/v13/test/scaffold.test.js +105 -0
- package/registry/php/symfony/plugin.json +35 -0
- package/registry/php/symfony/v7/questions.js +19 -0
- package/registry/php/symfony/v7/scaffold.js +74 -0
- package/registry/python/django/plugin.json +35 -0
- package/registry/python/django/v5/questions.js +24 -0
- package/registry/python/django/v5/scaffold.js +107 -0
- package/registry/python/fastapi/plugin.json +35 -0
- package/registry/python/fastapi/v1/questions.js +25 -0
- package/registry/python/fastapi/v1/scaffold.js +180 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
export default async (answers, utils) => {
|
|
2
|
+
const { projectName, database, async: useAsync, docker } = answers;
|
|
3
|
+
|
|
4
|
+
utils.title('Creating FastAPI Project');
|
|
5
|
+
|
|
6
|
+
// ─── Step 1: Create project folder ────────────────────
|
|
7
|
+
utils.step(1, 'Creating project structure');
|
|
8
|
+
await utils.run(`mkdir ${projectName}`);
|
|
9
|
+
await utils.run(`mkdir ${projectName}/app`);
|
|
10
|
+
|
|
11
|
+
// ─── Step 2: Create virtual environment ───────────────
|
|
12
|
+
utils.step(2, 'Creating virtual environment');
|
|
13
|
+
await utils.runInProject(projectName, 'python3 -m venv venv');
|
|
14
|
+
|
|
15
|
+
// ─── Step 3: Install FastAPI + Uvicorn ────────────────
|
|
16
|
+
utils.step(3, 'Installing FastAPI and Uvicorn');
|
|
17
|
+
await utils.runInProject(
|
|
18
|
+
projectName,
|
|
19
|
+
'venv/bin/pip install "fastapi>=0.100.0" "uvicorn[standard]"'
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// ─── Step 4: Database drivers ─────────────────────────
|
|
23
|
+
if (database !== 'none') {
|
|
24
|
+
utils.step(4, 'Installing database dependencies');
|
|
25
|
+
await utils.runInProject(
|
|
26
|
+
projectName,
|
|
27
|
+
'venv/bin/pip install sqlalchemy alembic'
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
if (database === 'postgresql') {
|
|
31
|
+
const driver = useAsync ? 'asyncpg' : 'psycopg2-binary';
|
|
32
|
+
await utils.runInProject(projectName, `venv/bin/pip install ${driver}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (database === 'mysql') {
|
|
36
|
+
const driver = useAsync ? 'aiomysql' : 'mysqlclient';
|
|
37
|
+
await utils.runInProject(projectName, `venv/bin/pip install ${driver}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (database === 'sqlite' && useAsync) {
|
|
41
|
+
await utils.runInProject(projectName, 'venv/bin/pip install aiosqlite');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ─── Step 5: Generate main.py ─────────────────────────
|
|
46
|
+
utils.step(5, 'Generating application files');
|
|
47
|
+
|
|
48
|
+
const mainPy = `from fastapi import FastAPI
|
|
49
|
+
|
|
50
|
+
app = FastAPI(title="${projectName}", version="0.1.0")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@app.get("/")
|
|
54
|
+
${useAsync ? 'async ' : ''}def root():
|
|
55
|
+
return {"message": "Hello from ${projectName}"}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@app.get("/health")
|
|
59
|
+
${useAsync ? 'async ' : ''}def health():
|
|
60
|
+
return {"status": "ok"}
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
await utils.createFile(`${projectName}/app/main.py`, mainPy);
|
|
64
|
+
|
|
65
|
+
// ─── Step 6: Generate database.py if needed ───────────
|
|
66
|
+
if (database !== 'none') {
|
|
67
|
+
const dsnMap = {
|
|
68
|
+
postgresql: useAsync
|
|
69
|
+
? `postgresql+asyncpg://user:password@localhost/${projectName}`
|
|
70
|
+
: `postgresql+psycopg2://user:password@localhost/${projectName}`,
|
|
71
|
+
mysql: useAsync
|
|
72
|
+
? `mysql+aiomysql://user:password@localhost/${projectName}`
|
|
73
|
+
: `mysql+mysqlclient://user:password@localhost/${projectName}`,
|
|
74
|
+
sqlite: useAsync
|
|
75
|
+
? `sqlite+aiosqlite:///./data.db`
|
|
76
|
+
: `sqlite:///./data.db`,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const databasePy = `from sqlalchemy${useAsync ? '.ext.asyncio' : ''} import create_engine${useAsync ? ', AsyncSession' : ''}, sessionmaker
|
|
80
|
+
from sqlalchemy.orm import DeclarativeBase
|
|
81
|
+
|
|
82
|
+
DATABASE_URL = "${dsnMap[database]}"
|
|
83
|
+
|
|
84
|
+
${
|
|
85
|
+
useAsync
|
|
86
|
+
? `engine = create_engine(DATABASE_URL)
|
|
87
|
+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)`
|
|
88
|
+
: `engine = create_engine(DATABASE_URL)
|
|
89
|
+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)`
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class Base(DeclarativeBase):
|
|
94
|
+
pass
|
|
95
|
+
`;
|
|
96
|
+
await utils.createFile(`${projectName}/app/database.py`, databasePy);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ─── Step 7: Generate __init__.py ─────────────────────
|
|
100
|
+
await utils.createFile(`${projectName}/app/__init__.py`, '');
|
|
101
|
+
|
|
102
|
+
// ─── Step 8: requirements.txt ─────────────────────────
|
|
103
|
+
utils.step(6, 'Generating requirements.txt');
|
|
104
|
+
|
|
105
|
+
const requirements = ['fastapi>=0.100.0', 'uvicorn[standard]'];
|
|
106
|
+
|
|
107
|
+
if (database !== 'none') {
|
|
108
|
+
requirements.push('sqlalchemy');
|
|
109
|
+
requirements.push('alembic');
|
|
110
|
+
if (database === 'postgresql')
|
|
111
|
+
requirements.push(useAsync ? 'asyncpg' : 'psycopg2-binary');
|
|
112
|
+
if (database === 'mysql')
|
|
113
|
+
requirements.push(useAsync ? 'aiomysql' : 'mysqlclient');
|
|
114
|
+
if (database === 'sqlite' && useAsync) requirements.push('aiosqlite');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
await utils.createFile(
|
|
118
|
+
`${projectName}/requirements.txt`,
|
|
119
|
+
requirements.join('\n') + '\n'
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// ─── Step 9: Docker ───────────────────────────────────
|
|
123
|
+
if (docker) {
|
|
124
|
+
utils.step(7, 'Creating Docker config');
|
|
125
|
+
|
|
126
|
+
const dockerfile = `FROM python:3.12-slim
|
|
127
|
+
|
|
128
|
+
WORKDIR /app
|
|
129
|
+
|
|
130
|
+
COPY requirements.txt .
|
|
131
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
132
|
+
|
|
133
|
+
COPY . .
|
|
134
|
+
|
|
135
|
+
EXPOSE 8000
|
|
136
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
|
137
|
+
`;
|
|
138
|
+
|
|
139
|
+
const dockerCompose = `version: '3.8'
|
|
140
|
+
services:
|
|
141
|
+
web:
|
|
142
|
+
build: .
|
|
143
|
+
ports:
|
|
144
|
+
- "8000:8000"
|
|
145
|
+
volumes:
|
|
146
|
+
- .:/app
|
|
147
|
+
${
|
|
148
|
+
database === 'postgresql'
|
|
149
|
+
? ` db:
|
|
150
|
+
image: postgres:15
|
|
151
|
+
environment:
|
|
152
|
+
POSTGRES_PASSWORD: password
|
|
153
|
+
POSTGRES_DB: ${projectName}
|
|
154
|
+
ports:
|
|
155
|
+
- "5432:5432"`
|
|
156
|
+
: ''
|
|
157
|
+
}
|
|
158
|
+
${
|
|
159
|
+
database === 'mysql'
|
|
160
|
+
? ` db:
|
|
161
|
+
image: mysql:8.0
|
|
162
|
+
environment:
|
|
163
|
+
MYSQL_ROOT_PASSWORD: password
|
|
164
|
+
MYSQL_DATABASE: ${projectName}
|
|
165
|
+
ports:
|
|
166
|
+
- "3306:3306"`
|
|
167
|
+
: ''
|
|
168
|
+
}
|
|
169
|
+
`;
|
|
170
|
+
|
|
171
|
+
await utils.createFile(`${projectName}/Dockerfile`, dockerfile);
|
|
172
|
+
await utils.createFile(`${projectName}/docker-compose.yml`, dockerCompose);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
utils.success(`FastAPI project "${projectName}" created successfully!`);
|
|
176
|
+
utils.log(` cd ${projectName}`);
|
|
177
|
+
utils.log(` source venv/bin/activate`);
|
|
178
|
+
utils.log(` uvicorn app.main:app --reload`);
|
|
179
|
+
utils.log(` Docs: http://localhost:8000/docs`);
|
|
180
|
+
};
|