refactor(api docks): added api docks back into the front end and prep for docusorus
All checks were successful
Build and Push LST Docker Image / docker (push) Successful in 2m15s

This commit is contained in:
2026-06-16 18:53:44 -05:00
parent 6a14bab30c
commit 3a24d62957
11 changed files with 229 additions and 248 deletions

View File

@@ -9,8 +9,6 @@ import os from "node:os";
import { apiReference } from "@scalar/express-api-reference"; import { apiReference } from "@scalar/express-api-reference";
// const port = 3000; // const port = 3000;
import type { OpenAPIV3_1 } from "openapi-types"; import type { OpenAPIV3_1 } from "openapi-types";
import { cronerActiveJobs } from "../scaler/cronerActiveJobs.spec.js";
import { cronerStatusChange } from "../scaler/cronerStatusChange.spec.js";
import { prodLoginSpec } from "../scaler/login.spec.js"; import { prodLoginSpec } from "../scaler/login.spec.js";
import { openDockApt } from "../scaler/opendockGetRelease.spec.js"; import { openDockApt } from "../scaler/opendockGetRelease.spec.js";
import { prodRestartSpec } from "../scaler/prodSqlRestart.spec.js"; import { prodRestartSpec } from "../scaler/prodSqlRestart.spec.js";
@@ -125,8 +123,6 @@ export const setupApiDocsRoutes = (baseUrl: string, app: Express) => {
...prodLoginSpec, ...prodLoginSpec,
...prodRegisterSpec, ...prodRegisterSpec,
//...mergedDatamart, //...mergedDatamart,
...cronerActiveJobs,
...cronerStatusChange,
...openDockApt, ...openDockApt,
// Add more specs here as you build features // Add more specs here as you build features

View File

@@ -1,43 +0,0 @@
import type { OpenAPIV3_1 } from "openapi-types";
export const cronerActiveJobs: OpenAPIV3_1.PathsObject = {
"/api/utils/croner": {
get: {
summary: "Cron jobs",
description: "Returns all jobs on the server.",
tags: ["Utils"],
responses: {
"200": {
description: "Jobs returned",
content: {
"application/json": {
schema: {
type: "object",
properties: {
status: {
type: "boolean",
format: "boolean",
example: true,
},
uptime: {
type: "number",
format: "3454.34",
example: 3454.34,
},
memoryUsage: {
type: "string",
format: "Heap: 11.62 MB / RSS: 86.31 MB",
},
sqlServerStats: {
type: "number",
format: "442127",
},
},
},
},
},
},
},
},
},
};

View File

@@ -1,94 +0,0 @@
import type { OpenAPIV3_1 } from "openapi-types";
export const cronerStatusChange: OpenAPIV3_1.PathsObject = {
"/api/utils/croner/{status}": {
patch: {
summary: "Pauses or Resume the Job",
description:
"When sending start or stop with job name it will resume or stop the job",
tags: ["Utils"],
parameters: [
{
name: "status",
in: "path",
required: true,
description: "Status change",
schema: {
type: "string",
},
example: "start",
},
{
name: "limit",
in: "query",
required: false, // 👈 optional
description: "Maximum number of records to return",
schema: {
type: "integer",
minimum: 1,
maximum: 100,
},
example: 10,
},
],
requestBody: {
required: true,
content: {
"application/json": {
schema: {
type: "object",
required: ["name"],
properties: {
name: {
type: "string",
example: "start",
},
},
},
},
},
},
responses: {
"200": {
description: "Successful response",
content: {
"application/json": {
schema: {
type: "object",
properties: {
success: { type: "boolean", example: true },
data: {
type: "object",
example: {
name: "exampleName",
value: "some value",
},
},
},
},
},
},
},
"400": {
description: "Bad request",
content: {
"application/json": {
schema: {
type: "object",
properties: {
success: { type: "boolean", example: false },
message: {
type: "string",
example: "Invalid name parameter",
},
},
},
},
},
},
},
},
},
};

View File

@@ -1,10 +1,14 @@
import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
import { Link } from "@tanstack/react-router";
import { LaptopMinimal } from "lucide-react";
import { import {
Sidebar, Sidebar,
SidebarContent, SidebarContent,
SidebarHeader, SidebarFooter,
SidebarMenu, SidebarMenu,
SidebarMenuButton,
SidebarMenuItem, SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar"; } from "@/components/ui/sidebar";
import { useSession } from "@/lib/auth-client"; import { useSession } from "@/lib/auth-client";
import { getSettings } from "../../lib/queries/getSettings"; import { getSettings } from "../../lib/queries/getSettings";
@@ -23,6 +27,7 @@ export function AppSidebar() {
openDock: ["read"], openDock: ["read"],
}), }),
); );
const { setOpen } = useSidebar();
// const { data: canReadWarehouse = false } = useQuery( // const { data: canReadWarehouse = false } = useQuery(
// permissionQuery({ // permissionQuery({
@@ -36,7 +41,7 @@ export function AppSidebar() {
collapsible="offcanvas" collapsible="offcanvas"
className="top-(--header-height) h-[calc(100svh-var(--header-height))]!" className="top-(--header-height) h-[calc(100svh-var(--header-height))]!"
> >
<SidebarHeader> <SidebarContent>
<SidebarMenu> <SidebarMenu>
<SidebarMenuItem> <SidebarMenuItem>
<SidebarContent> <SidebarContent>
@@ -64,7 +69,24 @@ export function AppSidebar() {
</SidebarContent> </SidebarContent>
</SidebarMenuItem> </SidebarMenuItem>
</SidebarMenu> </SidebarMenu>
</SidebarHeader> </SidebarContent>
{session &&
(session.user.role === "admin" ||
session.user.role === "systemAdmin" ||
session.user.role === "manager") && (
<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<Link to={"/apidocs"} onClick={() => setOpen(false)}>
<LaptopMinimal />
<span>Api docs</span>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
)}
</Sidebar> </Sidebar>
); );
} }

