feat(swagger): added in the start of swagger where all the common and useable endpoints will be

This commit is contained in:
2025-11-25 17:02:20 -06:00
parent bdb4bfc53d
commit 2607fd3026
8 changed files with 238 additions and 20 deletions

View File

@@ -20,9 +20,7 @@ import { baseSettings } from "./src/internal/system/controller/settings/baseSett
import { import {
addListeners, addListeners,
manualFixes, manualFixes,
settingsMigrate,
} from "./src/internal/system/utlis/addListeners.js"; } from "./src/internal/system/utlis/addListeners.js";
import { swaggerOptions } from "./src/pkg/apiDocs/swaggerOptions.js";
import { auth } from "./src/pkg/auth/auth.js"; import { auth } from "./src/pkg/auth/auth.js";
import { db } from "./src/pkg/db/db.js"; import { db } from "./src/pkg/db/db.js";
import { settings } from "./src/pkg/db/schema/settings.js"; import { settings } from "./src/pkg/db/schema/settings.js";
@@ -35,6 +33,9 @@ import { sendNotify } from "./src/pkg/utils/notify.js";
import { returnFunc } from "./src/pkg/utils/return.js"; import { returnFunc } from "./src/pkg/utils/return.js";
import { tryCatch } from "./src/pkg/utils/tryCatch.js"; import { tryCatch } from "./src/pkg/utils/tryCatch.js";
import { setupIoServer } from "./src/ws/server.js"; import { setupIoServer } from "./src/ws/server.js";
import { swaggerConfig, swaggerUiOptions } from "./src/internal/swagger/config.js";
import { setupSwagger } from "./src/internal/swagger/swagger.js";
const main = async () => { const main = async () => {
const env = validateEnv(process.env); const env = validateEnv(process.env);
@@ -177,13 +178,14 @@ const main = async () => {
); );
// docs and routes // docs and routes
const openapiSpec: any = swaggerJsdoc(swaggerOptions); // const openapiSpec: any = swaggerJsdoc(swaggerConfig);
app.use( // app.use(
basePath + "/api/docs", // basePath + "/api/docs",
swaggerUi.serve, // swaggerUi.serve,
swaggerUi.setup(openapiSpec), // swaggerUi.setup(openapiSpec, swaggerUiOptions),
); // );
setupSwagger(app, basePath)
app.use(basePath + "/d", express.static(join(__dirname, "../lstDocs/build"))); app.use(basePath + "/d", express.static(join(__dirname, "../lstDocs/build")));
app.use( app.use(
basePath + "/app", basePath + "/app",

View File

@@ -24,6 +24,13 @@ router.post("/", async (req: Request, res: Response) => {
.from(user) .from(user)
.where(eq(user.username, validated.username)); .where(eq(user.username, validated.username));
if(userLogin.length === 0 ){
return res.status(200).json({
success: false,
message: `It appears you do not have a user yet please head over to the register page and create a user then try again.`,
});
}
if ( if (
!userLogin[0].lastLogin || !userLogin[0].lastLogin ||
differenceInDays(userLogin[0].lastLogin, new Date(Date.now())) > 120 differenceInDays(userLogin[0].lastLogin, new Date(Date.now())) > 120

View File

@@ -0,0 +1,60 @@
export const swaggerUiOptions = {
explorer: true,
customCss: '.swagger-ui .topbar { display: none }',
customSiteTitle: 'Your API Documentation',
swaggerOptions: {
persistAuthorization: true,
displayRequestDuration: true,
filter: true,
syntaxHighlight: {
activate: true,
theme: 'monokai'
}
}
};
export const swaggerConfig = {
definition: {
openapi: '3.0.0',
info: {
title: 'Logistics Support Tool',
version: '1.8.0',
description: 'Complete API documentation for lst',
contact: {
name: 'API Support',
email: 'blake.matthes@alpla.com'
}
},
servers: [
{
url: 'http://localhost:4200',
description: 'Development server'
},
{
url: 'https://api.yourapp.com',
description: 'Production server'
}
],
components: {
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT'
},
apiKey: {
type: 'apiKey',
in: 'header',
name: 'X-API-Key'
}
}
},
security: [
{
bearerAuth: []
}
]
},
apis: [] // We'll populate this dynamically
};

View File

@@ -0,0 +1,129 @@
const loginEndpoint = {
'/lst/api/user/login': {
post: {
tags: ['Authentication'],
summary: 'Login to get a token',
description: 'User enters username and password, gets back a JWT token and session data',
// What the user sends you
requestBody: {
required: true,
content: {
'application/json': {
schema: {
type: 'object',
required: ['username', 'password'],
properties: {
username: {
type: 'string',
example: 'smith01'
},
password: {
type: 'string',
example: 'MyPassword123'
}
}
}
}
}
},
// What you send back to the user
responses: {
// SUCCESS - Login worked
200: {
description: 'Login successful',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: true
},
message: {
type: 'string',
example: 'Login successful'
},
data: {
type: 'object',
properties: {
token: {
type: 'string',
example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
},
user: {
type: 'object',
properties: {
id: {
type: 'string',
example: '12345'
},
email: {
type: 'string',
example: 'user@example.com'
},
username: {
type: 'string',
example: 'johndoe'
}
}
}
}
}
}
}
}
}
},
// ERROR - Wrong password or email
401: {
description: 'Wrong email or password',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: false
},
message: {
type: 'string',
example: 'Invalid credentials'
}
}
}
}
}
},
// ERROR - Missing fields
400: {
description: 'Missing email or password',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: false
},
message: {
type: 'string',
example: 'Email and password are required'
}
}
}
}
}
}
}
}
}
};
export default loginEndpoint;

View File

@@ -0,0 +1,31 @@
import swaggerJsdoc from 'swagger-jsdoc';
import swaggerUi from 'swagger-ui-express';
import { swaggerConfig, swaggerUiOptions } from './config.js';
import { type Express } from 'express';
import loginEndpoint from './endpoints/auth/login.js';
const allPaths = {
...loginEndpoint,
// When you add more endpoints, add them here:
// ...registerEndpoint,
// ...logoutEndpoint,
};
const swaggerSpec = {
...swaggerConfig.definition,
paths: allPaths
};
const specs = swaggerJsdoc({
...swaggerConfig,
definition: swaggerSpec
});
export function setupSwagger(app: Express, basePath: string): void {
// Swagger UI at /api-docs
app.use(basePath + "/api/docs", swaggerUi.serve, swaggerUi.setup(specs, swaggerUiOptions));
//console.log('📚 Swagger docs at http://localhost:3000/api-docs');
}

View File

@@ -1,11 +0,0 @@
export const swaggerOptions = {
definition: {
openapi: "3.0.0",
info: {
title: "Logistics Support Tool",
version: "1.0.0",
},
},
// globs where swagger-jsdoc should look for annotations:
apis: ["../../src/**/*.ts"],
};