From 3bcc6f89b3f25289f2fc1b1d7a22f849cc7661b1 Mon Sep 17 00:00:00 2001 From: blake Date: Sat, 13 Dec 2025 12:07:34 -0600 Subject: [PATCH] scaler added and confirmed builds work --- backend/app.ts | 16 ++-- backend/src/routes/routeHandler.route.ts | 13 ++++ backend/src/routes/routeHandler.ts | 34 --------- backend/src/scaler/config.ts | 93 ++++++++++++++++++++++-- backend/src/scaler/specs/health.spec.ts | 37 ++++++++++ package-lock.json | 16 +++- package.json | 3 +- 7 files changed, 161 insertions(+), 51 deletions(-) create mode 100644 backend/src/routes/routeHandler.route.ts delete mode 100644 backend/src/routes/routeHandler.ts create mode 100644 backend/src/scaler/specs/health.spec.ts diff --git a/backend/app.ts b/backend/app.ts index 58a02e3..b02b333 100644 --- a/backend/app.ts +++ b/backend/app.ts @@ -1,10 +1,14 @@ import express from "express"; -import { setupRoutes } from "@/src/routes/routeHandler.js"; +import { setupRoutes } from "@/src/routes/routeHandler.route.js"; -const app = express(); +const startApp = async () => { + const app = express(); + const baseUrl = ""; + setupRoutes(baseUrl, app); -setupRoutes(app); + app.listen(3000, () => { + console.log("Listening on port 3000"); + }); +}; -app.listen(3000, () => { - console.log("Listening on port 3000"); -}); +startApp(); diff --git a/backend/src/routes/routeHandler.route.ts b/backend/src/routes/routeHandler.route.ts new file mode 100644 index 0000000..8eac48c --- /dev/null +++ b/backend/src/routes/routeHandler.route.ts @@ -0,0 +1,13 @@ +import type { Express, Response } from "express"; +import { setupApiDocsRoutes } from "../scaler/config.js"; + +export const setupRoutes = (baseUrl: string, app: Express) => { + //setup all the routes + setupApiDocsRoutes(baseUrl, app); + app.get(`${baseUrl}/`, (_, res: Response) => { + res.status(200).json({ + success: true, + message: "This is just an example of this working", + }); + }); +}; diff --git a/backend/src/routes/routeHandler.ts b/backend/src/routes/routeHandler.ts deleted file mode 100644 index 4cddb23..0000000 --- a/backend/src/routes/routeHandler.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { apiReference } from "@scalar/express-api-reference"; -import type { Express, Response } from "express"; -import { openApiSpec } from "../scaler/config.js"; - -export const setupRoutes = (app: Express) => { - /** - * @openapi - * /: - * get: - * summary: Health check - * responses: - * 200: - * description: Success - */ - app.get("/", (_, res: Response) => { - res.status(200).json({ - success: true, - message: "This is just an example of this working", - }); - }); - - app.get("/api/docs.json", (_, res) => { - res.json(openApiSpec); - }); - - app.use( - "/api/dos", - apiReference({ - // Put your OpenAPI url here: - url: "/openapi.json", - theme: "purple", - }), - ); -}; diff --git a/backend/src/scaler/config.ts b/backend/src/scaler/config.ts index 38df4f2..eb1bd33 100644 --- a/backend/src/scaler/config.ts +++ b/backend/src/scaler/config.ts @@ -1,12 +1,16 @@ //import path from "node:path"; //import { fileURLToPath } from "node:url"; -import type { OpenAPIV3_1 } from "openapi-types"; +import type { Express } from "express"; //const __filename = fileURLToPath(import.meta.url); // const __dirname = path.dirname(__filename); +import { apiReference } from "@scalar/express-api-reference"; // const port = 3000; -export const openApiSpec: OpenAPIV3_1.Document = { +import type { OpenAPIV3_1 } from "openapi-types"; +import { healthSpec } from "./specs/health.spec.js"; + +export const openApiBase: OpenAPIV3_1.Document = { openapi: "3.1.0", info: { title: "LST API", @@ -27,12 +31,87 @@ export const openApiSpec: OpenAPIV3_1.Document = { bearerFormat: "JWT", }, }, + schemas: { + Error: { + type: "object", + properties: { + error: { type: "string" }, + message: { type: "string" }, + }, + }, + }, }, - paths: {}, tags: [ - { name: "Health", description: "Health check endpoints" }, - { name: "Printing", description: "Label printing operations" }, - { name: "Silo", description: "Silo management" }, - { name: "TMS", description: "TMS integration" }, + // { name: "Health", description: "Health check endpoints" }, + // { name: "Printing", description: "Label printing operations" }, + // { name: "Silo", description: "Silo management" }, + // { name: "TMS", description: "TMS integration" }, ], + paths: {}, // Will be populated +}; + +export const setupApiDocsRoutes = (baseUrl: string, app: Express) => { + const fullSpec = { + ...openApiBase, + paths: { + ...healthSpec, + + // Add more specs here as you build features + }, + }; + app.get(`${baseUrl}/api/docs.json`, (_, res) => { + res.json(fullSpec); + }); + + app.use( + `${baseUrl}/api/docs`, + apiReference({ + url: `${baseUrl}/api/docs.json`, + theme: "purple", + darkMode: true, + authentication: { + securitySchemes: { + httpBasic: { + username: "username", + password: "password", + }, + }, + }, + defaultHttpClient: { + targetKey: "node", + clientKey: "axios", + }, + documentDownloadType: "json", + hideClientButton: true, + hiddenClients: { + // C + c: ["libcurl"], + // Clojure + clojure: ["clj_http"], + // C# + csharp: ["httpclient", "restsharp"], + // Dart + dart: ["http"], + // F# + fsharp: ["httpclient"], + // Java + java: ["asynchttp", "nethttp", "okhttp", "unirest"], + // Objective-C + objc: ["nsurlsession"], + // OCaml + ocaml: ["cohttp"], + // PHP + php: ["curl", "guzzle"], + + // R + r: ["httr"], + // Ruby + ruby: ["native"], + // Rust + rust: ["reqwest"], + // Swift + swift: ["nsurlsession"], + }, + }), + ); }; diff --git a/backend/src/scaler/specs/health.spec.ts b/backend/src/scaler/specs/health.spec.ts new file mode 100644 index 0000000..9da382e --- /dev/null +++ b/backend/src/scaler/specs/health.spec.ts @@ -0,0 +1,37 @@ +import type { OpenAPIV3_1 } from "openapi-types"; + +export const healthSpec: OpenAPIV3_1.PathsObject = { + "/": { + get: { + summary: "Health check", + description: "Check if the API is running", + //tags: ["Health"], + responses: { + "200": { + description: "API is healthy", + content: { + "application/json": { + schema: { + type: "object", + properties: { + success: { + type: "boolean", + example: true, + }, + message: { + type: "string", + example: "LST v3 is running", + }, + timestamp: { + type: "string", + format: "date-time", + }, + }, + }, + }, + }, + }, + }, + }, + }, +}; diff --git a/package-lock.json b/package-lock.json index 37b8fa6..886ff1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "version": "1.4.6", "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.4.6.tgz", "integrity": "sha512-cYjscr4wU5ZJPhk86JuUkecJT+LSYCFmUzYaitiLkizl+wCr1qdPFSEoAnRVZVTUEEoKpeS2XW69voBJ1NoB3g==", + "peer": true, "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.1.12" @@ -60,12 +61,14 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz", "integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@better-fetch/fetch": { "version": "1.1.18", "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.1.18.tgz", - "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==" + "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==", + "peer": true }, "node_modules/@biomejs/biome": { "version": "2.3.8", @@ -868,6 +871,7 @@ "integrity": "sha512-gqkrWUsS8hcm0r44yn7/xZeV1ERva/nLgrLxFRUGb7aoNMIJfZJ3AC261zDQuOAKC7MiXai1WCpYc48jAHoShQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1091,6 +1095,7 @@ "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.1.5.tgz", "integrity": "sha512-nQJ3S87v6wApbDwbZ++FrQiSiVxWvZdjaO+2v6lZJAG2WWggkB2CziUDjPciz3eAt9TqfRursIQMZIcpkBnvlw==", "license": "MIT", + "peer": true, "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", @@ -1842,6 +1847,7 @@ "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/panva" } @@ -1851,6 +1857,7 @@ "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.8.tgz", "integrity": "sha512-QUOgl5ZrS9IRuhq5FvOKFSsD/3+IA6MLE81/bOOTRA/YQpKDza2sFdN5g6JCB9BOpqMJDGefLCQ9F12hRS13TA==", "license": "MIT", + "peer": true, "engines": { "node": ">=20.0.0" } @@ -1988,6 +1995,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": "^20.0.0 || >=22.0.0" } @@ -2063,7 +2071,8 @@ "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/parseurl": { "version": "1.3.3", @@ -2627,6 +2636,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index c8db32c..08dca8b 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,9 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev:app": "cd backend && tsx watch app.ts", + "prebuild": "tsx backend/src/scaler/generateSpec.ts", "build": "esbuild backend/app.ts --bundle --platform=node --minify --outfile=dist/index.js --format=esm --packages=external", - "build:app": "ncc build backend/app.ts -o dist -m -s -e swagger-ui-express -e swagger-ui-dist -e swagger-jsdoc", + "build:app": "ncc build backend/app.ts -o dist -m -s", "lint": "tsc", "start": "node dist/index.js" },