View File

@@ -11,9 +11,11 @@
import { Route as rootRouteImport } from './routes/__root' import { Route as rootRouteImport } from './routes/__root'
import { Route as ForbiddenRouteImport } from './routes/forbidden' import { Route as ForbiddenRouteImport } from './routes/forbidden'
import { Route as AppDownRouteImport } from './routes/app-down' import { Route as AppDownRouteImport } from './routes/app-down'
import { Route as ApidocsRouteImport } from './routes/apidocs'
import { Route as AboutRouteImport } from './routes/about' import { Route as AboutRouteImport } from './routes/about'
import { Route as IndexRouteImport } from './routes/index' import { Route as IndexRouteImport } from './routes/index'
import { Route as DocsIndexRouteImport } from './routes/docs/index' import { Route as DocsIndexRouteImport } from './routes/docs/index'
import { Route as DocsDatamartRouteImport } from './routes/docs/datamart'
import { Route as DocsSplatRouteImport } from './routes/docs/$' import { Route as DocsSplatRouteImport } from './routes/docs/$'
import { Route as AdminUsersRouteImport } from './routes/admin/users' import { Route as AdminUsersRouteImport } from './routes/admin/users'
import { Route as AdminSettingsRouteImport } from './routes/admin/settings' import { Route as AdminSettingsRouteImport } from './routes/admin/settings'
@@ -41,6 +43,11 @@ const AppDownRoute = AppDownRouteImport.update({
path: '/app-down', path: '/app-down',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any) } as any)
const ApidocsRoute = ApidocsRouteImport.update({
id: '/apidocs',
path: '/apidocs',
getParentRoute: () => rootRouteImport,
} as any)
const AboutRoute = AboutRouteImport.update({ const AboutRoute = AboutRouteImport.update({
id: '/about', id: '/about',
path: '/about', path: '/about',
@@ -56,6 +63,11 @@ const DocsIndexRoute = DocsIndexRouteImport.update({
path: '/docs/', path: '/docs/',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any) } as any)
const DocsDatamartRoute = DocsDatamartRouteImport.update({
id: '/docs/datamart',
path: '/docs/datamart',
getParentRoute: () => rootRouteImport,
} as any)
const DocsSplatRoute = DocsSplatRouteImport.update({ const DocsSplatRoute = DocsSplatRouteImport.update({
id: '/docs/$', id: '/docs/$',
path: '/docs/$', path: '/docs/$',
@@ -145,6 +157,7 @@ const WarehouseDockdoorscanningScansDockScansRoute =
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
'/': typeof IndexRoute '/': typeof IndexRoute
'/about': typeof AboutRoute '/about': typeof AboutRoute
'/apidocs': typeof ApidocsRoute
'/app-down': typeof AppDownRoute '/app-down': typeof AppDownRoute
'/forbidden': typeof ForbiddenRoute '/forbidden': typeof ForbiddenRoute
'/login': typeof authLoginRoute '/login': typeof authLoginRoute
@@ -155,6 +168,7 @@ export interface FileRoutesByFullPath {
'/admin/settings': typeof AdminSettingsRoute '/admin/settings': typeof AdminSettingsRoute
'/admin/users': typeof AdminUsersRoute '/admin/users': typeof AdminUsersRoute
'/docs/$': typeof DocsSplatRoute '/docs/$': typeof DocsSplatRoute
'/docs/datamart': typeof DocsDatamartRoute
'/docs/': typeof DocsIndexRoute '/docs/': typeof DocsIndexRoute
'/user/profile': typeof authUserProfileRoute '/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute '/user/resetpassword': typeof authUserResetpasswordRoute
@@ -168,6 +182,7 @@ export interface FileRoutesByFullPath {
export interface FileRoutesByTo { export interface FileRoutesByTo {
'/': typeof IndexRoute '/': typeof IndexRoute
'/about': typeof AboutRoute '/about': typeof AboutRoute
'/apidocs': typeof ApidocsRoute
'/app-down': typeof AppDownRoute '/app-down': typeof AppDownRoute
'/forbidden': typeof ForbiddenRoute '/forbidden': typeof ForbiddenRoute
'/login': typeof authLoginRoute '/login': typeof authLoginRoute
@@ -178,6 +193,7 @@ export interface FileRoutesByTo {
'/admin/settings': typeof AdminSettingsRoute '/admin/settings': typeof AdminSettingsRoute
'/admin/users': typeof AdminUsersRoute '/admin/users': typeof AdminUsersRoute
'/docs/$': typeof DocsSplatRoute '/docs/$': typeof DocsSplatRoute
'/docs/datamart': typeof DocsDatamartRoute
'/docs': typeof DocsIndexRoute '/docs': typeof DocsIndexRoute
'/user/profile': typeof authUserProfileRoute '/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute '/user/resetpassword': typeof authUserResetpasswordRoute
@@ -192,6 +208,7 @@ export interface FileRoutesById {
__root__: typeof rootRouteImport __root__: typeof rootRouteImport
'/': typeof IndexRoute '/': typeof IndexRoute
'/about': typeof AboutRoute '/about': typeof AboutRoute
'/apidocs': typeof ApidocsRoute
'/app-down': typeof AppDownRoute '/app-down': typeof AppDownRoute
'/forbidden': typeof ForbiddenRoute '/forbidden': typeof ForbiddenRoute
'/(auth)/login': typeof authLoginRoute '/(auth)/login': typeof authLoginRoute
@@ -202,6 +219,7 @@ export interface FileRoutesById {
'/admin/settings': typeof AdminSettingsRoute '/admin/settings': typeof AdminSettingsRoute
'/admin/users': typeof AdminUsersRoute '/admin/users': typeof AdminUsersRoute
'/docs/$': typeof DocsSplatRoute '/docs/$': typeof DocsSplatRoute
'/docs/datamart': typeof DocsDatamartRoute
'/docs/': typeof DocsIndexRoute '/docs/': typeof DocsIndexRoute
'/(auth)/user/profile': typeof authUserProfileRoute '/(auth)/user/profile': typeof authUserProfileRoute
'/(auth)/user/resetpassword': typeof authUserResetpasswordRoute '/(auth)/user/resetpassword': typeof authUserResetpasswordRoute
@@ -217,6 +235,7 @@ export interface FileRouteTypes {
fullPaths: fullPaths:
| '/' | '/'
| '/about' | '/about'
| '/apidocs'
| '/app-down' | '/app-down'
| '/forbidden' | '/forbidden'
| '/login' | '/login'
@@ -227,6 +246,7 @@ export interface FileRouteTypes {
| '/admin/settings' | '/admin/settings'
| '/admin/users' | '/admin/users'
| '/docs/$' | '/docs/$'
| '/docs/datamart'
| '/docs/' | '/docs/'
| '/user/profile' | '/user/profile'
| '/user/resetpassword' | '/user/resetpassword'
@@ -240,6 +260,7 @@ export interface FileRouteTypes {
to: to:
| '/' | '/'
| '/about' | '/about'
| '/apidocs'
| '/app-down' | '/app-down'
| '/forbidden' | '/forbidden'
| '/login' | '/login'
@@ -250,6 +271,7 @@ export interface FileRouteTypes {
| '/admin/settings' | '/admin/settings'
| '/admin/users' | '/admin/users'
| '/docs/$' | '/docs/$'
| '/docs/datamart'
| '/docs' | '/docs'
| '/user/profile' | '/user/profile'
| '/user/resetpassword' | '/user/resetpassword'
@@ -263,6 +285,7 @@ export interface FileRouteTypes {
| '__root__' | '__root__'
| '/' | '/'
| '/about' | '/about'
| '/apidocs'
| '/app-down' | '/app-down'
| '/forbidden' | '/forbidden'
| '/(auth)/login' | '/(auth)/login'
@@ -273,6 +296,7 @@ export interface FileRouteTypes {
| '/admin/settings' | '/admin/settings'
| '/admin/users' | '/admin/users'
| '/docs/$' | '/docs/$'
| '/docs/datamart'
| '/docs/' | '/docs/'
| '/(auth)/user/profile' | '/(auth)/user/profile'
| '/(auth)/user/resetpassword' | '/(auth)/user/resetpassword'
@@ -287,6 +311,7 @@ export interface FileRouteTypes {
export interface RootRouteChildren { export interface RootRouteChildren {
IndexRoute: typeof IndexRoute IndexRoute: typeof IndexRoute
AboutRoute: typeof AboutRoute AboutRoute: typeof AboutRoute
ApidocsRoute: typeof ApidocsRoute
AppDownRoute: typeof AppDownRoute AppDownRoute: typeof AppDownRoute
ForbiddenRoute: typeof ForbiddenRoute ForbiddenRoute: typeof ForbiddenRoute
authLoginRoute: typeof authLoginRoute authLoginRoute: typeof authLoginRoute
@@ -297,6 +322,7 @@ export interface RootRouteChildren {
AdminSettingsRoute: typeof AdminSettingsRoute AdminSettingsRoute: typeof AdminSettingsRoute
AdminUsersRoute: typeof AdminUsersRoute AdminUsersRoute: typeof AdminUsersRoute
DocsSplatRoute: typeof DocsSplatRoute DocsSplatRoute: typeof DocsSplatRoute
DocsDatamartRoute: typeof DocsDatamartRoute
DocsIndexRoute: typeof DocsIndexRoute DocsIndexRoute: typeof DocsIndexRoute
authUserProfileRoute: typeof authUserProfileRoute authUserProfileRoute: typeof authUserProfileRoute
authUserResetpasswordRoute: typeof authUserResetpasswordRoute authUserResetpasswordRoute: typeof authUserResetpasswordRoute
@@ -324,6 +350,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppDownRouteImport preLoaderRoute: typeof AppDownRouteImport
parentRoute: typeof rootRouteImport parentRoute: typeof rootRouteImport
} }
'/apidocs': {
id: '/apidocs'
path: '/apidocs'
fullPath: '/apidocs'
preLoaderRoute: typeof ApidocsRouteImport
parentRoute: typeof rootRouteImport
}
'/about': { '/about': {
id: '/about' id: '/about'
path: '/about' path: '/about'
@@ -345,6 +378,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DocsIndexRouteImport preLoaderRoute: typeof DocsIndexRouteImport
parentRoute: typeof rootRouteImport parentRoute: typeof rootRouteImport
} }
'/docs/datamart': {
id: '/docs/datamart'
path: '/docs/datamart'
fullPath: '/docs/datamart'
preLoaderRoute: typeof DocsDatamartRouteImport
parentRoute: typeof rootRouteImport
}
'/docs/$': { '/docs/$': {
id: '/docs/$' id: '/docs/$'
path: '/docs/$' path: '/docs/$'
@@ -463,6 +503,7 @@ declare module '@tanstack/react-router' {
const rootRouteChildren: RootRouteChildren = { const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute, IndexRoute: IndexRoute,
AboutRoute: AboutRoute, AboutRoute: AboutRoute,
ApidocsRoute: ApidocsRoute,
AppDownRoute: AppDownRoute, AppDownRoute: AppDownRoute,
ForbiddenRoute: ForbiddenRoute, ForbiddenRoute: ForbiddenRoute,
authLoginRoute: authLoginRoute, authLoginRoute: authLoginRoute,
@@ -473,6 +514,7 @@ const rootRouteChildren: RootRouteChildren = {
AdminSettingsRoute: AdminSettingsRoute, AdminSettingsRoute: AdminSettingsRoute,
AdminUsersRoute: AdminUsersRoute, AdminUsersRoute: AdminUsersRoute,
DocsSplatRoute: DocsSplatRoute, DocsSplatRoute: DocsSplatRoute,
DocsDatamartRoute: DocsDatamartRoute,
DocsIndexRoute: DocsIndexRoute, DocsIndexRoute: DocsIndexRoute,
authUserProfileRoute: authUserProfileRoute, authUserProfileRoute: authUserProfileRoute,
authUserResetpasswordRoute: authUserResetpasswordRoute, authUserResetpasswordRoute: authUserResetpasswordRoute,

View File

@@ -19,8 +19,10 @@ const RootLayout = () => {
<div className="relative min-h-[calc(100svh-var(--header-height))]"> <div className="relative min-h-[calc(100svh-var(--header-height))]">
<AppSidebar /> <AppSidebar />
<main className="w-full p-4"> <main className="w-full">
<div className="mx-auto w-full max-w-7xl"> <div className="mx-auto w-full flex justify-center">
{" "}
{/* className="mx-auto w-full max-w-7xl" use this for dashboards and stuff*/}
<Outlet /> <Outlet />
</div> </div>
</main> </main>
@@ -31,7 +33,7 @@ const RootLayout = () => {
</SidebarProvider> </SidebarProvider>
</ThemeProvider> </ThemeProvider>
{session && session.user.role === "systemAdmin" && ( {session && session.user.role === "systemAdmin" && (
<TanStackRouterDevtools /> <TanStackRouterDevtools position="bottom-right" />
)} )}
</div> </div>
); );

View File

@@ -248,7 +248,7 @@ function RouteComponent() {
}; };
//console.log(logs); //console.log(logs);
return ( return (
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1 max-w-7xl">
<div className="flex gap-1 justify-end"> <div className="flex gap-1 justify-end">
<Button onClick={triggerBuild}>Trigger Build</Button> <Button onClick={triggerBuild}>Trigger Build</Button>
<Button onClick={() => clearRoom()}>Clear Logs</Button> <Button onClick={() => clearRoom()}>Clear Logs</Button>

View File

@@ -0,0 +1,15 @@
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/apidocs")({
component: RouteComponent,
});
function RouteComponent() {
return (
<iframe
src="/lst/api/docs"
className="h-[calc(100vh-64px)] w-full border-0"
title="LST API Docs"
/>
);
}

View File

@@ -1,18 +1,18 @@
import { useSuspenseQuery } from "@tanstack/react-query"; import { useSuspenseQuery } from "@tanstack/react-query";
import { createFileRoute, redirect } from "@tanstack/react-router"; import { createFileRoute, redirect } from "@tanstack/react-router";
import { createColumnHelper } from "@tanstack/react-table"; import { createColumnHelper } from "@tanstack/react-table";
import { Trash } from "lucide-react";
import { Suspense, useState } from "react"; import { Suspense, useState } from "react";
import { toast } from "sonner";
import { Button } from "../../../components/ui/button";
import { Spinner } from "../../../components/ui/spinner";
import { api } from "../../../lib/apiHelper";
import { authClient } from "../../../lib/auth-client"; import { authClient } from "../../../lib/auth-client";
import { getArticleLinks } from "../../../lib/queries/getArticleLinks"; import { getArticleLinks } from "../../../lib/queries/getArticleLinks";
import LstTable from "../../../lib/tableStuff/LstTable"; import LstTable from "../../../lib/tableStuff/LstTable";
import SearchableHeader from "../../../lib/tableStuff/SearchableHeader"; import SearchableHeader from "../../../lib/tableStuff/SearchableHeader";
import SkellyTable from "../../../lib/tableStuff/SkellyTable"; import SkellyTable from "../../../lib/tableStuff/SkellyTable";
import NewArticleLink from "./-components/NewArticleLink"; import NewArticleLink from "./-components/NewArticleLink";
import { api } from "../../../lib/apiHelper";
import { toast } from "sonner";
import { Button } from "../../../components/ui/button";
import { Spinner } from "../../../components/ui/spinner";
import { Trash } from "lucide-react";
export const Route = createFileRoute("/transportation/opendock/")({ export const Route = createFileRoute("/transportation/opendock/")({
beforeLoad: async ({ location }) => { beforeLoad: async ({ location }) => {
@@ -167,7 +167,7 @@ const ArticleLinkTable = () => {
}), }),
]; ];
return ( return (
<div> <div className="">
<div> <div>
<div className="flex justify-end m-2"> <div className="flex justify-end m-2">
<Suspense <Suspense

90
package-lock.json generated
View File

@@ -10,7 +10,7 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@dotenvx/dotenvx": "^1.57.0", "@dotenvx/dotenvx": "^1.57.0",
"@scalar/express-api-reference": "^0.9.4", "@scalar/express-api-reference": "^0.9.20",
"@socket.io/admin-ui": "^0.5.1", "@socket.io/admin-ui": "^0.5.1",
"archiver": "^7.0.1", "archiver": "^7.0.1",
"axios": "^1.13.6", "axios": "^1.13.6",
@@ -44,7 +44,8 @@
"socket.io": "^4.8.3", "socket.io": "^4.8.3",
"socket.io-client": "^4.8.3", "socket.io-client": "^4.8.3",
"xlsx": "^0.18.5", "xlsx": "^0.18.5",
"zod": "^4.3.6" "zod": "^4.3.6",
"zod-openapi": "^6.0.0"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "2.4.8", "@biomejs/biome": "2.4.8",
@@ -2424,46 +2425,61 @@
"devOptional": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@scalar/core": { "node_modules/@scalar/client-side-rendering": {
"version": "0.4.4", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/@scalar/core/-/core-0.4.4.tgz", "resolved": "https://registry.npmjs.org/@scalar/client-side-rendering/-/client-side-rendering-0.1.13.tgz",
"integrity": "sha512-eXIG0opyQn45FzpTp0dAWFP1Vjcx+helgUAsa0uN36tyUR7DSmz2kRwHqqedzvPWryeRCKPz7/vwzKpETZp5lg==", "integrity": "sha512-p8V4HgEWjaCpqsnhclg1pTfjE9JA0AWRr0ocBQHexoHo+pqnSs1d83Mv9rjH7R0FZJrlCSandZZeY3DMX2gYXQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@scalar/types": "0.7.4" "@scalar/schemas": "0.3.3",
"@scalar/types": "0.12.3",
"@scalar/validation": "0.6.0"
}, },
"engines": { "engines": {
"node": ">=22" "node": ">=22"
} }
}, },
"node_modules/@scalar/express-api-reference": { "node_modules/@scalar/express-api-reference": {
"version": "0.9.4", "version": "0.9.20",
"resolved": "https://registry.npmjs.org/@scalar/express-api-reference/-/express-api-reference-0.9.4.tgz", "resolved": "https://registry.npmjs.org/@scalar/express-api-reference/-/express-api-reference-0.9.20.tgz",
"integrity": "sha512-KXG+VaMArCGcWhzDV2rfkHd+UF1HYevIFbO6cqFpd+az7QHvVT99BU8Yh60T1dmtCp504s0Pl/vcTyJ91fK1Ug==", "integrity": "sha512-J0P6qpYoL0kXvs/A/vuAwCqQFCYnErbXSB5/3lEGTbARuK0oGyMvl55dQyW5Ucq3CX1npuRejlTX6bxEprSvJA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@scalar/core": "0.4.4" "@scalar/client-side-rendering": "0.1.13"
}, },
"engines": { "engines": {
"node": ">=22" "node": ">=22"
} }
}, },
"node_modules/@scalar/helpers": { "node_modules/@scalar/helpers": {
"version": "0.4.2", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/@scalar/helpers/-/helpers-0.4.2.tgz", "resolved": "https://registry.npmjs.org/@scalar/helpers/-/helpers-0.8.1.tgz",
"integrity": "sha512-IrgrGVSahCfYDNWITazz4Q1BOndp5eEzlimRkfxiYn++KqeWyLfALyym1omqcdKGYtiSx1KIbKaUJL9vkjaN7w==", "integrity": "sha512-yuiuBCadP5bjAnIv23QvifVN/NaMi9xBF6b8Wdk4QOzwzLPJmp699MAdf33J0A5i2qKcvnu32iz/VkEJmQRe5g==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=22" "node": ">=22"
} }
}, },
"node_modules/@scalar/types": { "node_modules/@scalar/schemas": {
"version": "0.7.4", "version": "0.3.3",
"resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.7.4.tgz", "resolved": "https://registry.npmjs.org/@scalar/schemas/-/schemas-0.3.3.tgz",
"integrity": "sha512-1o9uf42lZ9YD0XP/HMWrwXN0unx6vFTTgtduA1F28Yloea9Pfv9N2R/t0wO91iSIzw4+NubEFolunbdb2QcgHA==", "integrity": "sha512-qDcgFu6ta5Z90L9D2P6DFKzYesU+FW5+m55SGmdI4iRMRCwj5umHpec2Y2W/SJcCF6bbUZawMxuOH2Ja6rUNpQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@scalar/helpers": "0.4.2", "@scalar/helpers": "0.8.1",
"@scalar/validation": "0.6.0"
},
"engines": {
"node": ">=22"
}
},
"node_modules/@scalar/types": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.12.3.tgz",
"integrity": "sha512-7zaXafbgTFmsJ/9AwYeExUWzXoZNyKOL0SEVAUWRaOndcjxpFCtwzuPrc1elMEWdHopWbY1Qe5pWKbE2aqG2HA==",
"license": "MIT",
"dependencies": {
"@scalar/helpers": "0.8.1",
"nanoid": "^5.1.6", "nanoid": "^5.1.6",
"type-fest": "^5.3.1", "type-fest": "^5.3.1",
"zod": "^4.3.5" "zod": "^4.3.5"
@@ -2472,6 +2488,15 @@
"node": ">=22" "node": ">=22"
} }
}, },
"node_modules/@scalar/validation": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@scalar/validation/-/validation-0.6.0.tgz",
"integrity": "sha512-tpmmG+/xRE2Kn9RpflU3AIyZv08v10+E1ZrJCx7z6+/91zHVxy0M73kC1LT4/8PbYNt85ywyC8+n+D99JdMcGA==",
"license": "MIT",
"engines": {
"node": ">=20"
}
},
"node_modules/@serialport/binding-mock": { "node_modules/@serialport/binding-mock": {
"version": "10.2.2", "version": "10.2.2",
"resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-10.2.2.tgz", "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-10.2.2.tgz",
@@ -10566,9 +10591,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "5.1.7", "version": "5.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.7.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz",
"integrity": "sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ==", "integrity": "sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -13252,9 +13277,9 @@
} }
}, },
"node_modules/type-fest": { "node_modules/type-fest": {
"version": "5.5.0", "version": "5.7.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.7.0.tgz",
"integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==", "integrity": "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==",
"license": "(MIT OR CC0-1.0)", "license": "(MIT OR CC0-1.0)",
"dependencies": { "dependencies": {
"tagged-tag": "^1.0.0" "tagged-tag": "^1.0.0"
@@ -13937,6 +13962,21 @@
"funding": { "funding": {
"url": "https://github.com/sponsors/colinhacks" "url": "https://github.com/sponsors/colinhacks"
} }
},
"node_modules/zod-openapi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/zod-openapi/-/zod-openapi-6.0.0.tgz",
"integrity": "sha512-mS4eRJ4DGCPrg6elRbJqc/3nLe4EPVi8KiHRKZ7dcTR5m5orPy8EfoWmceAyGZAq71MAWuyrTTOag7W5N61ZPQ==",
"license": "MIT",
"engines": {
"node": ">=22.14.0"
},
"funding": {
"url": "https://github.com/samchungy/zod-openapi?sponsor=1"
},
"peerDependencies": {
"zod": "^4.0.0"
}
} }
} }
} }

View File

@@ -68,7 +68,7 @@
}, },
"dependencies": { "dependencies": {
"@dotenvx/dotenvx": "^1.57.0", "@dotenvx/dotenvx": "^1.57.0",
"@scalar/express-api-reference": "^0.9.4", "@scalar/express-api-reference": "^0.9.20",
"@socket.io/admin-ui": "^0.5.1", "@socket.io/admin-ui": "^0.5.1",
"archiver": "^7.0.1", "archiver": "^7.0.1",
"axios": "^1.13.6", "axios": "^1.13.6",
@@ -102,7 +102,8 @@
"socket.io": "^4.8.3", "socket.io": "^4.8.3",
"socket.io-client": "^4.8.3", "socket.io-client": "^4.8.3",
"xlsx": "^0.18.5", "xlsx": "^0.18.5",
"zod": "^4.3.6" "zod": "^4.3.6",
"zod-openapi": "^6.0.0"
}, },
"config": { "config": {
"commitizen": { "commitizen": {