phos 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.
Files changed (116) hide show
  1. package/.eslintignore +3 -0
  2. package/AGENTS.md +172 -0
  3. package/CHANGELOG.md +184 -0
  4. package/LICENSE +21 -0
  5. package/README.md +279 -0
  6. package/bun.lock +125 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +255 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/generators/backends/elysia.d.ts +3 -0
  12. package/dist/generators/backends/elysia.d.ts.map +1 -0
  13. package/dist/generators/backends/elysia.js +135 -0
  14. package/dist/generators/backends/elysia.js.map +1 -0
  15. package/dist/generators/backends/fastapi.d.ts +3 -0
  16. package/dist/generators/backends/fastapi.d.ts.map +1 -0
  17. package/dist/generators/backends/fastapi.js +158 -0
  18. package/dist/generators/backends/fastapi.js.map +1 -0
  19. package/dist/generators/frontends/astro.d.ts +3 -0
  20. package/dist/generators/frontends/astro.d.ts.map +1 -0
  21. package/dist/generators/frontends/astro.js +303 -0
  22. package/dist/generators/frontends/astro.js.map +1 -0
  23. package/dist/generators/frontends/nextjs.d.ts +3 -0
  24. package/dist/generators/frontends/nextjs.d.ts.map +1 -0
  25. package/dist/generators/frontends/nextjs.js +274 -0
  26. package/dist/generators/frontends/nextjs.js.map +1 -0
  27. package/dist/generators/frontends/svelte.d.ts +3 -0
  28. package/dist/generators/frontends/svelte.d.ts.map +1 -0
  29. package/dist/generators/frontends/svelte.js +324 -0
  30. package/dist/generators/frontends/svelte.js.map +1 -0
  31. package/dist/generators/monorepo.d.ts +3 -0
  32. package/dist/generators/monorepo.d.ts.map +1 -0
  33. package/dist/generators/monorepo.js +320 -0
  34. package/dist/generators/monorepo.js.map +1 -0
  35. package/dist/generators/single.d.ts +3 -0
  36. package/dist/generators/single.d.ts.map +1 -0
  37. package/dist/generators/single.js +229 -0
  38. package/dist/generators/single.js.map +1 -0
  39. package/dist/utils/helpers.d.ts +38 -0
  40. package/dist/utils/helpers.d.ts.map +1 -0
  41. package/dist/utils/helpers.js +109 -0
  42. package/dist/utils/helpers.js.map +1 -0
  43. package/package.json +46 -0
  44. package/src/cli.ts +500 -0
  45. package/src/generators/backends/elysia.ts +45 -0
  46. package/src/generators/backends/fastapi.ts +71 -0
  47. package/src/generators/frontends/astro.ts +37 -0
  48. package/src/generators/frontends/nextjs.ts +37 -0
  49. package/src/generators/frontends/svelte.ts +38 -0
  50. package/src/generators/monorepo.ts +529 -0
  51. package/src/generators/single.ts +465 -0
  52. package/src/templates/backend/elysia/README.md +15 -0
  53. package/src/templates/backend/elysia/package.json +26 -0
  54. package/src/templates/backend/elysia/src/api/user_api.ts +0 -0
  55. package/src/templates/backend/elysia/src/db.ts +17 -0
  56. package/src/templates/backend/elysia/src/index.ts +68 -0
  57. package/src/templates/backend/elysia/src/service/user_service.ts +0 -0
  58. package/src/templates/backend/elysia/src/sql/user_sql.ts +0 -0
  59. package/src/templates/backend/elysia/src/types/user_type.ts +0 -0
  60. package/src/templates/backend/elysia/tsconfig.json +103 -0
  61. package/src/templates/backend/fastapi/.pylintrc +2 -0
  62. package/src/templates/backend/fastapi/README.md +33 -0
  63. package/src/templates/backend/fastapi/pyproject.toml +9 -0
  64. package/src/templates/backend/fastapi/pyproject_prettier.toml +20 -0
  65. package/src/templates/backend/fastapi/requirements.txt +15 -0
  66. package/src/templates/backend/fastapi/setup.sh +23 -0
  67. package/src/templates/backend/fastapi/src/api/user_api.py +0 -0
  68. package/src/templates/backend/fastapi/src/db.py +31 -0
  69. package/src/templates/backend/fastapi/src/main.py +53 -0
  70. package/src/templates/backend/fastapi/src/service/user_service.py +0 -0
  71. package/src/templates/backend/fastapi/src/sql/user_sql.py +0 -0
  72. package/src/templates/backend/fastapi/src/types/user_type.py +0 -0
  73. package/src/templates/frontend/astro/README.md +46 -0
  74. package/src/templates/frontend/astro/astro.config.mjs +5 -0
  75. package/src/templates/frontend/astro/package.json +28 -0
  76. package/src/templates/frontend/astro/public/favicon.ico +0 -0
  77. package/src/templates/frontend/astro/public/favicon.svg +9 -0
  78. package/src/templates/frontend/astro/src/assets/astro.svg +1 -0
  79. package/src/templates/frontend/astro/src/assets/background.svg +1 -0
  80. package/src/templates/frontend/astro/src/components/Welcome.astro +5 -0
  81. package/src/templates/frontend/astro/src/layouts/Layout.astro +23 -0
  82. package/src/templates/frontend/astro/src/pages/index.astro +8 -0
  83. package/src/templates/frontend/astro/tsconfig.json +5 -0
  84. package/src/templates/frontend/nextjs/README.md +36 -0
  85. package/src/templates/frontend/nextjs/app/favicon.ico +0 -0
  86. package/src/templates/frontend/nextjs/app/globals.css +26 -0
  87. package/src/templates/frontend/nextjs/app/layout.tsx +34 -0
  88. package/src/templates/frontend/nextjs/app/page.tsx +16 -0
  89. package/src/templates/frontend/nextjs/eslint.config.mjs +18 -0
  90. package/src/templates/frontend/nextjs/next.config.ts +7 -0
  91. package/src/templates/frontend/nextjs/package.json +28 -0
  92. package/src/templates/frontend/nextjs/postcss.config.mjs +7 -0
  93. package/src/templates/frontend/nextjs/public/file.svg +1 -0
  94. package/src/templates/frontend/nextjs/public/globe.svg +1 -0
  95. package/src/templates/frontend/nextjs/public/next.svg +1 -0
  96. package/src/templates/frontend/nextjs/public/vercel.svg +1 -0
  97. package/src/templates/frontend/nextjs/public/window.svg +1 -0
  98. package/src/templates/frontend/nextjs/tsconfig.json +34 -0
  99. package/src/templates/frontend/svelte/.prettierignore +9 -0
  100. package/src/templates/frontend/svelte/.prettierrc +19 -0
  101. package/src/templates/frontend/svelte/README.md +42 -0
  102. package/src/templates/frontend/svelte/eslint.config.js +39 -0
  103. package/src/templates/frontend/svelte/package.json +39 -0
  104. package/src/templates/frontend/svelte/src/app.d.ts +13 -0
  105. package/src/templates/frontend/svelte/src/app.html +11 -0
  106. package/src/templates/frontend/svelte/src/lib/assets/favicon.svg +1 -0
  107. package/src/templates/frontend/svelte/src/lib/index.ts +1 -0
  108. package/src/templates/frontend/svelte/src/routes/+layout.svelte +9 -0
  109. package/src/templates/frontend/svelte/src/routes/+page.svelte +2 -0
  110. package/src/templates/frontend/svelte/src/routes/layout.css +2 -0
  111. package/src/templates/frontend/svelte/static/robots.txt +3 -0
  112. package/src/templates/frontend/svelte/svelte.config.js +13 -0
  113. package/src/templates/frontend/svelte/tsconfig.json +20 -0
  114. package/src/templates/frontend/svelte/vite.config.ts +5 -0
  115. package/src/utils/helpers.ts +198 -0
  116. package/tsconfig.json +24 -0
