From a0a05615b1fdeb2c1f31c829cece95359c3cdfb4 Mon Sep 17 00:00:00 2001 From: shafi54 <108669266+shafi-aviz@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:35:39 +0530 Subject: [PATCH] enh --- apps/backend/index.ts | 5 +- apps/backend/package.json | 5 +- apps/backend/src/lib/jwt-utils.ts | 56 +++++++++++++++++ apps/backend/src/lib/upload-handler.ts | 8 --- .../backend/src/middleware/auth.middleware.ts | 4 +- apps/backend/src/middleware/auth.ts | 11 ++-- apps/backend/src/middleware/staff-auth.ts | 8 +-- .../trpc/apis/admin-apis/apis/staff-user.ts | 7 +-- .../src/trpc/apis/user-apis/apis/auth.ts | 18 ++---- .../src/trpc/apis/user-apis/apis/user.ts | 12 +--- bun.lock | 63 +------------------ 11 files changed, 87 insertions(+), 110 deletions(-) create mode 100644 apps/backend/src/lib/jwt-utils.ts delete mode 100755 apps/backend/src/lib/upload-handler.ts diff --git a/apps/backend/index.ts b/apps/backend/index.ts index b450036..ac50116 100755 --- a/apps/backend/index.ts +++ b/apps/backend/index.ts @@ -2,7 +2,6 @@ import 'dotenv/config'; import express, { NextFunction, Request, Response } from "express"; import cors from "cors"; // import bodyParser from "body-parser"; -import multer from "multer"; import path from "path"; import fs from "fs"; import { db } from '@/src/db/db_index'; @@ -13,11 +12,11 @@ import initFunc from '@/src/lib/init'; import { createExpressMiddleware } from '@trpc/server/adapters/express'; import { appRouter } from '@/src/trpc/router'; import { TRPCError } from '@trpc/server'; -import jwt from 'jsonwebtoken' import signedUrlCache from '@/src/lib/signed-url-cache'; import { seed } from '@/src/db/seed'; import '@/src/jobs/jobs-index'; import { startAutomatedJobs } from '@/src/lib/automatedJobs'; +import { verifyToken } from '@/src/lib/jwt-utils'; seed() initFunc() @@ -78,7 +77,7 @@ app.use('/api/trpc', createExpressMiddleware({ if (authHeader?.startsWith('Bearer ')) { const token = authHeader.substring(7); try { - const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key') as any; + const decoded = (await verifyToken(token)) as any; // Check if this is a staff token (has staffId) if (decoded.staffId) { diff --git a/apps/backend/package.json b/apps/backend/package.json index 7d2e490..d240080 100755 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -26,8 +26,6 @@ "@turf/turf": "^7.2.0", "@types/bcryptjs": "^2.4.6", "@types/cors": "^2.8.19", - "@types/jsonwebtoken": "^9.0.10", - "@types/multer": "^2.0.0", "axios": "^1.11.0", "bcryptjs": "^3.0.2", "bullmq": "^5.63.0", @@ -38,8 +36,7 @@ "expo-server-sdk": "^4.0.0", "express": "^5.1.0", "fuse.js": "^7.1.0", - "jsonwebtoken": "^9.0.2", - "multer": "^2.0.2", + "jose": "^5.10.0", "node-cron": "^4.2.1", "pg": "^8.16.3", "razorpay": "^2.9.6", diff --git a/apps/backend/src/lib/jwt-utils.ts b/apps/backend/src/lib/jwt-utils.ts new file mode 100644 index 0000000..739c5ff --- /dev/null +++ b/apps/backend/src/lib/jwt-utils.ts @@ -0,0 +1,56 @@ +import { SignJWT, jwtVerify, errors } from 'jose'; +import { jwtSecret } from './env-exporter'; + +// Convert string secret to Uint8Array +const getSecret = () => { + if (!jwtSecret) { + throw new Error('JWT secret not configured'); + } + return new TextEncoder().encode(jwtSecret); +}; + +/** + * Sign a JWT token + * Compatible with tokens signed by jsonwebtoken library + */ +export const signToken = async ( + payload: Record, + expiresIn: string = '7d' +): Promise => { + const secret = getSecret(); + + return new SignJWT(payload) + .setProtectedHeader({ alg: 'HS256' }) + .setIssuedAt() + .setExpirationTime(expiresIn) + .sign(secret); +}; + +/** + * Verify a JWT token + * Compatible with tokens signed by jsonwebtoken library + */ +export const verifyToken = async (token: string): Promise> => { + try { + const secret = getSecret(); + const { payload } = await jwtVerify(token, secret); + return payload; + } catch (error) { + if (error instanceof errors.JWTExpired) { + throw new Error('Token expired'); + } + if (error instanceof errors.JWTInvalid) { + throw new Error('Invalid token'); + } + throw error; + } +}; + +/** + * Check if an error is a JWT-related error + */ +export const isJWTError = (error: any): boolean => { + return error instanceof errors.JOSEError || + error?.message?.includes('token') || + error?.message?.includes('JWT'); +}; diff --git a/apps/backend/src/lib/upload-handler.ts b/apps/backend/src/lib/upload-handler.ts deleted file mode 100755 index 3caa4c2..0000000 --- a/apps/backend/src/lib/upload-handler.ts +++ /dev/null @@ -1,8 +0,0 @@ -import multerParent from 'multer'; -const uploadHandler = multerParent({ - limits: { - fileSize: 10 * 1024 * 1024, // 10 MB - } -}); - -export default uploadHandler \ No newline at end of file diff --git a/apps/backend/src/middleware/auth.middleware.ts b/apps/backend/src/middleware/auth.middleware.ts index 1e381bb..11495b2 100644 --- a/apps/backend/src/middleware/auth.middleware.ts +++ b/apps/backend/src/middleware/auth.middleware.ts @@ -1,9 +1,9 @@ import { Request, Response, NextFunction } from 'express'; -import jwt from 'jsonwebtoken'; import { db } from '@/src/db/db_index' import { staffUsers, userDetails } from '@/src/db/schema' import { eq } from 'drizzle-orm'; import { ApiError } from '@/src/lib/api-error' +import { verifyToken } from '@/src/lib/jwt-utils' interface AuthenticatedRequest extends Request { user?: { @@ -29,7 +29,7 @@ export const authenticateUser = async (req: AuthenticatedRequest, res: Response, const token = authHeader.substring(7); console.log(req.headers) - const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key') as any; + const decoded = (await verifyToken(token)) as any; // Check if this is a staff token (has staffId) if (decoded.staffId) { diff --git a/apps/backend/src/middleware/auth.ts b/apps/backend/src/middleware/auth.ts index a1a4f3a..dc3c01d 100755 --- a/apps/backend/src/middleware/auth.ts +++ b/apps/backend/src/middleware/auth.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from 'express'; -import jwt from 'jsonwebtoken'; import { ApiError } from '@/src/lib/api-error' +import { verifyToken, isJWTError } from '@/src/lib/jwt-utils' // Extend the Request interface to include user property declare global { @@ -11,7 +11,7 @@ declare global { } } -export const verifyToken = (req: Request, res: Response, next: NextFunction) => { +export const verifyTokenMiddleware = async (req: Request, res: Response, next: NextFunction) => { try { // Get token from Authorization header const authHeader = req.headers.authorization; @@ -28,7 +28,7 @@ export const verifyToken = (req: Request, res: Response, next: NextFunction) => } // Verify token - const decoded = jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key'); + const decoded = await verifyToken(token); // Add user info to request @@ -36,7 +36,7 @@ export const verifyToken = (req: Request, res: Response, next: NextFunction) => next(); } catch (error) { - if (error instanceof jwt.JsonWebTokenError) { + if (isJWTError(error)) { next(new ApiError('Invalid Auth Credentials', 401)); } else { next(error); @@ -44,6 +44,9 @@ export const verifyToken = (req: Request, res: Response, next: NextFunction) => } }; +// Keep old name for backward compatibility +export { verifyTokenMiddleware as verifyToken }; + export const requireRole = (roles: string[]) => { return (req: Request, res: Response, next: NextFunction) => { try { diff --git a/apps/backend/src/middleware/staff-auth.ts b/apps/backend/src/middleware/staff-auth.ts index 2215f5d..0ce2df3 100644 --- a/apps/backend/src/middleware/staff-auth.ts +++ b/apps/backend/src/middleware/staff-auth.ts @@ -1,9 +1,9 @@ import { Request, Response, NextFunction } from 'express'; -import jwt from 'jsonwebtoken'; import { db } from '@/src/db/db_index' import { staffUsers } from '@/src/db/schema' import { eq } from 'drizzle-orm'; import { ApiError } from '@/src/lib/api-error' +import { verifyToken } from '@/src/lib/jwt-utils' // Extend Request interface to include staffUser declare global { @@ -20,9 +20,9 @@ declare global { /** * Verify JWT token and extract payload */ -const verifyStaffToken = (token: string) => { +const verifyStaffToken = async (token: string) => { try { - return jwt.verify(token, process.env.JWT_SECRET || 'default-secret'); + return await verifyToken(token); } catch (error) { throw new ApiError('Access denied. Invalid auth credentials', 401); } @@ -47,7 +47,7 @@ export const authenticateStaff = async (req: Request, res: Response, next: NextF } // Verify token and extract payload - const decoded = verifyStaffToken(token) as any; + const decoded = (await verifyStaffToken(token)) as any; // Verify staffId exists in token if (!decoded.staffId) { diff --git a/apps/backend/src/trpc/apis/admin-apis/apis/staff-user.ts b/apps/backend/src/trpc/apis/admin-apis/apis/staff-user.ts index 0a62c21..428f36e 100644 --- a/apps/backend/src/trpc/apis/admin-apis/apis/staff-user.ts +++ b/apps/backend/src/trpc/apis/admin-apis/apis/staff-user.ts @@ -4,8 +4,8 @@ import { db } from '@/src/db/db_index' import { staffUsers, staffRoles, users, userDetails, orders } from '@/src/db/schema' import { eq, or, ilike, and, lt, desc } from 'drizzle-orm'; import bcrypt from 'bcryptjs'; -import jwt from 'jsonwebtoken'; import { ApiError } from '@/src/lib/api-error' +import { signToken } from '@/src/lib/jwt-utils' export const staffUserRouter = router({ login: publicProcedure @@ -33,10 +33,9 @@ export const staffUserRouter = router({ throw new ApiError('Invalid credentials', 401); } - const token = jwt.sign( + const token = await signToken( { staffId: staff.id, name: staff.name }, - process.env.JWT_SECRET || 'default-secret', - { expiresIn: '30d' } + '30d' ); return { diff --git a/apps/backend/src/trpc/apis/user-apis/apis/auth.ts b/apps/backend/src/trpc/apis/user-apis/apis/auth.ts index 6f97d79..986f8e8 100644 --- a/apps/backend/src/trpc/apis/user-apis/apis/auth.ts +++ b/apps/backend/src/trpc/apis/user-apis/apis/auth.ts @@ -1,7 +1,6 @@ import { router, publicProcedure, protectedProcedure } from '@/src/trpc/trpc-index'; import { z } from 'zod'; import bcrypt from 'bcryptjs'; -import jwt from 'jsonwebtoken'; import { eq } from 'drizzle-orm'; import { db } from '@/src/db/db_index'; import { @@ -14,8 +13,8 @@ import { generateSignedUrlFromS3Url, claimUploadUrl, scaffoldAssetUrl } from '@/ import { deleteS3Image } from '@/src/lib/delete-image'; import { ApiError } from '@/src/lib/api-error'; import catchAsync from '@/src/lib/catch-async'; -import { jwtSecret } from '@/src/lib/env-exporter'; import { sendOtp, verifyOtpUtil, getOtpCreds } from '@/src/lib/otp-utils'; +import { signToken } from '@/src/lib/jwt-utils'; interface LoginRequest { identifier: string; // email or mobile @@ -45,13 +44,8 @@ interface AuthResponse { }; } -const generateToken = (userId: number): string => { - const secret = jwtSecret; - if (!secret) { - throw new ApiError('JWT secret not configured', 500); - } - - return jwt.sign({ userId }, secret, { expiresIn: '7d' }); +const generateToken = async (userId: number): Promise => { + return signToken({ userId }); }; @@ -121,7 +115,7 @@ export const authRouter = router({ throw new ApiError('Invalid credentials', 401); } - const token = generateToken(foundUser.id); + const token = await generateToken(foundUser.id); const response: AuthResponse = { token, @@ -237,7 +231,7 @@ export const authRouter = router({ } } - const token = generateToken(newUser.id); + const token = await generateToken(newUser.id); // Get user details for profile image const [userDetail] = await db @@ -312,7 +306,7 @@ export const authRouter = router({ } // Generate JWT - const token = generateToken(user.id); + const token = await generateToken(user.id); return { success: true, diff --git a/apps/backend/src/trpc/apis/user-apis/apis/user.ts b/apps/backend/src/trpc/apis/user-apis/apis/user.ts index 730c1af..057697a 100644 --- a/apps/backend/src/trpc/apis/user-apis/apis/user.ts +++ b/apps/backend/src/trpc/apis/user-apis/apis/user.ts @@ -1,12 +1,11 @@ import { router, protectedProcedure, publicProcedure } from '@/src/trpc/trpc-index'; -import jwt from 'jsonwebtoken'; import { eq, and } from 'drizzle-orm'; import { z } from 'zod'; import { db } from '@/src/db/db_index'; import { users, userDetails, userCreds, notifCreds, unloggedUserTokens } from '@/src/db/schema'; import { ApiError } from '@/src/lib/api-error'; -import { jwtSecret } from '@/src/lib/env-exporter'; import { generateSignedUrlFromS3Url } from '@/src/lib/s3-client'; +import { signToken } from '@/src/lib/jwt-utils'; interface AuthResponse { token: string; @@ -23,13 +22,8 @@ interface AuthResponse { }; } -const generateToken = (userId: number): string => { - const secret = jwtSecret; - if (!secret) { - throw new ApiError('JWT secret not configured', 500); - } - - return jwt.sign({ userId }, secret, { expiresIn: '7d' }); +const generateToken = async (userId: number): Promise => { + return signToken({ userId }); }; export const userRouter = router({ diff --git a/bun.lock b/bun.lock index f94e3c2..6db5928 100644 --- a/bun.lock +++ b/bun.lock @@ -117,8 +117,6 @@ "@turf/turf": "^7.2.0", "@types/bcryptjs": "^2.4.6", "@types/cors": "^2.8.19", - "@types/jsonwebtoken": "^9.0.10", - "@types/multer": "^2.0.0", "axios": "^1.11.0", "bcryptjs": "^3.0.2", "bullmq": "^5.63.0", @@ -129,8 +127,7 @@ "expo-server-sdk": "^4.0.0", "express": "^5.1.0", "fuse.js": "^7.1.0", - "jsonwebtoken": "^9.0.2", - "multer": "^2.0.2", + "jose": "^5.10.0", "node-cron": "^4.2.1", "pg": "^8.16.3", "razorpay": "^2.9.6", @@ -1413,18 +1410,12 @@ "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], - "@types/jsonwebtoken": ["@types/jsonwebtoken@9.0.10", "", { "dependencies": { "@types/ms": "*", "@types/node": "*" } }, "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA=="], - "@types/kdbush": ["@types/kdbush@3.0.5", "", {}, "sha512-tdJz7jaWFu4nR+8b2B+CdPZ6811ighYylWsu2hpsivapzW058yP0KdfZuNY89IiRe5jbKvBGXN3LQdN2KPXVdQ=="], "@types/mapbox__point-geometry": ["@types/mapbox__point-geometry@0.1.4", "", {}, "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA=="], "@types/mapbox__vector-tile": ["@types/mapbox__vector-tile@1.3.4", "", { "dependencies": { "@types/geojson": "*", "@types/mapbox__point-geometry": "*", "@types/pbf": "*" } }, "sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg=="], - "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - - "@types/multer": ["@types/multer@2.1.0", "", { "dependencies": { "@types/express": "*" } }, "sha512-zYZb0+nJhOHtPpGDb3vqPjwpdeGlGC157VpkqNQL+UU2qwoacoQ7MpsAmUptI/0Oa127X32JzWDqQVEXp2RcIA=="], - "@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="], "@types/offscreencanvas": ["@types/offscreencanvas@2019.7.3", "", {}, "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A=="], @@ -1567,8 +1558,6 @@ "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - "append-field": ["append-field@1.0.0", "", {}, "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="], - "arc": ["arc@0.2.0", "", {}, "sha512-8NFOo126uYKQJyXNSLY/jSklgfLQL+XWAcPXGo876JwEQ8nSOPXWNI3TV2jLZMN8QEw8uksJ1ZwS4npjBca8MA=="], "arg": ["arg@4.1.0", "", {}, "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="], @@ -1681,14 +1670,10 @@ "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], - "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], - "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], "bullmq": ["bullmq@5.71.0", "", { "dependencies": { "cron-parser": "4.9.0", "ioredis": "5.9.3", "msgpackr": "1.11.5", "node-abort-controller": "3.1.1", "semver": "7.7.4", "tslib": "2.8.1", "uuid": "11.1.0" } }, "sha512-aeNWh4drsafSKnAJeiNH/nZP/5O8ZdtdMbnOPZmpjXj7NZUP5YC901U3bIH41iZValm7d1i3c34ojv7q31m30w=="], - "busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="], - "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], @@ -1763,8 +1748,6 @@ "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - "concat-stream": ["concat-stream@2.0.0", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.0.2", "typedarray": "^0.0.6" } }, "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A=="], - "concaveman": ["concaveman@1.2.1", "", { "dependencies": { "point-in-polygon": "^1.1.0", "rbush": "^3.0.1", "robust-predicates": "^2.0.4", "tinyqueue": "^2.0.3" } }, "sha512-PwZYKaM/ckQSa8peP5JpVr7IMJ4Nn/MHIaWUjP4be+KoZ7Botgs8seAZGpmaOM+UZXawcdYRao/px9ycrCihHw=="], "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="], @@ -1899,8 +1882,6 @@ "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], - "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], - "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], "electron-to-chromium": ["electron-to-chromium@1.5.313", "", {}, "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA=="], @@ -2365,6 +2346,8 @@ "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], + "jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="], + "js-stringify": ["js-stringify@1.0.2", "", {}, "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g=="], "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], @@ -2387,18 +2370,12 @@ "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], - "jsonwebtoken": ["jsonwebtoken@9.0.3", "", { "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g=="], - "jstransformer": ["jstransformer@1.0.0", "", { "dependencies": { "is-promise": "^2.0.0", "promise": "^7.0.1" } }, "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A=="], "jsts": ["jsts@2.7.1", "", {}, "sha512-x2wSZHEBK20CY+Wy+BPE7MrFQHW6sIsdaGUMEqmGAio+3gFzQaBYPwLRonUfQf9Ak8pBieqj9tUofX1+WtAEIg=="], "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="], - "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], - - "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], - "jwt-decode": ["jwt-decode@4.0.0", "", {}, "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA=="], "kdbush": ["kdbush@4.0.2", "", {}, "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="], @@ -2455,24 +2432,10 @@ "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="], - "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="], - "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="], - "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], - - "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="], - - "lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="], - - "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], - - "lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="], - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="], - "lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="], "log-symbols": ["log-symbols@2.2.0", "", { "dependencies": { "chalk": "^2.0.1" } }, "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg=="], @@ -2567,8 +2530,6 @@ "msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="], - "multer": ["multer@2.1.1", "", { "dependencies": { "append-field": "^1.0.0", "busboy": "^1.6.0", "concat-stream": "^2.0.0", "type-is": "^1.6.18" } }, "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A=="], - "murmurhash-js": ["murmurhash-js@1.0.0", "", {}, "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw=="], "mylas": ["mylas@2.1.14", "", {}, "sha512-BzQguy9W9NJgoVn2mRWzbFrFWWztGCcng2QI9+41frfk+Athwgx3qhqhvStz7ExeUUu7Kzw427sNzHpEZNINog=="], @@ -2885,8 +2846,6 @@ "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], - "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "redis": ["redis@5.11.0", "", { "dependencies": { "@redis/bloom": "5.11.0", "@redis/client": "5.11.0", "@redis/json": "5.11.0", "@redis/search": "5.11.0", "@redis/time-series": "5.11.0" } }, "sha512-YwXjATVDT+AuxcyfOwZn046aml9jMlQPvU1VXIlLDVAExe0u93aTfPYSeRgG4p9Q/Jlkj+LXJ1XEoFV+j2JKcQ=="], @@ -3051,8 +3010,6 @@ "stream-buffers": ["stream-buffers@2.2.0", "", {}, "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg=="], - "streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="], - "strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="], "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -3069,8 +3026,6 @@ "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], - "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - "strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="], "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -3217,8 +3172,6 @@ "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="], - "typedarray": ["typedarray@0.0.6", "", {}, "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="], - "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], "ua-parser-js": ["ua-parser-js@0.7.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg=="], @@ -3559,8 +3512,6 @@ "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "jsonwebtoken/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], - "jstransformer/is-promise": ["is-promise@2.2.2", "", {}, "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="], "jstransformer/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="], @@ -3583,8 +3534,6 @@ "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "multer/type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], - "node-gyp-build-optional-packages/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "npm-package-arg/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], @@ -3835,10 +3784,6 @@ "metro/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "multer/type-is/media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], - - "multer/type-is/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], "ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], @@ -3961,8 +3906,6 @@ "log-symbols/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], - "multer/type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "ora/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], "ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],