feat(swagger): added in the start of swagger where all the common and useable endpoints will be
This commit is contained in:
20
app/main.ts
20
app/main.ts
@@ -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",
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
60
app/src/internal/swagger/config.ts
Normal file
60
app/src/internal/swagger/config.ts
Normal 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
|
||||||
|
};
|
||||||
129
app/src/internal/swagger/endpoints/auth/login.ts
Normal file
129
app/src/internal/swagger/endpoints/auth/login.ts
Normal 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;
|
||||||
0
app/src/internal/swagger/schemas/auth.schema.ts
Normal file
0
app/src/internal/swagger/schemas/auth.schema.ts
Normal file
0
app/src/internal/swagger/schemas/common.schema.ts
Normal file
0
app/src/internal/swagger/schemas/common.schema.ts
Normal file
31
app/src/internal/swagger/swagger.ts
Normal file
31
app/src/internal/swagger/swagger.ts
Normal 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');
|
||||||
|
}
|
||||||
@@ -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"],
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user