create-backlist 4.0.0 → 5.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.
@@ -1,64 +1,125 @@
1
- // Auto-generated by create-backlist on <%= new Date().toISOString() %>
2
- import { Request, Response } from 'express';
3
- import <%= modelName %>, { I<%= modelName %> } from '../models/<%= modelName %>.model';
4
-
5
- // @desc Create a new <%= modelName %>
6
- export const create<%= modelName %> = async (req: Request, res: Response) => {
7
- try {
8
- const newDoc = new <%= modelName %>(req.body);
9
- await newDoc.save();
10
- res.status(201).json(newDoc);
11
- } catch (error) {
12
- if (error.name === 'ValidationError') {
13
- return res.status(400).json({ message: 'Validation Error', errors: error.errors });
14
- }
15
- res.status(500).json({ message: 'Error creating document', error });
16
- }
17
- };
18
-
19
- // @desc Get all <%= modelName %>s
20
- export const getAll<%= modelName %>s = async (req: Request, res: Response) => {
21
- try {
22
- const docs = await <%= modelName %>.find();
23
- res.status(200).json(docs);
24
- } catch (error) {
25
- res.status(500).json({ message: 'Error fetching documents', error });
26
- }
27
- };
28
-
29
- // @desc Get a single <%= modelName %> by ID
30
- export const get<%= modelName %>ById = async (req: Request, res: Response) => {
31
- try {
32
- const doc = await <%= modelName %>.findById(req.params.id);
33
- if (!doc) return res.status(404).json({ message: 'Document not found' });
34
- res.status(200).json(doc);
35
- } catch (error) {
36
- res.status(500).json({ message: 'Error fetching document', error });
37
- }
38
- };
39
-
40
- // @desc Update a <%= modelName %> by ID
41
- export const update<%= modelName %>ById = async (req: Request, res: Response) => {
42
- try {
43
- const doc = await <%= modelName %>.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
44
- if (!doc) return res.status(404).json({ message: 'Document not found' });
45
- res.status(200).json(doc);
46
- } catch (error) {
47
- if (error.name === 'ValidationError') {
48
- return res.status(400).json({ message: 'Validation Error', errors: error.errors });
1
+ // Auto-generated by create-backlist v5.0
2
+ using Microsoft.AspNetCore.Mvc;
3
+ using Microsoft.EntityFrameworkCore;
4
+ using <%= projectName %>.Data;
5
+ using <%= projectName %>.Models;
6
+
7
+ namespace <%= projectName %>.Controllers
8
+ {
9
+ [ApiController]
10
+ [Route("api/[controller]")]
11
+ public class <%= controllerName %>Controller : ControllerBase
12
+ {
13
+ private readonly ApplicationDbContext _context;
14
+
15
+ public <%= controllerName %>Controller(ApplicationDbContext context)
16
+ {
17
+ _context = context;
18
+ }
19
+
20
+ // GET: api/<%= controllerName.toLowerCase() %>
21
+ // Retrieves all items.
22
+ [HttpGet]
23
+ public async Task<ActionResult<IEnumerable<<%= controllerName %>>>> Get<%= controllerName %>s()
24
+ {
25
+ if (_context.<%= controllerName %>s == null)
26
+ {
27
+ return NotFound("Entity set '<%= controllerName %>s' is null.");
28
+ }
29
+ return await _context.<%= controllerName %>s.ToListAsync();
30
+ }
31
+
32
+ // GET: api/<%= controllerName.toLowerCase() %>/{id}
33
+ // Retrieves a specific item by its ID.
34
+ [HttpGet("{id}")]
35
+ public async Task<ActionResult<<%= controllerName %>>> Get<%= controllerName %>(Guid id)
36
+ {
37
+ if (_context.<%= controllerName %>s == null)
38
+ {
39
+ return NotFound();
40
+ }
41
+ var item = await _context.<%= controllerName %>s.FindAsync(id);
42
+
43
+ if (item == null)
44
+ {
45
+ return NotFound();
46
+ }
47
+
48
+ return item;
49
+ }
50
+
51
+ // PUT: api/<%= controllerName.toLowerCase() %>/{id}
52
+ // Updates a specific item.
53
+ [HttpPut("{id}")]
54
+ public async Task<IActionResult> Put<%= controllerName %>(Guid id, <%= controllerName %> item)
55
+ {
56
+ if (id != item.Id)
57
+ {
58
+ return BadRequest();
59
+ }
60
+
61
+ _context.Entry(item).State = EntityState.Modified;
62
+
63
+ try
64
+ {
65
+ await _context.SaveChangesAsync();
66
+ }
67
+ catch (DbUpdateConcurrencyException)
68
+ {
69
+ if (!ItemExists(id))
70
+ {
71
+ return NotFound();
72
+ }
73
+ else
74
+ {
75
+ throw;
76
+ }
77
+ }
78
+
79
+ return NoContent();
80
+ }
81
+
82
+ // POST: api/<%= controllerName.toLowerCase() %>
83
+ // Creates a new item.
84
+ [HttpPost]
85
+ public async Task<ActionResult<<%= controllerName %>>> Post<%= controllerName %>(<%= controllerName %> item)
86
+ {
87
+ if (_context.<%= controllerName %>s == null)
88
+ {
89
+ return Problem("Entity set '<%= controllerName %>s' is null.");
90
+ }
91
+ // Ensure a new Guid is created for the new item
92
+ item.Id = Guid.NewGuid();
93
+ _context.<%= controllerName %>s.Add(item);
94
+ await _context.SaveChangesAsync();
95
+
96
+ return CreatedAtAction(nameof(Get<%= controllerName %>), new { id = item.Id }, item);
97
+ }
98
+
99
+ // DELETE: api/<%= controllerName.toLowerCase() %>/{id}
100
+ // Deletes a specific item.
101
+ [HttpDelete("{id}")]
102
+ public async Task<IActionResult> Delete<%= controllerName %>(Guid id)
103
+ {
104
+ if (_context.<%= controllerName %>s == null)
105
+ {
106
+ return NotFound();
107
+ }
108
+ var item = await _context.<%= controllerName %>s.FindAsync(id);
109
+ if (item == null)
110
+ {
111
+ return NotFound();
112
+ }
113
+
114
+ _context.<%= controllerName %>s.Remove(item);
115
+ await _context.SaveChangesAsync();
116
+
117
+ return NoContent();
118
+ }
119
+
120
+ private bool ItemExists(Guid id)
121
+ {
122
+ return (_context.<%= controllerName %>s?.Any(e => e.Id == id)).GetValueOrDefault();
123
+ }
49
124
  }
50
- res.status(500).json({ message: 'Error updating document', error });
51
- }
52
- };
53
-
54
- // @desc Delete a <%= modelName %> by ID
55
- export const delete<%= modelName %>ById = async (req: Request, res: Response) => {
56
- try {
57
- const doc = await <%= modelName %>.findByIdAndDelete(req.params.id);
58
- if (!doc) return res.status(404).json({ message: 'Document not found' });
59
- // For DELETE, it's common to return a success message or just a 204 No Content status.
60
- res.status(200).json({ message: 'Document deleted successfully' });
61
- } catch (error) {
62
- res.status(500).json({ message: 'Error deleting document', error });
63
- }
64
- };
125
+ }
@@ -0,0 +1,15 @@
1
+ // Auto-generated by create-backlist
2
+ using Microsoft.EntityFrameworkCore;
3
+ using <%= projectName %>.Models;
4
+
5
+ namespace <%= projectName %>.Data
6
+ {
7
+ public class ApplicationDbContext : DbContext
8
+ {
9
+ public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
10
+
11
+ <% modelsToGenerate.forEach(model => { %>
12
+ public DbSet<<%= model.name %>> <%= model.name %>s { get; set; }
13
+ <% }); %>
14
+ }
15
+ }
@@ -0,0 +1,33 @@
1
+ # Auto-generated by create-backlist v5.0
2
+
3
+ # ---- Base Stage ----
4
+ FROM node:18-alpine AS base
5
+ WORKDIR /usr/src/app
6
+ COPY package*.json ./
7
+
8
+ # ---- Dependencies Stage ----
9
+ FROM base AS dependencies
10
+ RUN npm install --frozen-lockfile
11
+
12
+ # ---- Build Stage ----
13
+ FROM base AS build
14
+ COPY --from=dependencies /usr/src/app/node_modules ./node_modules
15
+ COPY . .
16
+ <% if (dbType === 'prisma') { %>
17
+ RUN npx prisma generate
18
+ <% } %>
19
+ RUN npm run build
20
+
21
+ # ---- Production Stage ----
22
+ FROM node:18-alpine AS production
23
+ WORKDIR /usr/src/app
24
+ COPY --from=build /usr/src/app/dist ./dist
25
+ COPY --from=dependencies /usr/src/app/node_modules ./node_modules
26
+ COPY package*.json ./
27
+ <% if (dbType === 'prisma') { %>
28
+ # Copy Prisma schema for runtime
29
+ COPY prisma ./prisma
30
+ <% } %>
31
+
32
+ EXPOSE <%= port %>
33
+ CMD ["node", "dist/server.js"]
@@ -0,0 +1,18 @@
1
+ // Auto-generated by create-backlist
2
+ namespace <%= projectName %>.Models
3
+ {
4
+ public class <%= modelName %>
5
+ {
6
+ public Guid Id { get; set; }
7
+
8
+ <% model.fields.forEach(field => { %>
9
+ <% let csharpType = 'string'; %>
10
+ <% if (field.type === 'Number') csharpType = 'int'; %>
11
+ <% if (field.type === 'Boolean') csharpType = 'bool'; %>
12
+ public <%= csharpType %> <%= field.name %> { get; set; }
13
+ <% }); %>
14
+
15
+ public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
16
+ public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
17
+ }
18
+ }
@@ -0,0 +1,66 @@
1
+ // Auto-generated by create-backlist v5.0 (Prisma Version)
2
+ import { Request, Response } from 'express';
3
+ import { prisma } from '../server'; // Import the Prisma client instance
4
+
5
+ // @desc Create a new <%= modelName %>
6
+ export const create<%= modelName %> = async (req: Request, res: Response) => {
7
+ try {
8
+ const newDoc = await prisma.<%= modelName.toLowerCase() %>.create({
9
+ data: req.body,
10
+ });
11
+ res.status(201).json(newDoc);
12
+ } catch (error) {
13
+ res.status(500).json({ message: 'Error creating document', error });
14
+ }
15
+ };
16
+
17
+ // @desc Get all <%= modelName %>s
18
+ export const getAll<%= modelName %>s = async (req: Request, res: Response) => {
19
+ try {
20
+ const docs = await prisma.<%= modelName.toLowerCase() %>.findMany();
21
+ res.status(200).json(docs);
22
+ } catch (error) {
23
+ res.status(500).json({ message: 'Error fetching documents', error });
24
+ }
25
+ };
26
+
27
+ // @desc Get a single <%= modelName %> by ID
28
+ export const get<%= modelName %>ById = async (req: Request, res: Response) => {
29
+ try {
30
+ const { id } = req.params;
31
+ const doc = await prisma.<%= modelName.toLowerCase() %>.findUnique({
32
+ where: { id },
33
+ });
34
+ if (!doc) return res.status(404).json({ message: 'Document not found' });
35
+ res.status(200).json(doc);
36
+ } catch (error) {
37
+ res.status(500).json({ message: 'Error fetching document', error });
38
+ }
39
+ };
40
+
41
+ // @desc Update a <%= modelName %> by ID
42
+ export const update<%= modelName %>ById = async (req: Request, res: Response) => {
43
+ try {
44
+ const { id } = req.params;
45
+ const doc = await prisma.<%= modelName.toLowerCase() %>.update({
46
+ where: { id },
47
+ data: req.body,
48
+ });
49
+ res.status(200).json(doc);
50
+ } catch (error) {
51
+ res.status(500).json({ message: 'Error updating document', error });
52
+ }
53
+ };
54
+
55
+ // @desc Delete a <%= modelName %> by ID
56
+ export const delete<%= modelName %>ById = async (req: Request, res: Response) => {
57
+ try {
58
+ const { id } = req.params;
59
+ await prisma.<%= modelName.toLowerCase() %>.delete({
60
+ where: { id },
61
+ });
62
+ res.status(200).json({ message: 'Document deleted successfully' });
63
+ } catch (error) {
64
+ res.status(500).json({ message: 'Error deleting document', error });
65
+ }
66
+ };
@@ -0,0 +1,28 @@
1
+ // Auto-generated by create-backlist v5.0
2
+
3
+ generator client {
4
+ provider = "prisma-client-js"
5
+ }
6
+
7
+ datasource db {
8
+ provider = "postgresql" // User can change to "mysql", "sqlite", "sqlserver", etc.
9
+ url = env("DATABASE_URL")
10
+ }
11
+
12
+ <%# Loop through each model identified by the analyzer %>
13
+ <% modelsToGenerate.forEach(model => { %>
14
+ model <%= model.name %> {
15
+ id String @id @default(cuid())
16
+ <%# Loop through each field in the model %>
17
+ <% model.fields.forEach(field => { %>
18
+ <%# Map JS types to Prisma types. This is a basic mapping. %>
19
+ <% let prismaType = 'String'; %>
20
+ <% if (field.type === 'Number') prismaType = 'Int'; %>
21
+ <% if (field.type === 'Boolean') prismaType = 'Boolean'; %>
22
+ <%= field.name.padEnd(10) %> <%= prismaType %><%- field.isOptional ? '?' : '' %><%- field.isUnique ? ' @unique' : '' %>
23
+ <% }); %>
24
+
25
+ createdAt DateTime @default(now())
26
+ updatedAt DateTime @updatedAt
27
+ }
28
+ <% }); %>
@@ -0,0 +1,47 @@
1
+ # Auto-generated by create-backlist v5.0
2
+ version: '3.8'
3
+
4
+ services:
5
+ app:
6
+ build: .
7
+ container_name: <%= projectName %>-app
8
+ ports:
9
+ - '<%= port %>:<%= port %>'
10
+ environment:
11
+ - PORT=<%= port %>
12
+ - DATABASE_URL=${DATABASE_URL}
13
+ - JWT_SECRET=${JWT_SECRET}
14
+ depends_on:
15
+ - db
16
+ volumes:
17
+ - .:/usr/src/app
18
+ - /usr/src/app/node_modules
19
+ command: npm run dev
20
+
21
+ db:
22
+ <% if (dbType === 'mongoose') { %>
23
+ image: mongo:latest
24
+ container_name: <%= projectName %>-mongo-db
25
+ ports:
26
+ - '27017:27017'
27
+ volumes:
28
+ - mongo-data:/data/db
29
+ <% } else if (dbType === 'prisma') { %>
30
+ image: postgres:14-alpine
31
+ container_name: <%= projectName %>-postgres-db
32
+ ports:
33
+ - '5432:5432'
34
+ environment:
35
+ - POSTGRES_USER=${DB_USER}
36
+ - POSTGRES_PASSWORD=${DB_PASSWORD}
37
+ - POSTGRES_DB=${DB_NAME}
38
+ volumes:
39
+ - postgres-data:/var/lib/postgresql/data
40
+ <% } %>
41
+
42
+ volumes:
43
+ <% if (dbType === 'mongoose') { %>
44
+ mongo-data:
45
+ <% } else if (dbType === 'prisma') { %>
46
+ postgres-data:
47
+ <% } %>
@@ -0,0 +1,38 @@
1
+ # Auto-generated by create-backlist v6.0
2
+ from fastapi import FastAPI
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ import uvicorn
5
+ import os
6
+
7
+ # Import generated routers
8
+ <% for (const controller of controllers) { %>
9
+ from app.routes import <%= controller.toLowerCase() %>_routes
10
+ <% } %>
11
+
12
+ # Create FastAPI app instance
13
+ app = FastAPI(title="<%= projectName %>")
14
+
15
+ # CORS (Cross-Origin Resource Sharing) Middleware
16
+ # This allows your frontend to communicate with this backend
17
+ app.add_middleware(
18
+ CORSMiddleware,
19
+ allow_origins=["*"], # In production, specify your frontend's origin
20
+ allow_credentials=True,
21
+ allow_methods=["*"],
22
+ allow_headers=["*"],
23
+ )
24
+
25
+ # Root endpoint
26
+ @app.get("/")
27
+ def read_root():
28
+ return {"message": "Welcome to the FastAPI backend generated by create-backlist!"}
29
+
30
+ # Include generated routers
31
+ <% for (const controller of controllers) { %>
32
+ app.include_router(<%= controller.toLowerCase() %>_routes.router, prefix="/api")
33
+ <% } %>
34
+
35
+
36
+ if __name__ == "__main__":
37
+ port = int(os.getenv("PORT", 8000))
38
+ uvicorn.run(app, host="0.0.0.0", port=port)
@@ -0,0 +1,4 @@
1
+ fastapi
2
+ uvicorn[standard]
3
+ pydantic
4
+ # Add other dependencies like 'sqlalchemy', 'psycopg2-binary' if using a database
@@ -0,0 +1,42 @@
1
+ # Auto-generated by create-backlist v6.0
2
+ from fastapi import APIRouter, status
3
+ from pydantic import BaseModel
4
+ from typing import List
5
+
6
+ # --- Pydantic Models for Request/Response Validation ---
7
+ # These are automatically generated based on your frontend code.
8
+
9
+ <% if (schema) { %>
10
+ class <%= modelName %>Base(BaseModel):
11
+ <% for (const field of schema.fields) { %>
12
+ <%= field.name %>: <%= field.type === 'Number' ? 'int' : 'str' %>
13
+ <% } %>
14
+
15
+ class <%= modelName %>(<%= modelName %>Base):
16
+ id: int # Or str, depending on your DB
17
+ # Add other fields like createdAt if needed
18
+ class Config:
19
+ orm_mode = True
20
+ <% } %>
21
+
22
+ # --- Router Definition ---
23
+ router = APIRouter(
24
+ prefix="/<%= modelName.toLowerCase() %>s",
25
+ tags=["<%= modelName %>s"]
26
+ )
27
+
28
+ # --- API Endpoints ---
29
+
30
+ @router.get("/", response_model=List[<%= modelName %>])
31
+ async def get_all_items():
32
+ # TODO: Implement database logic to fetch all items
33
+ # Example: return await db.query(<%= modelName %>).all()
34
+ return [{"id": 1, "name": "Example Item", "email": "example@test.com"}]
35
+
36
+ @router.post("/", status_code=status.HTTP_201_CREATED, response_model=<%= modelName %>)
37
+ async def create_item(item: <%= modelName %>Base):
38
+ # TODO: Implement database logic to create a new item
39
+ # Example: new_item = await db.create(<%= modelName %>, **item.dict())
40
+ return {**item.dict(), "id": 2}
41
+
42
+ # TODO: Add routes for GET (by id), PUT, and DELETE based on detected endpoints.