Skip to content

Commit db610b4

Browse files
Add public facing directory
1 parent 595c1b7 commit db610b4

File tree

7 files changed

+388
-4
lines changed

7 files changed

+388
-4
lines changed

.github/workflows/stainless.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Upload OpenAPI spec to Stainless
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
jobs:
8+
stainless:
9+
concurrency: upload-openapi-spec-action
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: stainless-api/upload-openapi-spec-action@main
14+
with:
15+
stainless_api_key: ${{ secrets.STAINLESS_API_KEY }}
16+
input_path: 'path/to/my-company-openapi.json'
17+
config_path: 'path/to/my-company.stainless.yaml'
18+
project_name: 'my-stainless-project'

src/lib/.keep

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/lib/index.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const express = require('express');
2+
const bodyParser = require('body-parser');
3+
const cors = require('cors');
4+
const path = require('path');
5+
const swaggerUi = require('swagger-ui-express');
6+
const openApiSpec = require('../swagger/openapi.json');
7+
8+
const app = express();
9+
const PORT = process.env.PORT || 3000;
10+
11+
app.use(cors());
12+
app.use(bodyParser.json());
13+
14+
// Routes
15+
const projectRoutes = require('./routes/projects');
16+
const taskRoutes = require('./routes/tasks');
17+
const userRoutes = require('./routes/users');
18+
19+
app.use('/api/projects', projectRoutes);
20+
app.use('/api/tasks', taskRoutes);
21+
app.use('/api/users', userRoutes);
22+
23+
// Swagger UI
24+
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(openApiSpec));
25+
26+
// OpenAPI JSON
27+
app.get('/openapi.json', (req, res) => {
28+
res.sendFile(path.join(__dirname, '../swagger/openapi.json'));
29+
});
30+
31+
app.listen(PORT, () => {
32+
console.log(`Server is running on http://localhost:${PORT}`);
33+
console.log(`API documentation available at http://localhost:${PORT}/api-docs`);
34+
console.log(`OpenAPI JSON available at http://localhost:${PORT}/openapi.json`);
35+
});

src/lib/routes/projects.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const express = require('express');
2+
const router = express.Router();
3+
4+
const projects = [
5+
{ id: 1, name: 'Website Redesign', description: 'Redesign the corporate website' },
6+
{ id: 2, name: 'App Launch', description: 'Prepare and launch the mobile app' },
7+
];
8+
9+
// Get all projects
10+
router.get('/', (req, res) => {
11+
res.json(projects);
12+
});
13+
14+
// Get a single project
15+
router.get('/:id', (req, res) => {
16+
const project = projects.find((p) => p.id === parseInt(req.params.id));
17+
if (!project) return res.status(404).json({ error: 'Project not found' });
18+
res.json(project);
19+
});
20+
21+
// Add a new project
22+
router.post('/', (req, res) => {
23+
const { name, description } = req.body;
24+
25+
if (!name || !description) {
26+
return res.status(400).json({ error: 'Name and description are required' });
27+
}
28+
29+
const newProject = {
30+
id: projects.length + 1,
31+
name,
32+
description,
33+
};
34+
35+
projects.push(newProject);
36+
res.status(201).json(newProject);
37+
});
38+
39+
module.exports = router;

src/lib/routes/tasks.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const express = require('express');
2+
const router = express.Router();
3+
4+
const tasks = [
5+
{ id: 1, projectId: 1, title: 'Wireframe Design', status: 'In Progress' },
6+
{ id: 2, projectId: 2, title: 'Marketing Campaign', status: 'Not Started' },
7+
];
8+
9+
// Get all tasks
10+
router.get('/', (req, res) => {
11+
res.json(tasks);
12+
});
13+
14+
// Get tasks for a project
15+
router.get('/project/:projectId', (req, res) => {
16+
const projectTasks = tasks.filter((t) => t.projectId === parseInt(req.params.projectId));
17+
res.json(projectTasks);
18+
});
19+
20+
// Add a new task
21+
router.post('/', (req, res) => {
22+
const { projectId, title, status } = req.body;
23+
24+
if (!projectId || !title || !status) {
25+
return res.status(400).json({ error: 'Project ID, title, and status are required' });
26+
}
27+
28+
const newTask = {
29+
id: tasks.length + 1,
30+
projectId,
31+
title,
32+
status,
33+
};
34+
35+
tasks.push(newTask);
36+
res.status(201).json(newTask);
37+
});
38+
39+
// Update a task
40+
router.put('/:id', (req, res) => {
41+
const { id } = req.params;
42+
const { title, status } = req.body;
43+
44+
const task = tasks.find((t) => t.id === parseInt(id));
45+
if (!task) return res.status(404).json({ error: 'Task not found' });
46+
47+
if (title) task.title = title;
48+
if (status) task.status = status;
49+
50+
res.json(task);
51+
});
52+
53+
module.exports = router;