@@ -0,0 +1,465 @@
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
+ }
@@ -0,0 +1,15 @@
1
+ # Elysia with Bun runtime
2
+
3
+ ## Getting Started
4
+ To get started with this template, simply paste this command into your terminal:
5
+ ```bash
6
+ bun create elysia ./elysia-example
7
+ ```
8
+
9
+ ## Development
10
+ To start the development server run:
11
+ ```bash
12
+ bun run dev
13
+ ```
14
+
15
+ Open http://localhost:3000/ with your browser to see the result.
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "{{backendName}}",
3
+ "version": "0.1.0",
4
+ "scripts": {
5
+ "test": "echo \"Error: no test specified\" && exit 1",
6
+ "dev": "{{packageManager}} run --watch src/index.ts",
7
+ "build": "{{packageManager}} build src/index.ts",
8
+ "start": "{{packageManager}} run dist/index.js"
9
+ },
10
+ "dependencies": {
11
+ "@elysiajs/cors": "latest",
12
+ "@elysiajs/swagger": "latest",
13
+ "@types/bcrypt": "latest",
14
+ "@types/jsonwebtoken": "latest",
15
+ "bcrypt": "latest",
16
+ "dotenv": "latest",
17
+ "elysia": "latest",
18
+ "jsonwebtoken": "latest",
19
+ "postgres": "^3.4.8",
20
+ "uuid": "latest"
21
+ },
22
+ "devDependencies": {
23
+ "bun-types": "latest"
24
+ },
25
+ "module": "src/index.js"
26
+ }
@@ -0,0 +1,17 @@
1
+ import postgres from "postgres";
2
+ import { join, dirname } from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+
8
+ const connectionString = `postgres://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`;
9
+
10
+ export const db = new postgres({
11
+ connectionString,
12
+ ssl: process.env.NODE_ENV === "production" ? { rejectUnauthorized: false } : false,
13
+ });
14
+
15
+ console.log(`🗄️ Database connected to: ${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`);
16
+
17
+ export default db;
@@ -0,0 +1,68 @@
1
+ import { Elysia } from "elysia";
2
+ import { cors } from "@elysiajs/cors";
3
+ import { swagger } from "@elysiajs/swagger";
4
+ import * as dotenv from "dotenv";
5
+ import { userApi } from "./api/user_api";
6
+ import { join, dirname } from "path";
7
+ import { fileURLToPath } from "url";
8
+ import { db } from "./db";
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+
13
+ dotenv.config({ path: join(__dirname, "../../.env") });
14
+
15
+ const API_KEY = process.env.X_API_KEY || "your-api-key";
16
+ const CORS_ALLOWED_ORIGINS = process.env.CORS_ALLOWED_ORIGINS || "http://localhost:4200";
17
+
18
+ const app = new Elysia()
19
+ .use(
20
+ cors({
21
+ origin: CORS_ALLOWED_ORIGINS.split(","),
22
+ credentials: true,
23
+ methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
24
+ allowedHeaders: ["Content-Type", "Authorization", "X-API-Key"],
25
+ })
26
+ )
27
+ .use(
28
+ swagger({
29
+ path: "/w",
30
+ documentation: {
31
+ info: {
32
+ title: "{{projectName}} API",
33
+ version: "1.0.0",
34
+ description: "A modern web application API built with ElysiaJS",
35
+ },
36
+ tags: [
37
+ { name: "Users", description: "User management endpoints" },
38
+ { name: "Health", description: "Health check endpoints" },
39
+ ],
40
+ },
41
+ })
42
+ )
43
+ .get("/health", () => ({ status: "ok", timestamp: new Date().toISOString() }), {
44
+ detail: {
45
+ tags: ["Health"],
46
+ summary: "Health check endpoint",
47
+ description: "Check if API is running and healthy",
48
+ },
49
+ })
50
+ .group("/api", (app) =>
51
+ app
52
+ .onBeforeHandle(({ headers, set }) => {
53
+ const apiKey = headers["x-api-key"];
54
+ if (!apiKey || apiKey !== API_KEY) {
55
+ set.status = 401;
56
+ return { error: "Unauthorized: Invalid or missing API key" };
57
+ }
58
+ })
59
+ .use(userApi)
60
+ )
61
+ .get("/", () => `Hello Elysia {{projectName}}`)
62
+ .listen(4100);
63
+
64
+ console.log(`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`);
65
+ console.log(`🦊 CORS allowed origins: ${CORS_ALLOWED_ORIGINS}`);
66
+ console.log(`🦊 Swagger docs available at ${app.server?.hostname}:${app.server?.port}/w`);
67
+
68
+ export type App = typeof app;