diff --git a/backend/configs/scaler.config.ts b/backend/configs/scaler.config.ts
index 03bfe88..bba0474 100644
--- a/backend/configs/scaler.config.ts
+++ b/backend/configs/scaler.config.ts
@@ -9,8 +9,6 @@ import os from "node:os";
import { apiReference } from "@scalar/express-api-reference";
// const port = 3000;
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 { openDockApt } from "../scaler/opendockGetRelease.spec.js";
import { prodRestartSpec } from "../scaler/prodSqlRestart.spec.js";
@@ -125,8 +123,6 @@ export const setupApiDocsRoutes = (baseUrl: string, app: Express) => {
...prodLoginSpec,
...prodRegisterSpec,
//...mergedDatamart,
- ...cronerActiveJobs,
- ...cronerStatusChange,
...openDockApt,
// Add more specs here as you build features
diff --git a/backend/scaler/cronerActiveJobs.spec.ts b/backend/scaler/cronerActiveJobs.spec.ts
deleted file mode 100644
index cc8b7c1..0000000
--- a/backend/scaler/cronerActiveJobs.spec.ts
+++ /dev/null
@@ -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",
- },
- },
- },
- },
- },
- },
- },
- },
- },
-};
diff --git a/backend/scaler/cronerStatusChange.spec.ts b/backend/scaler/cronerStatusChange.spec.ts
deleted file mode 100644
index 1706ac2..0000000
--- a/backend/scaler/cronerStatusChange.spec.ts
+++ /dev/null
@@ -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",
- },
- },
- },
- },
- },
- },
- },
- },
- },
-};
diff --git a/frontend/src/components/Sidebar/sidebar.tsx b/frontend/src/components/Sidebar/sidebar.tsx
index f309187..5570097 100644
--- a/frontend/src/components/Sidebar/sidebar.tsx
+++ b/frontend/src/components/Sidebar/sidebar.tsx
@@ -1,10 +1,14 @@
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
+import { Link } from "@tanstack/react-router";
+import { LaptopMinimal } from "lucide-react";
import {
Sidebar,
SidebarContent,
- SidebarHeader,
+ SidebarFooter,
SidebarMenu,
+ SidebarMenuButton,
SidebarMenuItem,
+ useSidebar,
} from "@/components/ui/sidebar";
import { useSession } from "@/lib/auth-client";
import { getSettings } from "../../lib/queries/getSettings";
@@ -23,6 +27,7 @@ export function AppSidebar() {
openDock: ["read"],
}),
);
+ const { setOpen } = useSidebar();
// const { data: canReadWarehouse = false } = useQuery(
// permissionQuery({
@@ -36,7 +41,7 @@ export function AppSidebar() {
collapsible="offcanvas"
className="top-(--header-height) h-[calc(100svh-var(--header-height))]!"
>
-
+
@@ -64,7 +69,24 @@ export function AppSidebar() {
-
+
+ {session &&
+ (session.user.role === "admin" ||
+ session.user.role === "systemAdmin" ||
+ session.user.role === "manager") && (
+
+
+
+
+ setOpen(false)}>
+
+ Api docs
+
+
+
+
+
+ )}
);
}
diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts
index 175d0a6..84d39e7 100644
--- a/frontend/src/routeTree.gen.ts
+++ b/frontend/src/routeTree.gen.ts
@@ -11,9 +11,11 @@
import { Route as rootRouteImport } from './routes/__root'
import { Route as ForbiddenRouteImport } from './routes/forbidden'
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 IndexRouteImport } from './routes/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 AdminUsersRouteImport } from './routes/admin/users'
import { Route as AdminSettingsRouteImport } from './routes/admin/settings'
@@ -41,6 +43,11 @@ const AppDownRoute = AppDownRouteImport.update({
path: '/app-down',
getParentRoute: () => rootRouteImport,
} as any)
+const ApidocsRoute = ApidocsRouteImport.update({
+ id: '/apidocs',
+ path: '/apidocs',
+ getParentRoute: () => rootRouteImport,
+} as any)
const AboutRoute = AboutRouteImport.update({
id: '/about',
path: '/about',
@@ -56,6 +63,11 @@ const DocsIndexRoute = DocsIndexRouteImport.update({
path: '/docs/',
getParentRoute: () => rootRouteImport,
} as any)
+const DocsDatamartRoute = DocsDatamartRouteImport.update({
+ id: '/docs/datamart',
+ path: '/docs/datamart',
+ getParentRoute: () => rootRouteImport,
+} as any)
const DocsSplatRoute = DocsSplatRouteImport.update({
id: '/docs/$',
path: '/docs/$',
@@ -145,6 +157,7 @@ const WarehouseDockdoorscanningScansDockScansRoute =
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/about': typeof AboutRoute
+ '/apidocs': typeof ApidocsRoute
'/app-down': typeof AppDownRoute
'/forbidden': typeof ForbiddenRoute
'/login': typeof authLoginRoute
@@ -155,6 +168,7 @@ export interface FileRoutesByFullPath {
'/admin/settings': typeof AdminSettingsRoute
'/admin/users': typeof AdminUsersRoute
'/docs/$': typeof DocsSplatRoute
+ '/docs/datamart': typeof DocsDatamartRoute
'/docs/': typeof DocsIndexRoute
'/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute
@@ -168,6 +182,7 @@ export interface FileRoutesByFullPath {
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/about': typeof AboutRoute
+ '/apidocs': typeof ApidocsRoute
'/app-down': typeof AppDownRoute
'/forbidden': typeof ForbiddenRoute
'/login': typeof authLoginRoute
@@ -178,6 +193,7 @@ export interface FileRoutesByTo {
'/admin/settings': typeof AdminSettingsRoute
'/admin/users': typeof AdminUsersRoute
'/docs/$': typeof DocsSplatRoute
+ '/docs/datamart': typeof DocsDatamartRoute
'/docs': typeof DocsIndexRoute
'/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute
@@ -192,6 +208,7 @@ export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/about': typeof AboutRoute
+ '/apidocs': typeof ApidocsRoute
'/app-down': typeof AppDownRoute
'/forbidden': typeof ForbiddenRoute
'/(auth)/login': typeof authLoginRoute
@@ -202,6 +219,7 @@ export interface FileRoutesById {
'/admin/settings': typeof AdminSettingsRoute
'/admin/users': typeof AdminUsersRoute
'/docs/$': typeof DocsSplatRoute
+ '/docs/datamart': typeof DocsDatamartRoute
'/docs/': typeof DocsIndexRoute
'/(auth)/user/profile': typeof authUserProfileRoute
'/(auth)/user/resetpassword': typeof authUserResetpasswordRoute
@@ -217,6 +235,7 @@ export interface FileRouteTypes {
fullPaths:
| '/'
| '/about'
+ | '/apidocs'
| '/app-down'
| '/forbidden'
| '/login'
@@ -227,6 +246,7 @@ export interface FileRouteTypes {
| '/admin/settings'
| '/admin/users'
| '/docs/$'
+ | '/docs/datamart'
| '/docs/'
| '/user/profile'
| '/user/resetpassword'
@@ -240,6 +260,7 @@ export interface FileRouteTypes {
to:
| '/'
| '/about'
+ | '/apidocs'
| '/app-down'
| '/forbidden'
| '/login'
@@ -250,6 +271,7 @@ export interface FileRouteTypes {
| '/admin/settings'
| '/admin/users'
| '/docs/$'
+ | '/docs/datamart'
| '/docs'
| '/user/profile'
| '/user/resetpassword'
@@ -263,6 +285,7 @@ export interface FileRouteTypes {
| '__root__'
| '/'
| '/about'
+ | '/apidocs'
| '/app-down'
| '/forbidden'
| '/(auth)/login'
@@ -273,6 +296,7 @@ export interface FileRouteTypes {
| '/admin/settings'
| '/admin/users'
| '/docs/$'
+ | '/docs/datamart'
| '/docs/'
| '/(auth)/user/profile'
| '/(auth)/user/resetpassword'
@@ -287,6 +311,7 @@ export interface FileRouteTypes {
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
AboutRoute: typeof AboutRoute
+ ApidocsRoute: typeof ApidocsRoute
AppDownRoute: typeof AppDownRoute
ForbiddenRoute: typeof ForbiddenRoute
authLoginRoute: typeof authLoginRoute
@@ -297,6 +322,7 @@ export interface RootRouteChildren {
AdminSettingsRoute: typeof AdminSettingsRoute
AdminUsersRoute: typeof AdminUsersRoute
DocsSplatRoute: typeof DocsSplatRoute
+ DocsDatamartRoute: typeof DocsDatamartRoute
DocsIndexRoute: typeof DocsIndexRoute
authUserProfileRoute: typeof authUserProfileRoute
authUserResetpasswordRoute: typeof authUserResetpasswordRoute
@@ -324,6 +350,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppDownRouteImport
parentRoute: typeof rootRouteImport
}
+ '/apidocs': {
+ id: '/apidocs'
+ path: '/apidocs'
+ fullPath: '/apidocs'
+ preLoaderRoute: typeof ApidocsRouteImport
+ parentRoute: typeof rootRouteImport
+ }
'/about': {
id: '/about'
path: '/about'
@@ -345,6 +378,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DocsIndexRouteImport
parentRoute: typeof rootRouteImport
}
+ '/docs/datamart': {
+ id: '/docs/datamart'
+ path: '/docs/datamart'
+ fullPath: '/docs/datamart'
+ preLoaderRoute: typeof DocsDatamartRouteImport
+ parentRoute: typeof rootRouteImport
+ }
'/docs/$': {
id: '/docs/$'
path: '/docs/$'
@@ -463,6 +503,7 @@ declare module '@tanstack/react-router' {
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
AboutRoute: AboutRoute,
+ ApidocsRoute: ApidocsRoute,
AppDownRoute: AppDownRoute,
ForbiddenRoute: ForbiddenRoute,
authLoginRoute: authLoginRoute,
@@ -473,6 +514,7 @@ const rootRouteChildren: RootRouteChildren = {
AdminSettingsRoute: AdminSettingsRoute,
AdminUsersRoute: AdminUsersRoute,
DocsSplatRoute: DocsSplatRoute,
+ DocsDatamartRoute: DocsDatamartRoute,
DocsIndexRoute: DocsIndexRoute,
authUserProfileRoute: authUserProfileRoute,
authUserResetpasswordRoute: authUserResetpasswordRoute,
diff --git a/frontend/src/routes/__root.tsx b/frontend/src/routes/__root.tsx
index 03a956a..17b706f 100644
--- a/frontend/src/routes/__root.tsx
+++ b/frontend/src/routes/__root.tsx
@@ -19,8 +19,10 @@ const RootLayout = () => {
-
-
+
+
+ {" "}
+ {/* className="mx-auto w-full max-w-7xl" use this for dashboards and stuff*/}
@@ -31,7 +33,7 @@ const RootLayout = () => {
{session && session.user.role === "systemAdmin" && (
-
+
)}
);
diff --git a/frontend/src/routes/admin/servers.tsx b/frontend/src/routes/admin/servers.tsx
index 456ad1f..1950657 100644
--- a/frontend/src/routes/admin/servers.tsx
+++ b/frontend/src/routes/admin/servers.tsx
@@ -248,7 +248,7 @@ function RouteComponent() {
};
//console.log(logs);
return (
-
+
diff --git a/frontend/src/routes/apidocs.tsx b/frontend/src/routes/apidocs.tsx
new file mode 100644
index 0000000..a4f4cd3
--- /dev/null
+++ b/frontend/src/routes/apidocs.tsx
@@ -0,0 +1,15 @@
+import { createFileRoute } from "@tanstack/react-router";
+
+export const Route = createFileRoute("/apidocs")({
+ component: RouteComponent,
+});
+
+function RouteComponent() {
+ return (
+
+ );
+}
diff --git a/frontend/src/routes/transportation/opendock/index.tsx b/frontend/src/routes/transportation/opendock/index.tsx
index e8dee09..461e670 100644
--- a/frontend/src/routes/transportation/opendock/index.tsx
+++ b/frontend/src/routes/transportation/opendock/index.tsx
@@ -1,18 +1,18 @@
import { useSuspenseQuery } from "@tanstack/react-query";
import { createFileRoute, redirect } from "@tanstack/react-router";
import { createColumnHelper } from "@tanstack/react-table";
+import { Trash } from "lucide-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 { getArticleLinks } from "../../../lib/queries/getArticleLinks";
import LstTable from "../../../lib/tableStuff/LstTable";
import SearchableHeader from "../../../lib/tableStuff/SearchableHeader";
import SkellyTable from "../../../lib/tableStuff/SkellyTable";
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/")({
beforeLoad: async ({ location }) => {
@@ -97,77 +97,77 @@ const ArticleLinkTable = () => {
cell: (i) => i.getValue(),
}),
columnHelper.accessor("deleteUser", {
- header: ({ column }) => (
-
- ),
- filterFn: "includesString",
- cell: (i) => {
- // biome-ignore lint: just removing the lint for now to get this going will maybe fix later
- const [activeToggle, setActiveToggle] = useState(false);
-
- const onTrigger = async () => {
- setActiveToggle(true);
-
- try {
- const res = await api.delete(
- `/opendock/articleCheck/${i.row.original.id}`,
-
- {
- withCredentials: true,
- timeout: 5000,
- validateStatus: () => true,
- },
- );
-
- if (res.data.success) {
- toast.success(`AV: ${i.row.original.av} was deleted.`);
- refetch();
- setActiveToggle(false);
- }
-
- if (!res.data.success) {
- toast.error(
- `AV: ${i.row.original.av} encountered an error when trying to delete: ${res.data.message}`,
- );
- refetch();
- setActiveToggle(false);
- }
- } catch (error) {
- setActiveToggle(false);
- console.error(error);
- }
- };
-
- return (
-
-
-
-
-
+ header: ({ column }) => (
+
+ ),
+ filterFn: "includesString",
+ cell: (i) => {
+ // biome-ignore lint: just removing the lint for now to get this going will maybe fix later
+ const [activeToggle, setActiveToggle] = useState(false);
+
+ const onTrigger = async () => {
+ setActiveToggle(true);
+
+ try {
+ const res = await api.delete(
+ `/opendock/articleCheck/${i.row.original.id}`,
+
+ {
+ withCredentials: true,
+ timeout: 5000,
+ validateStatus: () => true,
+ },
);
- },
- }),
+
+ if (res.data.success) {
+ toast.success(`AV: ${i.row.original.av} was deleted.`);
+ refetch();
+ setActiveToggle(false);
+ }
+
+ if (!res.data.success) {
+ toast.error(
+ `AV: ${i.row.original.av} encountered an error when trying to delete: ${res.data.message}`,
+ );
+ refetch();
+ setActiveToggle(false);
+ }
+ } catch (error) {
+ setActiveToggle(false);
+ console.error(error);
+ }
+ };
+
+ return (
+
+
+
+
+
+ );
+ },
+ }),
];
return (
-
+
=22"
}
},
"node_modules/@scalar/express-api-reference": {
- "version": "0.9.4",
- "resolved": "https://registry.npmjs.org/@scalar/express-api-reference/-/express-api-reference-0.9.4.tgz",
- "integrity": "sha512-KXG+VaMArCGcWhzDV2rfkHd+UF1HYevIFbO6cqFpd+az7QHvVT99BU8Yh60T1dmtCp504s0Pl/vcTyJ91fK1Ug==",
+ "version": "0.9.20",
+ "resolved": "https://registry.npmjs.org/@scalar/express-api-reference/-/express-api-reference-0.9.20.tgz",
+ "integrity": "sha512-J0P6qpYoL0kXvs/A/vuAwCqQFCYnErbXSB5/3lEGTbARuK0oGyMvl55dQyW5Ucq3CX1npuRejlTX6bxEprSvJA==",
"license": "MIT",
"dependencies": {
- "@scalar/core": "0.4.4"
+ "@scalar/client-side-rendering": "0.1.13"
},
"engines": {
"node": ">=22"
}
},
"node_modules/@scalar/helpers": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/@scalar/helpers/-/helpers-0.4.2.tgz",
- "integrity": "sha512-IrgrGVSahCfYDNWITazz4Q1BOndp5eEzlimRkfxiYn++KqeWyLfALyym1omqcdKGYtiSx1KIbKaUJL9vkjaN7w==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@scalar/helpers/-/helpers-0.8.1.tgz",
+ "integrity": "sha512-yuiuBCadP5bjAnIv23QvifVN/NaMi9xBF6b8Wdk4QOzwzLPJmp699MAdf33J0A5i2qKcvnu32iz/VkEJmQRe5g==",
"license": "MIT",
"engines": {
"node": ">=22"
}
},
- "node_modules/@scalar/types": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.7.4.tgz",
- "integrity": "sha512-1o9uf42lZ9YD0XP/HMWrwXN0unx6vFTTgtduA1F28Yloea9Pfv9N2R/t0wO91iSIzw4+NubEFolunbdb2QcgHA==",
+ "node_modules/@scalar/schemas": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@scalar/schemas/-/schemas-0.3.3.tgz",
+ "integrity": "sha512-qDcgFu6ta5Z90L9D2P6DFKzYesU+FW5+m55SGmdI4iRMRCwj5umHpec2Y2W/SJcCF6bbUZawMxuOH2Ja6rUNpQ==",
"license": "MIT",
"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",
"type-fest": "^5.3.1",
"zod": "^4.3.5"
@@ -2472,6 +2488,15 @@
"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": {
"version": "10.2.2",
"resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-10.2.2.tgz",
@@ -10566,9 +10591,9 @@
"license": "ISC"
},
"node_modules/nanoid": {
- "version": "5.1.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.7.tgz",
- "integrity": "sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ==",
+ "version": "5.1.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz",
+ "integrity": "sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==",
"funding": [
{
"type": "github",
@@ -13252,9 +13277,9 @@
}
},
"node_modules/type-fest": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz",
- "integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.7.0.tgz",
+ "integrity": "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==",
"license": "(MIT OR CC0-1.0)",
"dependencies": {
"tagged-tag": "^1.0.0"
@@ -13937,6 +13962,21 @@
"funding": {
"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"
+ }
}
}
}
diff --git a/package.json b/package.json
index 44de43d..154aa65 100644
--- a/package.json
+++ b/package.json
@@ -68,7 +68,7 @@
},
"dependencies": {
"@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",
"archiver": "^7.0.1",
"axios": "^1.13.6",
@@ -102,7 +102,8 @@
"socket.io": "^4.8.3",
"socket.io-client": "^4.8.3",
"xlsx": "^0.18.5",
- "zod": "^4.3.6"
+ "zod": "^4.3.6",
+ "zod-openapi": "^6.0.0"
},
"config": {
"commitizen": {