src/lib/routes/users.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const express = require('express');
2+
const router = express.Router();
3+
4+
const users = [
5+
{ id: 1, name: 'Alice', email: '[email protected]' },
6+
{ id: 2, name: 'Bob', email: '[email protected]' },
7+
];
8+
9+
// Get all users
10+
router.get('/', (req, res) => {
11+
res.json(users);
12+
});
13+
14+
// Add a new user
15+
router.post('/', (req, res) => {
16+
const { name, email } = req.body;
17+
18+
if (!name || !email) {
19+
return res.status(400).json({ error: 'Name and email are required' });
20+
}
21+
22+
const newUser = {
23+
id: users.length + 1,
24+
name,
25+
email,
26+
};
27+
28+
users.push(newUser);
29+
res.status(201).json(newUser);
30+
});
31+
32+
module.exports = router;

src/lib/swagger/openapi.json

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
{
2+
"openapi": "3.0.0",
3+
"info": {
4+
"title": "The LightSwitch API",
5+
"version": "1.0.0",
6+
"description": "API for managing projects, tasks, and users."
7+
},
8+
"servers": [
9+
{
10+
"url": "https://lightswitch.gitbook.dev/api"
11+
}
12+
],
13+
"paths": {
14+
"/projects": {
15+
"get": {
16+
"summary": "Get all projects",
17+
"responses": {
18+
"200": {
19+
"description": "List of projects",
20+
"content": {
21+
"application/json": {
22+
"schema": {
23+
"type": "array",
24+
"items": {
25+
"$ref": "#/components/schemas/Project"
26+
}
27+
}
28+
}
29+
}
30+
}
31+
}
32+
},
33+
"post": {
34+
"summary": "Add a new project",
35+
"requestBody": {
36+
"content": {
37+
"application/json": {
38+
"schema": {
39+
"$ref": "#/components/schemas/Project"
40+
}
41+
}
42+
},
43+
"required": true
44+
},
45+
"responses": {
46+
"201": {
47+
"description": "Project created",
48+
"content": {
49+
"application/json": {
50+
"$ref": "#/components/schemas/Project"
51+
}
52+
}
53+
}
54+
}
55+
}
56+
},
57+
"/tasks": {
58+
"get": {
59+
"summary": "Get all tasks",
60+
"responses": {
61+
"200": {
62+
"description": "List of tasks",
63+
"content": {
64+
"application/json": {
65+
"schema": {
66+
"type": "array",
67+
"items": {
68+
"$ref": "#/components/schemas/Task"
69+
}
70+
}
71+
}
72+
}
73+
}
74+
}
75+
},
76+
"post": {
77+
"summary": "Add a new task",
78+
"requestBody": {
79+
"content": {
80+
"application/json": {
81+
"schema": {
82+
"$ref": "#/components/schemas/Task"
83+
}
84+
}
85+
},
86+
"required": true
87+
},
88+
"responses": {
89+
"201": {
90+
"description": "Task created",
91+
"content": {
92+
"application/json": {
93+
"$ref": "#/components/schemas/Task"
94+
}
95+
}
96+
}
97+
}
98+
}
99+
},
100+
"/tasks/{task_id}": {
101+
"put": {
102+
"summary": "Update a task",
103+
"parameters": [
104+
{
105+
"name": "task_id",
106+
"in": "path",
107+
"required": true,
108+
"schema": {
109+
"type": "integer"
110+
},
111+
"description": "Task ID to update"
112+
}
113+
],
114+
"requestBody": {
115+
"content": {
116+
"application/json": {
117+
"schema": {
118+
"$ref": "#/components/schemas/Task"
119+
}
120+
}
121+
},
122+
"required": true
123+
},
124+
"responses": {
125+
"200": {
126+
"description": "Task updated",
127+
"content": {
128+
"application/json": {
129+
"schema": {
130+
"$ref": "#/components/schemas/Task"
131+
}
132+
}
133+
}
134+
}
135+
}
136+
}
137+
},
138+
"/users": {
139+
"get": {
140+
"summary": "Get all users",
141+
"responses": {
142+
"200": {
143+
"description": "List of users",
144+
"content": {
145+
"application/json": {
146+
"schema": {
147+
"type": "array",
148+
"items": {
149+
"$ref": "#/components/schemas/User"
150+
}
151+
}
152+
}
153+
}
154+
}
155+
}
156+
},
157+
"post": {
158+
"summary": "Add a new user",
159+
"requestBody": {
160+
"content": {
161+
"application/json": {
162+
"schema": {
163+
"$ref": "#/components/schemas/User"
164+
}
165+
}
166+
},
167+
"required": true
168+
},
169+
"responses": {
170+
"201": {
171+
"description": "User created",
172+
"content": {
173+
"application/json": {
174+
"$ref": "#/components/schemas/User"
175+
}
176+
}
177+
}
178+
}
179+
}
180+
}
181+
},
182+
"components": {
183+
"schemas": {
184+
"Project": {
185+
"type": "object",
186+
"properties": {
187+
"id": { "type": "integer" },
188+
"name": { "type": "string" },
189+
"description": { "type": "string" }
190+
}
191+
},
192+
"Task": {
193+
"type": "object",
194+
"properties": {
195+
"id": { "type": "integer" },
196+
"projectId": { "type": "integer" },
197+
"title": { "type": "string" },
198+
"status": { "type": "string" }
199+
}
200+
},
201+
"User": {
202+
"type": "object",
203+
"properties": {
204+
"id": { "type": "integer" },
205+
"name": { "type": "string" },
206+
"email": { "type": "string" }
207+
}
208+
}
209+
}
210+
}
211+
}

0 commit comments

Comments
 (0)