phos 1.0.1 ā 1.0.2
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 +2 -1
- package/package.json +5 -1
- package/src/templates/frontend/astro/.vscode/extensions.json +4 -0
- package/src/templates/frontend/astro/.vscode/launch.json +11 -0
- package/src/templates/frontend/svelte/.vscode/settings.json +5 -0
- package/.eslintignore +0 -3
- package/AGENTS.md +0 -172
- package/CHANGELOG.md +0 -202
- package/bun.lock +0 -125
- package/src/cli.ts +0 -500
- package/src/generators/backends/elysia.ts +0 -45
- package/src/generators/backends/fastapi.ts +0 -71
- package/src/generators/frontends/astro.ts +0 -37
- package/src/generators/frontends/nextjs.ts +0 -37
- package/src/generators/frontends/svelte.ts +0 -38
- package/src/generators/monorepo.ts +0 -529
- package/src/generators/single.ts +0 -465
- package/src/utils/helpers.ts +0 -198
- package/tsconfig.json +0 -24
package/src/generators/single.ts
DELETED
|
@@ -1,465 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createDirectory,
|
|
3
|
-
writeFile,
|
|
4
|
-
getProjectPath,
|
|
5
|
-
logStep,
|
|
6
|
-
logSuccess,
|
|
7
|
-
logInfo,
|
|
8
|
-
initializeGit,
|
|
9
|
-
type GeneratorConfig,
|
|
10
|
-
capitalize,
|
|
11
|
-
} from "@/utils/helpers.js";
|
|
12
|
-
import { generateElysiaBackend } from "@/generators/backends/elysia.js";
|
|
13
|
-
import { generateFastAPIBackend } from "@/generators/backends/fastapi.js";
|
|
14
|
-
import { generateAstroFrontend } from "@/generators/frontends/astro.js";
|
|
15
|
-
import { generateSvelteFrontend } from "@/generators/frontends/svelte.js";
|
|
16
|
-
import { generateNextJSFrontend } from "@/generators/frontends/nextjs.js";
|
|
17
|
-
|
|
18
|
-
export async function generateSingle(config: GeneratorConfig): Promise<void> {
|
|
19
|
-
const projectPath = getProjectPath(config.projectName);
|
|
20
|
-
|
|
21
|
-
logStep(`Creating single project at ${projectPath}`);
|
|
22
|
-
await createDirectory(projectPath);
|
|
23
|
-
|
|
24
|
-
const docsPath = `${projectPath}/Docs`;
|
|
25
|
-
await createDirectory(docsPath);
|
|
26
|
-
|
|
27
|
-
await generateGitIgnore(projectPath);
|
|
28
|
-
await generateReadme(projectPath, config);
|
|
29
|
-
await generateAgentsMd(projectPath, config);
|
|
30
|
-
await generateLicense(projectPath, config);
|
|
31
|
-
await generateEnvExample(projectPath);
|
|
32
|
-
|
|
33
|
-
if (config.backend?.framework) {
|
|
34
|
-
await createDirectory(`${projectPath}/src`);
|
|
35
|
-
switch (config.backend.framework) {
|
|
36
|
-
case "elysia":
|
|
37
|
-
await generateElysiaBackend(projectPath, config);
|
|
38
|
-
break;
|
|
39
|
-
case "fastapi":
|
|
40
|
-
await generateFastAPIBackend(projectPath, config);
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
} else if (config.frontend?.framework) {
|
|
44
|
-
await createDirectory(`${projectPath}/src`);
|
|
45
|
-
switch (config.frontend.framework) {
|
|
46
|
-
case "astro":
|
|
47
|
-
await generateAstroFrontend(projectPath, config);
|
|
48
|
-
break;
|
|
49
|
-
case "svelte":
|
|
50
|
-
await generateSvelteFrontend(projectPath, config);
|
|
51
|
-
break;
|
|
52
|
-
case "nextjs":
|
|
53
|
-
await generateNextJSFrontend(projectPath, config);
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
await createDirectory(`${docsPath}/Feature`);
|
|
59
|
-
await createDirectory(`${docsPath}/DatabaseSetup`);
|
|
60
|
-
await generateSchemaDocs(docsPath, config);
|
|
61
|
-
|
|
62
|
-
logSuccess(`Project created at ${config.projectName}`);
|
|
63
|
-
logSuccess("Docs folder created");
|
|
64
|
-
|
|
65
|
-
if (config.git) {
|
|
66
|
-
await initializeGit(projectPath);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (config.backend?.framework) {
|
|
70
|
-
const backendInstallCmd =
|
|
71
|
-
config.backend.framework === "fastapi" && config.backend.packageManager === "venv"
|
|
72
|
-
? `chmod +x setup.sh && ./setup.sh`
|
|
73
|
-
: config.backend.packageManager === "venv" || config.backend.packageManager === "pip"
|
|
74
|
-
? `pip install -r requirements.txt`
|
|
75
|
-
: `${config.backend.packageManager} install`;
|
|
76
|
-
const backendRunCmd =
|
|
77
|
-
config.backend.framework === "fastapi"
|
|
78
|
-
? `python src/main.py`
|
|
79
|
-
: `${config.backend.packageManager} run dev`;
|
|
80
|
-
|
|
81
|
-
logInfo("\nš¦ Next steps:");
|
|
82
|
-
logInfo(` cd ${config.projectName}`);
|
|
83
|
-
logInfo(` ${backendInstallCmd}`);
|
|
84
|
-
logInfo(` ${backendRunCmd}`);
|
|
85
|
-
} else if (config.frontend?.framework) {
|
|
86
|
-
logInfo("\nš¦ Next steps:");
|
|
87
|
-
logInfo(` cd ${config.projectName}`);
|
|
88
|
-
logInfo(` ${config.frontend.packageManager} install`);
|
|
89
|
-
logInfo(` ${config.frontend.packageManager} run dev`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async function generateGitIgnore(projectPath: string): Promise<void> {
|
|
94
|
-
const content = `# Dependencies
|
|
95
|
-
node_modules/
|
|
96
|
-
.pnp
|
|
97
|
-
.pnp.js
|
|
98
|
-
|
|
99
|
-
# Testing
|
|
100
|
-
coverage/
|
|
101
|
-
*.lcov
|
|
102
|
-
playwright-report/
|
|
103
|
-
playwright/.cache/
|
|
104
|
-
|
|
105
|
-
# Next.js
|
|
106
|
-
.next/
|
|
107
|
-
out/
|
|
108
|
-
|
|
109
|
-
# Production
|
|
110
|
-
build/
|
|
111
|
-
dist/
|
|
112
|
-
|
|
113
|
-
# Misc
|
|
114
|
-
.DS_Store
|
|
115
|
-
*.pem
|
|
116
|
-
|
|
117
|
-
# Debug
|
|
118
|
-
npm-debug.log*
|
|
119
|
-
yarn-debug.log*
|
|
120
|
-
yarn-error.log*
|
|
121
|
-
pnpm-debug.log*
|
|
122
|
-
|
|
123
|
-
# Local env files
|
|
124
|
-
.env
|
|
125
|
-
.env.local
|
|
126
|
-
.env.development.local
|
|
127
|
-
.env.test.local
|
|
128
|
-
.env.production.local
|
|
129
|
-
|
|
130
|
-
# Vercel
|
|
131
|
-
.vercel
|
|
132
|
-
|
|
133
|
-
# TypeScript
|
|
134
|
-
*.tsbuildinfo
|
|
135
|
-
|
|
136
|
-
# Astro
|
|
137
|
-
.astro/
|
|
138
|
-
|
|
139
|
-
# Svelte
|
|
140
|
-
.svelte-kit/
|
|
141
|
-
|
|
142
|
-
# Python
|
|
143
|
-
__pycache__/
|
|
144
|
-
*.py[cod]
|
|
145
|
-
*$py.class
|
|
146
|
-
*.so
|
|
147
|
-
.Python
|
|
148
|
-
venv/
|
|
149
|
-
*.egg-info/
|
|
150
|
-
.eggs/
|
|
151
|
-
dist/
|
|
152
|
-
build/
|
|
153
|
-
|
|
154
|
-
# IDE
|
|
155
|
-
.idea/
|
|
156
|
-
.vscode/
|
|
157
|
-
*.swp
|
|
158
|
-
*.swo
|
|
159
|
-
*~
|
|
160
|
-
`;
|
|
161
|
-
|
|
162
|
-
await writeFile(`${projectPath}/.gitignore`, content);
|
|
163
|
-
logSuccess(".gitignore created");
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async function generateReadme(projectPath: string, config: GeneratorConfig): Promise<void> {
|
|
167
|
-
let content = `# ${config.projectName}
|
|
168
|
-
|
|
169
|
-
This project was generated by [Phos](https://github.com/yourusername/phos).
|
|
170
|
-
|
|
171
|
-
## Getting Started
|
|
172
|
-
|
|
173
|
-
`;
|
|
174
|
-
|
|
175
|
-
if (config.backend?.framework) {
|
|
176
|
-
content += `\`\`\`bash
|
|
177
|
-
${
|
|
178
|
-
config.backend!.packageManager === "venv" || config.backend!.packageManager === "pip"
|
|
179
|
-
? "pip install -r requirements.txt"
|
|
180
|
-
: `${config.backend!.packageManager} install`
|
|
181
|
-
}
|
|
182
|
-
${config.backend!.framework === "fastapi" ? "python src/main.py" : `${config.backend!.packageManager} run dev`}
|
|
183
|
-
\`\`\``;
|
|
184
|
-
} else if (config.frontend?.framework) {
|
|
185
|
-
content += `\`\`\`bash
|
|
186
|
-
${config.frontend!.packageManager} install
|
|
187
|
-
${config.frontend!.packageManager} run dev
|
|
188
|
-
\`\`\``;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
content += `
|
|
192
|
-
|
|
193
|
-
## Tech Stack
|
|
194
|
-
`;
|
|
195
|
-
|
|
196
|
-
if (config.backend?.framework) {
|
|
197
|
-
content += `- Framework: ${config.backend!.framework}
|
|
198
|
-
- Package Manager: ${config.backend!.packageManager}
|
|
199
|
-
- TypeScript: ${config.backend!.typescript ? "Yes" : "No"}
|
|
200
|
-
- ESLint: ${config.backend!.eslint ? "Yes" : "No"}
|
|
201
|
-
- Prettier: ${config.backend!.prettier ? "Yes" : "No"}
|
|
202
|
-
`;
|
|
203
|
-
} else if (config.frontend?.framework) {
|
|
204
|
-
content += `- Framework: ${config.frontend!.framework}
|
|
205
|
-
- Package Manager: ${config.frontend!.packageManager}
|
|
206
|
-
- TypeScript: ${config.frontend!.typescript ? "Yes" : "No"}
|
|
207
|
-
- ESLint: ${config.frontend!.eslint ? "Yes" : "No"}
|
|
208
|
-
- Prettier: ${config.frontend!.prettier ? "Yes" : "No"}
|
|
209
|
-
- CSS Framework: ${config.frontend!.cssFramework}
|
|
210
|
-
- UI Components: ${config.frontend!.uiComponents}
|
|
211
|
-
- Testing: ${config.frontend!.testing}
|
|
212
|
-
`;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
await writeFile(`${projectPath}/README.md`, content);
|
|
216
|
-
logSuccess("README.md created");
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
async function generateAgentsMd(projectPath: string, config: GeneratorConfig): Promise<void> {
|
|
220
|
-
const projectName = config.projectName;
|
|
221
|
-
|
|
222
|
-
const content = `# AGENTS Guidelines for This Repository
|
|
223
|
-
|
|
224
|
-
## Project Name: ${projectName}
|
|
225
|
-
|
|
226
|
-
This project was generated by [Phos](https://github.com/yourusername/phos).
|
|
227
|
-
|
|
228
|
-
### Core Features:
|
|
229
|
-
- Fast and interactive project setup
|
|
230
|
-
- Modern framework support
|
|
231
|
-
- Type-safe configurations
|
|
232
|
-
- ESLint and Prettier support
|
|
233
|
-
- Testing infrastructure
|
|
234
|
-
|
|
235
|
-
### Project Structure:
|
|
236
|
-
\`\`\`
|
|
237
|
-
${projectName}/
|
|
238
|
-
āāā src/ # Source code
|
|
239
|
-
āāā Docs/ # Documentation
|
|
240
|
-
ā āāā Feature/ # Feature documentation
|
|
241
|
-
ā āāā DatabaseSetup/ # Database scripts
|
|
242
|
-
āāā README.md # Project documentation
|
|
243
|
-
āāā .gitignore # Git ignore rules
|
|
244
|
-
āāā LICENSE # License file
|
|
245
|
-
\`\`\`
|
|
246
|
-
|
|
247
|
-
### Development Workflow:
|
|
248
|
-
1. Make changes to source code in \`src/\`
|
|
249
|
-
2. Update documentation in \`Docs/\` as needed
|
|
250
|
-
3. Test changes thoroughly
|
|
251
|
-
4. Commit with clear, descriptive messages
|
|
252
|
-
|
|
253
|
-
### Agent Guidelines:
|
|
254
|
-
- Follow existing code style and conventions
|
|
255
|
-
- Add proper type annotations where applicable
|
|
256
|
-
- Write tests for new features
|
|
257
|
-
- Update README.md for major changes
|
|
258
|
-
- Use clear, descriptive variable/function names
|
|
259
|
-
- Comment complex logic for maintainability
|
|
260
|
-
|
|
261
|
-
### Best Practices:
|
|
262
|
-
- Run linter before committing (ESLint, Prettier)
|
|
263
|
-
- Test on different environments before deployment
|
|
264
|
-
- Keep dependencies updated and secure
|
|
265
|
-
- Write clear, concise commit messages
|
|
266
|
-
- Review pull requests thoroughly before merging
|
|
267
|
-
|
|
268
|
-
### Troubleshooting:
|
|
269
|
-
- Check documentation first
|
|
270
|
-
- Review recent changes if issues arise
|
|
271
|
-
- Use version control to revert problematic changes
|
|
272
|
-
- Ask for help in team channels when stuck
|
|
273
|
-
`;
|
|
274
|
-
|
|
275
|
-
await writeFile(`${projectPath}/AGENTS.md`, content);
|
|
276
|
-
logSuccess("AGENTS.md created");
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
async function generateLicense(projectPath: string, config: GeneratorConfig): Promise<void> {
|
|
280
|
-
const year = new Date().getFullYear();
|
|
281
|
-
const content = `MIT License
|
|
282
|
-
|
|
283
|
-
Copyright (c) ${year} ${config.projectName}
|
|
284
|
-
|
|
285
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
286
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
287
|
-
in the Software without restriction, including without limitation the rights
|
|
288
|
-
to use, copy, modify, merge, publish, distribute, sublicense,
|
|
289
|
-
and/or sell copies of the Software, and to permit persons to whom the
|
|
290
|
-
Software is furnished to do so, subject to the following conditions:
|
|
291
|
-
|
|
292
|
-
The above copyright notice and this permission notice shall be included in all
|
|
293
|
-
copies or substantial portions of the Software.
|
|
294
|
-
|
|
295
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
296
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
297
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
298
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
299
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
300
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
301
|
-
DEALINGS IN THE SOFTWARE.
|
|
302
|
-
`;
|
|
303
|
-
|
|
304
|
-
await writeFile(`${projectPath}/LICENSE`, content);
|
|
305
|
-
logSuccess("LICENSE created");
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
async function generateEnvExample(projectPath: string): Promise<void> {
|
|
309
|
-
const content = `# Database
|
|
310
|
-
DB_HOST=localhost
|
|
311
|
-
DB_NAME=your_db_name
|
|
312
|
-
DB_USER=postgres
|
|
313
|
-
DB_PASSWORD=postgres
|
|
314
|
-
DB_PORT=5433
|
|
315
|
-
|
|
316
|
-
# URLs
|
|
317
|
-
FRONTEND_BASE_URL=http://localhost:4200
|
|
318
|
-
BACKEND_BASE_URL=http://localhost:4100
|
|
319
|
-
|
|
320
|
-
# JWT Configuration for rest API
|
|
321
|
-
JWT_SECRET=your-super-secret-jwt-key-change-in-production
|
|
322
|
-
JWT_EXPIRES_IN=60m
|
|
323
|
-
|
|
324
|
-
# Encryption
|
|
325
|
-
ENCRYPTION_SALT=your-super-secret-salt-change-in-production
|
|
326
|
-
|
|
327
|
-
# API Keys
|
|
328
|
-
X_API_KEY=1234
|
|
329
|
-
`;
|
|
330
|
-
|
|
331
|
-
await writeFile(`${projectPath}/env.example`, content);
|
|
332
|
-
logSuccess("env.example created");
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
async function generateSchemaDocs(docsPath: string, config: GeneratorConfig): Promise<void> {
|
|
336
|
-
const projectName = config.projectName;
|
|
337
|
-
const content = `# ${projectName} Database Schema
|
|
338
|
-
|
|
339
|
-
## Table of Contents
|
|
340
|
-
|
|
341
|
-
- [${projectName} Database Schema](#${projectName.toLowerCase()}-database-schema)
|
|
342
|
-
- [Table of Contents](#table-of-contents)
|
|
343
|
-
- [Overview](#overview)
|
|
344
|
-
- [Core Entities](#core-entities)
|
|
345
|
-
- [Entity Name](#entity-name)
|
|
346
|
-
- [Entity Relationships](#entity-relationships)
|
|
347
|
-
- [SQL Schema](#sql-schema)
|
|
348
|
-
- [Create Tables](#create-tables)
|
|
349
|
-
- [Sample Data](#sample-data)
|
|
350
|
-
- [Data Types Notes](#data-types-notes)
|
|
351
|
-
- [Migration Notes](#migration-notes)
|
|
352
|
-
|
|
353
|
-
---
|
|
354
|
-
|
|
355
|
-
## Overview
|
|
356
|
-
|
|
357
|
-
This document describes the complete database schema for ${projectName}, including all entities, relationships, and sample data.
|
|
358
|
-
|
|
359
|
-
---
|
|
360
|
-
|
|
361
|
-
## Core Entities
|
|
362
|
-
|
|
363
|
-
### Entity Name
|
|
364
|
-
|
|
365
|
-
| Column | Type | Nullable | Description |
|
|
366
|
-
| ----------- | -------- | -------- | ---------------------------------- |
|
|
367
|
-
| id | int | No | Primary key, auto-incremented ID |
|
|
368
|
-
| uuid | string | No | Unique identifier |
|
|
369
|
-
| column_name | str | Yes/No | Description of column |
|
|
370
|
-
| created_at | datetime | No | Record creation timestamp (UTC) |
|
|
371
|
-
| updated_at | datetime | Yes | Record last update timestamp (UTC) |
|
|
372
|
-
|
|
373
|
-
---
|
|
374
|
-
|
|
375
|
-
## Entity Relationships
|
|
376
|
-
|
|
377
|
-
\`\`\`
|
|
378
|
-
table1 (1) āāāā (many) table2
|
|
379
|
-
table3 (many) āāāā (1) table4
|
|
380
|
-
\`\`\`
|
|
381
|
-
|
|
382
|
-
---
|
|
383
|
-
|
|
384
|
-
## SQL Schema
|
|
385
|
-
|
|
386
|
-
### Create Tables
|
|
387
|
-
|
|
388
|
-
For PostgreSQL deployment, use the following schema:
|
|
389
|
-
|
|
390
|
-
\`\`\`sql
|
|
391
|
-
-- Drop tables if they exist (for clean setup)
|
|
392
|
-
DROP TABLE IF EXISTS child_table;
|
|
393
|
-
DROP TABLE IF EXISTS parent_table;
|
|
394
|
-
|
|
395
|
-
-- Parent table
|
|
396
|
-
CREATE TABLE parent_table (
|
|
397
|
-
id SERIAL PRIMARY KEY,
|
|
398
|
-
uuid TEXT NOT NULL UNIQUE,
|
|
399
|
-
name TEXT NOT NULL,
|
|
400
|
-
description TEXT,
|
|
401
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
402
|
-
updated_at TIMESTAMP
|
|
403
|
-
);
|
|
404
|
-
|
|
405
|
-
-- Child table
|
|
406
|
-
CREATE TABLE child_table (
|
|
407
|
-
id TEXT PRIMARY KEY,
|
|
408
|
-
parent_id TEXT NOT NULL,
|
|
409
|
-
content TEXT NOT NULL,
|
|
410
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
411
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
412
|
-
FOREIGN KEY (parent_id) REFERENCES parent_table(uuid)
|
|
413
|
-
);
|
|
414
|
-
|
|
415
|
-
-- Add foreign key constraints if needed
|
|
416
|
-
ALTER TABLE child_table ADD CONSTRAINT fk_child_parent FOREIGN KEY (parent_id) REFERENCES parent_table(uuid);
|
|
417
|
-
|
|
418
|
-
-- Performance indexes
|
|
419
|
-
CREATE INDEX idx_parent_table_uuid ON parent_table(uuid);
|
|
420
|
-
CREATE INDEX idx_child_table_parent_id ON child_table(parent_id);
|
|
421
|
-
CREATE INDEX idx_child_table_created_at ON child_table(created_at);
|
|
422
|
-
\`\`\`
|
|
423
|
-
|
|
424
|
-
---
|
|
425
|
-
|
|
426
|
-
## Sample Data
|
|
427
|
-
|
|
428
|
-
\`\`\`sql
|
|
429
|
-
-- Insert sample data for parent table
|
|
430
|
-
INSERT INTO parent_table (uuid, name, description, created_at)
|
|
431
|
-
VALUES ('550e8400-e29b-41d4-a716-4466554400000', 'Sample Name', 'Sample description', CURRENT_TIMESTAMP);
|
|
432
|
-
|
|
433
|
-
-- Insert sample data for child table
|
|
434
|
-
INSERT INTO child_table (id, parent_id, content, created_at, updated_at)
|
|
435
|
-
VALUES ('6ba7b810-9dad-11d1-80b4-00c04fd430c8', '550e8400-e29b-41d4-a716-4466554400000', 'Sample content', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
|
|
436
|
-
\`\`\`
|
|
437
|
-
|
|
438
|
-
---
|
|
439
|
-
|
|
440
|
-
## Data Types Notes
|
|
441
|
-
|
|
442
|
-
- **UUID**: Stored as TEXT for simplicity
|
|
443
|
-
- **Arrays**: Stored as native PostgreSQL arrays (e.g., text[])
|
|
444
|
-
- **JSON**: Stored as JSONB for PostgreSQL (or TEXT for SQLite)
|
|
445
|
-
- **Boolean**: Stored as BOOLEAN for PostgreSQL (or INTEGER 0/1 for SQLite)
|
|
446
|
-
- **Decimal**: Stored as DECIMAL for precision calculations
|
|
447
|
-
- **Datetime**: Stored as TIMESTAMP with CURRENT_TIMESTAMP defaults
|
|
448
|
-
|
|
449
|
-
---
|
|
450
|
-
|
|
451
|
-
## Migration Notes
|
|
452
|
-
|
|
453
|
-
When deploying to production:
|
|
454
|
-
|
|
455
|
-
1. Consider using PostgreSQL for better JSON support and performance
|
|
456
|
-
2. Add proper UUID generation in application code
|
|
457
|
-
3. Implement database migrations for schema changes
|
|
458
|
-
4. Add database constraints and triggers as needed
|
|
459
|
-
5. Run \`ALTER TABLE\` statements for schema additions
|
|
460
|
-
6. Test migrations on staging environment before production
|
|
461
|
-
`;
|
|
462
|
-
|
|
463
|
-
await writeFile(`${docsPath}/Schema.md`, content);
|
|
464
|
-
logSuccess("Schema.md created");
|
|
465
|
-
}
|
package/src/utils/helpers.ts
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import fs from "fs-extra";
|
|
2
|
-
import Handlebars from "handlebars";
|
|
3
|
-
import pc from "picocolors";
|
|
4
|
-
import { execSync } from "child_process";
|
|
5
|
-
import { resolve, join } from "path";
|
|
6
|
-
|
|
7
|
-
Handlebars.registerHelper("eq", function (a, b) {
|
|
8
|
-
return a === b;
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
Handlebars.registerHelper("or", function (...args) {
|
|
12
|
-
return args.slice(0, -1).some(Boolean);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
export interface GeneratorConfig {
|
|
16
|
-
projectName: string;
|
|
17
|
-
projectType: "monorepo" | "single";
|
|
18
|
-
backend?: {
|
|
19
|
-
framework: "elysia" | "fastapi";
|
|
20
|
-
packageManager: "npm" | "yarn" | "pnpm" | "bun" | "venv" | "pip";
|
|
21
|
-
typescript: boolean;
|
|
22
|
-
eslint: boolean;
|
|
23
|
-
prettier: boolean;
|
|
24
|
-
};
|
|
25
|
-
frontend?: {
|
|
26
|
-
framework: "astro" | "svelte" | "nextjs";
|
|
27
|
-
packageManager: "npm" | "yarn" | "pnpm" | "bun";
|
|
28
|
-
typescript: boolean;
|
|
29
|
-
eslint: boolean;
|
|
30
|
-
prettier: boolean;
|
|
31
|
-
cssFramework: "none" | "tailwind" | "scss" | "css-modules";
|
|
32
|
-
uiComponents: "none" | "shadcn" | "radix";
|
|
33
|
-
testing: "none" | "vitest" | "playwright" | "both";
|
|
34
|
-
};
|
|
35
|
-
git: boolean;
|
|
36
|
-
install: boolean;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function createDirectory(dirPath: string): Promise<void> {
|
|
40
|
-
await fs.ensureDir(dirPath);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export async function writeFile(filePath: string, content: string): Promise<void> {
|
|
44
|
-
await fs.ensureFile(filePath);
|
|
45
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function copyTemplate(
|
|
49
|
-
templatePath: string,
|
|
50
|
-
outputPath: string,
|
|
51
|
-
data: Record<string, unknown>
|
|
52
|
-
): Promise<void> {
|
|
53
|
-
const files = await fs.readdir(templatePath, { withFileTypes: true });
|
|
54
|
-
|
|
55
|
-
const binaryExtensions = [
|
|
56
|
-
".png",
|
|
57
|
-
".jpg",
|
|
58
|
-
".jpeg",
|
|
59
|
-
".gif",
|
|
60
|
-
".svg",
|
|
61
|
-
".ico",
|
|
62
|
-
".webp",
|
|
63
|
-
".woff",
|
|
64
|
-
".woff2",
|
|
65
|
-
".ttf",
|
|
66
|
-
".otf",
|
|
67
|
-
".eot",
|
|
68
|
-
".pdf",
|
|
69
|
-
".zip",
|
|
70
|
-
".tar",
|
|
71
|
-
".gz",
|
|
72
|
-
".7z",
|
|
73
|
-
".bin",
|
|
74
|
-
".exe",
|
|
75
|
-
".dll",
|
|
76
|
-
".so",
|
|
77
|
-
".dylib",
|
|
78
|
-
];
|
|
79
|
-
|
|
80
|
-
for (const file of files) {
|
|
81
|
-
const srcPath = join(templatePath, file.name);
|
|
82
|
-
const destPath = join(outputPath, file.name);
|
|
83
|
-
|
|
84
|
-
if (file.isDirectory()) {
|
|
85
|
-
await createDirectory(destPath);
|
|
86
|
-
await copyTemplate(srcPath, destPath, data);
|
|
87
|
-
} else {
|
|
88
|
-
const ext = file.name.toLowerCase();
|
|
89
|
-
const isBinary = binaryExtensions.some((binExt) => ext.endsWith(binExt));
|
|
90
|
-
|
|
91
|
-
if (isBinary) {
|
|
92
|
-
await fs.copy(srcPath, destPath);
|
|
93
|
-
} else {
|
|
94
|
-
let content = await fs.readFile(srcPath, "utf-8");
|
|
95
|
-
const template = Handlebars.compile(content);
|
|
96
|
-
const rendered = template(data);
|
|
97
|
-
await writeFile(destPath, rendered);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function getPackageManagerInstallCmd(packageManager: string): string {
|
|
104
|
-
switch (packageManager) {
|
|
105
|
-
case "npm":
|
|
106
|
-
return "npm install";
|
|
107
|
-
case "yarn":
|
|
108
|
-
return "yarn";
|
|
109
|
-
case "pnpm":
|
|
110
|
-
return "pnpm install";
|
|
111
|
-
case "bun":
|
|
112
|
-
return "bun install";
|
|
113
|
-
case "venv":
|
|
114
|
-
return "source venv/bin/activate && pip install -r requirements.txt";
|
|
115
|
-
case "pip":
|
|
116
|
-
return "pip install -r requirements.txt";
|
|
117
|
-
default:
|
|
118
|
-
return "npm install";
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export function getPackageManagerRunCmd(packageManager: string, script: string): string {
|
|
123
|
-
switch (packageManager) {
|
|
124
|
-
case "npm":
|
|
125
|
-
return `npm run ${script}`;
|
|
126
|
-
case "yarn":
|
|
127
|
-
return `yarn ${script}`;
|
|
128
|
-
case "pnpm":
|
|
129
|
-
return `pnpm run ${script}`;
|
|
130
|
-
case "bun":
|
|
131
|
-
return `bun run ${script}`;
|
|
132
|
-
case "venv":
|
|
133
|
-
return `source venv/bin/activate && python src/main.py`;
|
|
134
|
-
case "pip":
|
|
135
|
-
return `python src/main.py`;
|
|
136
|
-
default:
|
|
137
|
-
return `npm run ${script}`;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export function logStep(message: string): void {
|
|
142
|
-
console.log(pc.cyan(` ${message}`));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export function logSuccess(message: string): void {
|
|
146
|
-
console.log(pc.green(` ā
${message}`));
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export function logInfo(message: string): void {
|
|
150
|
-
console.log(pc.blue(` ā¹ļø ${message}`));
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export async function installDependencies(
|
|
154
|
-
projectPath: string,
|
|
155
|
-
packageManager: string
|
|
156
|
-
): Promise<void> {
|
|
157
|
-
try {
|
|
158
|
-
logStep(`Installing dependencies with ${packageManager}...`);
|
|
159
|
-
execSync(getPackageManagerInstallCmd(packageManager), {
|
|
160
|
-
cwd: projectPath,
|
|
161
|
-
stdio: "inherit",
|
|
162
|
-
});
|
|
163
|
-
logSuccess("Dependencies installed");
|
|
164
|
-
} catch (error) {
|
|
165
|
-
throw new Error(`Failed to install dependencies: ${error}`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export async function initializeGit(projectPath: string): Promise<void> {
|
|
170
|
-
try {
|
|
171
|
-
logStep("Initializing Git repository...");
|
|
172
|
-
execSync("git init", { cwd: projectPath, stdio: "inherit" });
|
|
173
|
-
execSync("git add .", { cwd: projectPath, stdio: "inherit" });
|
|
174
|
-
execSync('git commit -m "Initial commit from Phos"', {
|
|
175
|
-
cwd: projectPath,
|
|
176
|
-
stdio: "inherit",
|
|
177
|
-
});
|
|
178
|
-
logSuccess("Git repository initialized");
|
|
179
|
-
} catch (error) {
|
|
180
|
-
throw new Error(`Failed to initialize Git: ${error}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export function getProjectPath(projectName: string): string {
|
|
185
|
-
return resolve(process.cwd(), projectName);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export function capitalize(str: string): string {
|
|
189
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export function toKebabCase(str: string): string {
|
|
193
|
-
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export function toPascalCase(str: string): string {
|
|
197
|
-
return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase()).replace(/^(.)/, (c) => c.toUpperCase());
|
|
198
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ES2022",
|
|
5
|
-
"lib": ["ES2022"],
|
|
6
|
-
"moduleResolution": "bundler",
|
|
7
|
-
"outDir": "./dist",
|
|
8
|
-
"rootDir": "./src",
|
|
9
|
-
"strict": true,
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"skipLibCheck": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"resolveJsonModule": true,
|
|
14
|
-
"declaration": true,
|
|
15
|
-
"declarationMap": true,
|
|
16
|
-
"sourceMap": true,
|
|
17
|
-
"baseUrl": ".",
|
|
18
|
-
"paths": {
|
|
19
|
-
"@/*": ["./src/*"]
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
"include": ["src/**/*"],
|
|
23
|
-
"exclude": ["node_modules", "dist", "src/templates/**/*"]
|
|
24
|
-
}
|