From 18f36107d8bc8714953d389350db5984588e2534 Mon Sep 17 00:00:00 2001 From: shafi54 <108669266+shafi-aviz@users.noreply.github.com> Date: Fri, 27 Mar 2026 01:59:26 +0530 Subject: [PATCH] enh --- AGENTS.md | 3 - apps/backend/index.ts | 128 +----- apps/backend/package.json | 6 +- .../admin-apis/apis/product.controller.ts | 236 ----------- apps/backend/src/app.ts | 126 ++++++ apps/backend/src/dbService.ts | 7 +- apps/backend/src/lib/env-exporter.ts | 113 +++-- apps/backend/src/lib/s3-client.ts | 28 +- apps/backend/src/lib/signed-url-cache-old.ts | 263 ++++++++++++ apps/backend/src/lib/signed-url-cache.ts | 285 +------------ apps/backend/src/sqliteImporter.ts | 294 +++++++++++++ .../src/trpc/apis/admin-apis/apis/product.ts | 2 +- .../apis/admin-apis/apis/vendor-snippets.ts | 8 +- .../src/trpc/apis/user-apis/apis/auth.ts | 8 +- .../src/trpc/apis/user-apis/apis/order.ts | 76 ++-- .../src/trpc/apis/user-apis/apis/payments.ts | 9 +- .../src/trpc/apis/user-apis/apis/user.ts | 4 +- apps/backend/tsconfig.json | 9 +- apps/backend/worker.ts | 10 + apps/backend/wrangler.toml | 32 ++ bun.lock | 396 +++++++----------- .../db_helper_sqlite/src/admin-apis/coupon.ts | 2 +- .../db_helper_sqlite/src/admin-apis/order.ts | 2 +- .../db_helper_sqlite/src/user-apis/order.ts | 2 +- packages/migrated.db | Bin 0 -> 12288 bytes packages/migrator/README.md | 84 ++++ packages/migrator/data/migrated.db | Bin 0 -> 12288 bytes packages/migrator/package.json | 26 ++ packages/migrator/src/config.ts | 36 ++ .../migrator/src/postgresToSqlite/index.ts | 288 +++++++++++++ .../migrator/src/sqliteToPostgres/index.ts | 273 ++++++++++++ packages/migrator/tsconfig.json | 18 + progress.md | 183 -------- 33 files changed, 1793 insertions(+), 1164 deletions(-) delete mode 100644 apps/backend/src/apis/admin-apis/apis/product.controller.ts create mode 100644 apps/backend/src/app.ts create mode 100755 apps/backend/src/lib/signed-url-cache-old.ts mode change 100755 => 100644 apps/backend/src/lib/signed-url-cache.ts create mode 100644 apps/backend/src/sqliteImporter.ts create mode 100644 apps/backend/worker.ts create mode 100644 apps/backend/wrangler.toml create mode 100644 packages/migrated.db create mode 100644 packages/migrator/README.md create mode 100644 packages/migrator/data/migrated.db create mode 100644 packages/migrator/package.json create mode 100644 packages/migrator/src/config.ts create mode 100644 packages/migrator/src/postgresToSqlite/index.ts create mode 100644 packages/migrator/src/sqliteToPostgres/index.ts create mode 100644 packages/migrator/tsconfig.json delete mode 100644 progress.md diff --git a/AGENTS.md b/AGENTS.md index 6eede73..ae98ac1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,6 @@ # Agent Instructions for Meat Farmer Monorepo ## Important instructions -- Don't try to build the code or run or compile it. Just make changes and leave the rest for the user. - Don't run any drizzle migrations. User will handle it. ## Code Style Guidelines @@ -48,6 +47,4 @@ react-native. They are available in the common-ui as MyText, MyTextInput, MyTouc - Database: Drizzle ORM with PostgreSQL ## Important Notes -- **Do not run build, compile, or migration commands** - These should be handled manually by developers -- Avoid running `npm run build`, `tsc`, `drizzle-kit generate`, or similar compilation/migration commands - Don't do anything with git. Don't do git add or git commit. That will be managed entirely by the user diff --git a/apps/backend/index.ts b/apps/backend/index.ts index ffba6ff..3a828a5 100755 --- a/apps/backend/index.ts +++ b/apps/backend/index.ts @@ -1,17 +1,8 @@ import 'dotenv/config'; -import { Hono } from 'hono'; -import { cors } from 'hono/cors'; -import { logger } from 'hono/logger'; import { serve } from '@hono/node-server'; -import { trpcServer } from '@hono/trpc-server'; -import { getStaffUserById, isUserSuspended } from '@/src/dbService'; -import mainRouter from '@/src/main-router'; import initFunc from '@/src/lib/init'; -import { appRouter } from '@/src/trpc/router'; -import { TRPCError } from '@trpc/server'; -import { jwtVerify } from 'jose' -import { encodedJwtSecret } from '@/src/lib/env-exporter'; -import signedUrlCache from '@/src/lib/signed-url-cache'; +import { createApp } from '@/src/app' +// import signedUrlCache from '@/src/lib/signed-url-cache'; import { seed } from '@/src/lib/seed'; import '@/src/jobs/jobs-index'; import { startAutomatedJobs } from '@/src/lib/automatedJobs'; @@ -20,120 +11,9 @@ seed() initFunc() startAutomatedJobs() -const app = new Hono(); +// signedUrlCache.loadFromDisk(); // Disabled for Workers compatibility -// CORS middleware -app.use(cors({ - origin: 'http://localhost:5174', - allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], - allowHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization'], - credentials: true, -})); - -signedUrlCache.loadFromDisk(); - -// Logger middleware -app.use(logger()); - -// tRPC middleware -app.use('/api/trpc', trpcServer({ - router: appRouter, - createContext: async ({ req }) => { - let user = null; - let staffUser = null; - const authHeader = req.headers.get('authorization'); - - if (authHeader?.startsWith('Bearer ')) { - const token = authHeader.substring(7); - try { - const { payload } = await jwtVerify(token, encodedJwtSecret); - const decoded = payload as any; - - // Check if this is a staff token (has staffId) - if (decoded.staffId) { - // This is a staff token, verify staff exists - const staff = await getStaffUserById(decoded.staffId); - - if (staff) { - user = staffUser - staffUser = { - id: staff.id, - name: staff.name, - }; - } - } else { - - // This is a regular user token - user = decoded; - - // Check if user is suspended - const suspended = await isUserSuspended(user.userId); - - if (suspended) { - throw new TRPCError({ - code: 'FORBIDDEN', - message: 'Account suspended', - }); - } - } - } catch (err) { - // Invalid token, both user and staffUser remain null - } - } - return { req, user, staffUser }; - }, - onError({ error, path, type, ctx }) { - console.error('🚨 tRPC Error :', { - path, - type, - code: error.code, - message: error.message, - userId: ctx?.user?.userId, - stack: error.stack, - }); - }, -})); - -// Mount main router -app.route('/api', mainRouter); - -// Global error handler -app.onError((err, c) => { - console.error(err); - // Handle different error types - let status = 500; - let message = 'Internal Server Error'; - - if (err instanceof TRPCError) { - // Map TRPC error codes to HTTP status codes - const trpcStatusMap: Record = { - 'BAD_REQUEST': 400, - 'UNAUTHORIZED': 401, - 'FORBIDDEN': 403, - 'NOT_FOUND': 404, - 'TIMEOUT': 408, - 'CONFLICT': 409, - 'PRECONDITION_FAILED': 412, - 'PAYLOAD_TOO_LARGE': 413, - 'METHOD_NOT_SUPPORTED': 405, - 'UNPROCESSABLE_CONTENT': 422, - 'TOO_MANY_REQUESTS': 429, - 'INTERNAL_SERVER_ERROR': 500, - }; - status = trpcStatusMap[err.code] || 500; - message = err.message; - } else if ((err as any).statusCode) { - status = (err as any).statusCode; - message = err.message; - } else if ((err as any).status) { - status = (err as any).status; - message = err.message; - } else if (err.message) { - message = err.message; - } - - return c.json({ message }, status as any); -}); +const app = createApp() serve({ fetch: app.fetch, diff --git a/apps/backend/package.json b/apps/backend/package.json index 2ee2228..e6ad9f9 100755 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -10,6 +10,8 @@ "dev2": "tsx watch index.ts", "dev_node": "tsx watch index.ts", "dev": "bun --watch index.ts", + "wrangler:dev": "wrangler dev worker.ts --config wrangler.toml", + "wrangler:deploy": "wrangler deploy worker.ts --config wrangler.toml", "docker:build": "cd .. && docker buildx build --platform linux/amd64 -t mohdshafiuddin54/health_petal:latest --progress=plain -f backend/Dockerfile .", "docker:push": "docker push mohdshafiuddin54/health_petal:latest" }, @@ -36,11 +38,13 @@ "zod": "^4.1.12" }, "devDependencies": { + "@cloudflare/workers-types": "^4.20260304.0", "@types/node": "^24.5.2", "rimraf": "^6.1.2", "ts-node-dev": "^2.0.0", "tsc-alias": "^1.8.16", "tsx": "^4.20.5", - "typescript": "^5.9.2" + "typescript": "^5.9.2", + "wrangler": "^3.114.0" } } diff --git a/apps/backend/src/apis/admin-apis/apis/product.controller.ts b/apps/backend/src/apis/admin-apis/apis/product.controller.ts deleted file mode 100644 index 2d91554..0000000 --- a/apps/backend/src/apis/admin-apis/apis/product.controller.ts +++ /dev/null @@ -1,236 +0,0 @@ -import { Context } from 'hono'; -import { - checkProductExistsByName, - checkUnitExists, - createProduct as createProductRecord, - createSpecialDealsForProduct, - getProductImagesById, - replaceProductTags, - updateProduct as updateProductRecord, - updateProductDeals, -} from '@/src/dbService' -import { ApiError } from "@/src/lib/api-error"; -import type { AdminSpecialDeal } from '@packages/shared' -import { imageUploadS3, getOriginalUrlFromSignedUrl } from "@/src/lib/s3-client"; -import { deleteS3Image } from "@/src/lib/delete-image"; -import { scheduleStoreInitialization } from '@/src/stores/store-initializer'; - - -type CreateDeal = { - quantity: number; - price: number; - validTill: string; -}; - -/** - * Create a new product - */ -export const createProduct = async (c: Context) => { - const body = await c.req.parseBody({ all: true }); - const { name, shortDescription, longDescription, unitId, storeId, price, marketPrice, incrementStep, productQuantity, isSuspended, isFlashAvailable, flashPrice, deals, tagIds } = body; - - // Validate required fields - if (!name || !unitId || !storeId || !price) { - throw new ApiError("Name, unitId, storeId, and price are required", 400); - } - - // Check for duplicate name - const existingProduct = await checkProductExistsByName((name as string).trim()) - - if (existingProduct) { - throw new ApiError("A product with this name already exists", 400); - } - - // Check if unit exists - const unitExists = await checkUnitExists(parseInt(unitId as string)) - - if (!unitExists) { - throw new ApiError("Invalid unit ID", 400); - } - - // Extract images from body - const images = body.images; - let uploadedImageUrls: string[] = []; - - if (images) { - const imageFiles = Array.isArray(images) ? images : [images]; - const imageUploadPromises = imageFiles.map((file, index) => { - if (file instanceof File) { - const key = `product-images/${Date.now()}-${index}`; - return imageUploadS3(Buffer.from(file.stream() as any), file.type, key); - } - return null; - }).filter(Boolean); - - uploadedImageUrls = await Promise.all(imageUploadPromises as Promise[]); - } - - // Create product - const productData: any = { - name: name as string, - shortDescription: shortDescription as string | undefined, - longDescription: longDescription as string | undefined, - unitId: parseInt(unitId as string), - storeId: parseInt(storeId as string), - price: parseFloat(price as string), - marketPrice: marketPrice ? parseFloat(marketPrice as string) : null, - incrementStep: incrementStep ? parseInt(incrementStep as string) : 1, - productQuantity: productQuantity ? parseInt(productQuantity as string) : 1, - isSuspended: isSuspended === 'true', - isFlashAvailable: isFlashAvailable === 'true', - images: uploadedImageUrls, - }; - - if (flashPrice) { - productData.flashPrice = parseFloat(flashPrice as string); - } - - const newProduct = await createProductRecord(productData) - - // Handle deals if provided - let createdDeals: AdminSpecialDeal[] = [] - if (deals) { - const parsedDeals = typeof deals === 'string' ? JSON.parse(deals) : deals; - if (Array.isArray(parsedDeals)) { - createdDeals = await createSpecialDealsForProduct(newProduct.id, parsedDeals) - } - } - - // Handle tag assignments if provided - if (tagIds) { - const parsedTagIds = typeof tagIds === 'string' ? JSON.parse(tagIds) : tagIds; - if (Array.isArray(parsedTagIds)) { - await replaceProductTags(newProduct.id, parsedTagIds) - } - } - - // Reinitialize stores to reflect changes - scheduleStoreInitialization() - - // Send response first - return c.json({ - product: newProduct, - deals: createdDeals, - message: "Product created successfully", - }, 201); -}; - -/** - * Update a product - */ -export const updateProduct = async (c: Context) => { - const id = c.req.param('id') - const body = await c.req.parseBody({ all: true }); - const { name, shortDescription, longDescription, unitId, storeId, price, marketPrice, incrementStep, productQuantity, isSuspended, isFlashAvailable, flashPrice, deals:dealsRaw, imagesToDelete:imagesToDeleteRaw, tagIds } = body; - - - const deals = dealsRaw ? (typeof dealsRaw === 'string' ? JSON.parse(dealsRaw) : dealsRaw) : null; - const imagesToDelete = imagesToDeleteRaw ? (typeof imagesToDeleteRaw === 'string' ? JSON.parse(imagesToDeleteRaw) : imagesToDeleteRaw) : []; - - if (!name || !unitId || !storeId || !price) { - throw new ApiError("Name, unitId, storeId, and price are required", 400); - } - - // Check if unit exists - const unitExists = await checkUnitExists(parseInt(unitId as string)) - - if (!unitExists) { - throw new ApiError("Invalid unit ID", 400); - } - - // Get current product to handle image updates - const currentImages = await getProductImagesById(parseInt(id as string)) - - if (!currentImages) { - throw new ApiError("Product not found", 404); - } - - // Handle image deletions - let updatedImages = currentImages || [] - if (imagesToDelete && imagesToDelete.length > 0) { - // Convert signed URLs to original S3 URLs for comparison - const originalUrlsToDelete = imagesToDelete - .map((signedUrl: string) => getOriginalUrlFromSignedUrl(signedUrl)) - .filter(Boolean); // Remove nulls - - // Find which stored images match the ones to delete - const imagesToRemoveFromDb = updatedImages.filter(storedUrl => - originalUrlsToDelete.includes(storedUrl) - ); - - // Delete the matching images from S3 - const deletePromises = imagesToRemoveFromDb.map(imageUrl => deleteS3Image(imageUrl)); - await Promise.all(deletePromises); - - // Remove deleted images from current images array - updatedImages = updatedImages.filter(img => !imagesToRemoveFromDb.includes(img)); - } - - // Extract new images from body - const images = body.images; - let uploadedImageUrls: string[] = []; - - if (images) { - const imageFiles = Array.isArray(images) ? images : [images]; - const imageUploadPromises = imageFiles.map((file, index) => { - if (file instanceof File) { - const key = `product-images/${Date.now()}-${index}`; - return imageUploadS3(Buffer.from(file.stream() as any), file.type, key); - } - return null; - }).filter(Boolean); - - uploadedImageUrls = await Promise.all(imageUploadPromises as Promise[]); - } - - // Combine remaining current images with new uploaded images - const finalImages = [...updatedImages, ...uploadedImageUrls]; - - const updateData: any = { - name: name as string, - shortDescription: shortDescription as string | undefined, - longDescription: longDescription as string | undefined, - unitId: parseInt(unitId as string), - storeId: parseInt(storeId as string), - price: parseFloat(price as string), - marketPrice: marketPrice ? parseFloat(marketPrice as string) : null, - incrementStep: incrementStep ? parseInt(incrementStep as string) : 1, - productQuantity: productQuantity ? parseInt(productQuantity as string) : 1, - isSuspended: isSuspended === 'true', - images: finalImages.length > 0 ? finalImages : undefined, - }; - - if (isFlashAvailable !== undefined) { - updateData.isFlashAvailable = isFlashAvailable === 'true'; - } - - if (flashPrice !== undefined) { - updateData.flashPrice = flashPrice ? parseFloat(flashPrice as string) : null; - } - - const updatedProduct = await updateProductRecord(parseInt(id as string), updateData) - - if (!updatedProduct) { - throw new ApiError("Product not found", 404); - } - - // Handle deals if provided - if (deals && Array.isArray(deals)) { - await updateProductDeals(parseInt(id as string), deals) - } - - // Handle tag assignments if provided - if (tagIds) { - const parsedTagIds = typeof tagIds === 'string' ? [parseInt(tagIds)] : (Array.isArray(tagIds) ? tagIds.map((t: any) => parseInt(t)) : [parseInt(tagIds as any)]) - await replaceProductTags(parseInt(id as string), parsedTagIds) - } - - // Reinitialize stores to reflect changes - scheduleStoreInitialization() - - // Send response first - return c.json({ - product: updatedProduct, - message: "Product updated successfully", - }, 200); -}; diff --git a/apps/backend/src/app.ts b/apps/backend/src/app.ts new file mode 100644 index 0000000..c4eb7ca --- /dev/null +++ b/apps/backend/src/app.ts @@ -0,0 +1,126 @@ +import { Hono } from 'hono' +import { cors } from 'hono/cors' +import { logger } from 'hono/logger' +import { trpcServer } from '@hono/trpc-server' +import { getStaffUserById, isUserSuspended } from '@/src/dbService' +import mainRouter from '@/src/main-router' +import { appRouter } from '@/src/trpc/router' +import { TRPCError } from '@trpc/server' +import { jwtVerify } from 'jose' +import { encodedJwtSecret } from '@/src/lib/env-exporter' + +export const createApp = () => { + const app = new Hono() + + // CORS middleware + app.use(cors({ + origin: 'http://localhost:5174', + allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], + allowHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization'], + credentials: true, + })) + + // Logger middleware + app.use(logger()) + + // tRPC middleware + app.use('/api/trpc', trpcServer({ + router: appRouter, + createContext: async ({ req }) => { + let user = null + let staffUser = null + const authHeader = req.headers.get('authorization') + + if (authHeader?.startsWith('Bearer ')) { + const token = authHeader.substring(7) + try { + const { payload } = await jwtVerify(token, encodedJwtSecret) + const decoded = payload as any + + // Check if this is a staff token (has staffId) + if (decoded.staffId) { + // This is a staff token, verify staff exists + const staff = await getStaffUserById(decoded.staffId) + + if (staff) { + user = staffUser + staffUser = { + id: staff.id, + name: staff.name, + } + } + } else { + // This is a regular user token + user = decoded + + // Check if user is suspended + const suspended = await isUserSuspended(user.userId) + + if (suspended) { + throw new TRPCError({ + code: 'FORBIDDEN', + message: 'Account suspended', + }) + } + } + } catch (err) { + // Invalid token, both user and staffUser remain null + } + } + return { req, user, staffUser } + }, + onError({ error, path, type, ctx }) { + console.error('🚨 tRPC Error :', { + path, + type, + code: error.code, + message: error.message, + userId: ctx?.user?.userId, + stack: error.stack, + }) + }, + })) + + // Mount main router + app.route('/api', mainRouter) + + // Global error handler + app.onError((err, c) => { + console.error(err) + // Handle different error types + let status = 500 + let message = 'Internal Server Error' + + if (err instanceof TRPCError) { + // Map TRPC error codes to HTTP status codes + const trpcStatusMap: Record = { + BAD_REQUEST: 400, + UNAUTHORIZED: 401, + FORBIDDEN: 403, + NOT_FOUND: 404, + TIMEOUT: 408, + CONFLICT: 409, + PRECONDITION_FAILED: 412, + PAYLOAD_TOO_LARGE: 413, + METHOD_NOT_SUPPORTED: 405, + UNPROCESSABLE_CONTENT: 422, + TOO_MANY_REQUESTS: 429, + INTERNAL_SERVER_ERROR: 500, + } + status = trpcStatusMap[err.code] || 500 + message = err.message + } else if ((err as any).statusCode) { + status = (err as any).statusCode + message = err.message + } else if ((err as any).status) { + status = (err as any).status + message = err.message + } else if (err.message) { + message = err.message + } + + return c.json({ message }, status as any) + }) + + return app +} diff --git a/apps/backend/src/dbService.ts b/apps/backend/src/dbService.ts index b9551d5..7217f8d 100644 --- a/apps/backend/src/dbService.ts +++ b/apps/backend/src/dbService.ts @@ -2,10 +2,13 @@ // This file re-exports everything from postgresImporter to provide a clean abstraction layer import type { AdminOrderDetails } from '@packages/shared' -import { getOrderDetails } from '@/src/postgresImporter' +// import { getOrderDetails } from '@/src/postgresImporter' +import { getOrderDetails } from '@/src/sqliteImporter' // Re-export everything from postgresImporter -export * from '@/src/postgresImporter' +// export * from '@/src/postgresImporter' + +export * from '@/src/sqliteImporter' // Re-export getOrderDetails with the correct signature export async function getOrderDetailsWrapper(orderId: number): Promise { diff --git a/apps/backend/src/lib/env-exporter.ts b/apps/backend/src/lib/env-exporter.ts index 19255d8..2cbecb7 100755 --- a/apps/backend/src/lib/env-exporter.ts +++ b/apps/backend/src/lib/env-exporter.ts @@ -1,57 +1,116 @@ -export const appUrl = process.env.APP_URL as string; +// Old env loading (Node only) +// export const appUrl = process.env.APP_URL as string; +// +// export const jwtSecret: string = process.env.JWT_SECRET as string +// +// export const defaultRoleName = 'gen_user'; +// +// export const encodedJwtSecret = new TextEncoder().encode(jwtSecret) +// +// export const s3AccessKeyId = process.env.S3_ACCESS_KEY_ID as string +// +// export const s3SecretAccessKey = process.env.S3_SECRET_ACCESS_KEY as string +// +// export const s3BucketName = process.env.S3_BUCKET_NAME as string +// +// export const s3Region = process.env.S3_REGION as string +// +// export const assetsDomain = process.env.ASSETS_DOMAIN as string; +// +// export const apiCacheKey = process.env.API_CACHE_KEY as string; +// +// export const cloudflareApiToken = process.env.CLOUDFLARE_API_TOKEN as string; +// +// export const cloudflareZoneId = process.env.CLOUDFLARE_ZONE_ID as string; +// +// export const s3Url = process.env.S3_URL as string +// +// export const redisUrl = process.env.REDIS_URL as string +// +// +// export const expoAccessToken = process.env.EXPO_ACCESS_TOKEN as string; +// +// export const phonePeBaseUrl = process.env.PHONE_PE_BASE_URL as string; +// +// export const phonePeClientId = process.env.PHONE_PE_CLIENT_ID as string; +// +// export const phonePeClientVersion = Number(process.env.PHONE_PE_CLIENT_VERSION as string); +// +// export const phonePeClientSecret = process.env.PHONE_PE_CLIENT_SECRET as string; +// +// export const phonePeMerchantId = process.env.PHONE_PE_MERCHANT_ID as string; +// +// export const razorpayId = process.env.RAZORPAY_KEY as string; +// +// export const razorpaySecret = process.env.RAZORPAY_SECRET as string; +// +// export const otpSenderAuthToken = process.env.OTP_SENDER_AUTH_TOKEN as string; +// +// export const minOrderValue = Number(process.env.MIN_ORDER_VALUE as string); +// +// export const deliveryCharge = Number(process.env.DELIVERY_CHARGE as string); +// +// export const telegramBotToken = process.env.TELEGRAM_BOT_TOKEN as string; +// +// export const telegramChatIds = (process.env.TELEGRAM_CHAT_IDS as string)?.split(',').map(id => id.trim()) || []; +// +// export const isDevMode = (process.env.ENV_MODE as string) === 'dev'; -export const jwtSecret: string = process.env.JWT_SECRET as string +const runtimeEnv = (globalThis as any).ENV || (globalThis as any).process?.env || {} + +export const appUrl = runtimeEnv.APP_URL as string + +export const jwtSecret: string = runtimeEnv.JWT_SECRET as string export const defaultRoleName = 'gen_user'; export const encodedJwtSecret = new TextEncoder().encode(jwtSecret) -export const s3AccessKeyId = process.env.S3_ACCESS_KEY_ID as string +export const s3AccessKeyId = runtimeEnv.S3_ACCESS_KEY_ID as string -export const s3SecretAccessKey = process.env.S3_SECRET_ACCESS_KEY as string +export const s3SecretAccessKey = runtimeEnv.S3_SECRET_ACCESS_KEY as string -export const s3BucketName = process.env.S3_BUCKET_NAME as string +export const s3BucketName = runtimeEnv.S3_BUCKET_NAME as string -export const s3Region = process.env.S3_REGION as string +export const s3Region = runtimeEnv.S3_REGION as string -export const assetsDomain = process.env.ASSETS_DOMAIN as string; +export const assetsDomain = runtimeEnv.ASSETS_DOMAIN as string -export const apiCacheKey = process.env.API_CACHE_KEY as string; +export const apiCacheKey = runtimeEnv.API_CACHE_KEY as string -export const cloudflareApiToken = process.env.CLOUDFLARE_API_TOKEN as string; +export const cloudflareApiToken = runtimeEnv.CLOUDFLARE_API_TOKEN as string -export const cloudflareZoneId = process.env.CLOUDFLARE_ZONE_ID as string; +export const cloudflareZoneId = runtimeEnv.CLOUDFLARE_ZONE_ID as string -export const s3Url = process.env.S3_URL as string +export const s3Url = runtimeEnv.S3_URL as string -export const redisUrl = process.env.REDIS_URL as string +export const redisUrl = runtimeEnv.REDIS_URL as string +export const expoAccessToken = runtimeEnv.EXPO_ACCESS_TOKEN as string -export const expoAccessToken = process.env.EXPO_ACCESS_TOKEN as string; +export const phonePeBaseUrl = runtimeEnv.PHONE_PE_BASE_URL as string -export const phonePeBaseUrl = process.env.PHONE_PE_BASE_URL as string; +export const phonePeClientId = runtimeEnv.PHONE_PE_CLIENT_ID as string -export const phonePeClientId = process.env.PHONE_PE_CLIENT_ID as string; +export const phonePeClientVersion = Number(runtimeEnv.PHONE_PE_CLIENT_VERSION as string) -export const phonePeClientVersion = Number(process.env.PHONE_PE_CLIENT_VERSION as string); +export const phonePeClientSecret = runtimeEnv.PHONE_PE_CLIENT_SECRET as string -export const phonePeClientSecret = process.env.PHONE_PE_CLIENT_SECRET as string; +export const phonePeMerchantId = runtimeEnv.PHONE_PE_MERCHANT_ID as string -export const phonePeMerchantId = process.env.PHONE_PE_MERCHANT_ID as string; +export const razorpayId = runtimeEnv.RAZORPAY_KEY as string -export const razorpayId = process.env.RAZORPAY_KEY as string; +export const razorpaySecret = runtimeEnv.RAZORPAY_SECRET as string -export const razorpaySecret = process.env.RAZORPAY_SECRET as string; +export const otpSenderAuthToken = runtimeEnv.OTP_SENDER_AUTH_TOKEN as string -export const otpSenderAuthToken = process.env.OTP_SENDER_AUTH_TOKEN as string; +export const minOrderValue = Number(runtimeEnv.MIN_ORDER_VALUE as string) -export const minOrderValue = Number(process.env.MIN_ORDER_VALUE as string); +export const deliveryCharge = Number(runtimeEnv.DELIVERY_CHARGE as string) -export const deliveryCharge = Number(process.env.DELIVERY_CHARGE as string); +export const telegramBotToken = runtimeEnv.TELEGRAM_BOT_TOKEN as string -export const telegramBotToken = process.env.TELEGRAM_BOT_TOKEN as string; +export const telegramChatIds = (runtimeEnv.TELEGRAM_CHAT_IDS as string)?.split(',').map(id => id.trim()) || [] -export const telegramChatIds = (process.env.TELEGRAM_CHAT_IDS as string)?.split(',').map(id => id.trim()) || []; - -export const isDevMode = (process.env.ENV_MODE as string) === 'dev'; +export const isDevMode = (runtimeEnv.ENV_MODE as string) === 'dev' diff --git a/apps/backend/src/lib/s3-client.ts b/apps/backend/src/lib/s3-client.ts index 3b4704f..ee93cb0 100755 --- a/apps/backend/src/lib/s3-client.ts +++ b/apps/backend/src/lib/s3-client.ts @@ -1,7 +1,7 @@ // import { s3A, awsBucketName, awsRegion, awsSecretAccessKey } from "@/src/lib/env-exporter" import { DeleteObjectCommand, DeleteObjectsCommand, PutObjectCommand, S3Client, GetObjectCommand } from "@aws-sdk/client-s3" import { getSignedUrl } from "@aws-sdk/s3-request-presigner" -import signedUrlCache from "@/src/lib/signed-url-cache" +// import signedUrlCache from "@/src/lib/signed-url-cache" // Disabled for Workers compatibility import { claimUploadUrlStatus, createUploadUrlStatus } from '@/src/dbService' import { s3AccessKeyId, s3Region, s3Url, s3SecretAccessKey, s3BucketName, assetsDomain } from "@/src/lib/env-exporter" @@ -89,12 +89,11 @@ export async function generateSignedUrlFromS3Url(s3UrlRaw: string|null, expiresI const s3Url = s3UrlRaw try { - // Check if we have a cached signed URL - const cachedUrl = signedUrlCache.get(s3Url); - if (cachedUrl) { - // Found in cache, return it - return cachedUrl; - } + // Cache disabled for Workers compatibility + // const cachedUrl = signedUrlCache.get(s3Url); + // if (cachedUrl) { + // return cachedUrl; + // } // Create the command to get the object const command = new GetObjectCommand({ @@ -105,8 +104,8 @@ export async function generateSignedUrlFromS3Url(s3UrlRaw: string|null, expiresI // Generate the signed URL const signedUrl = await getSignedUrl(s3Client, command, { expiresIn }); - // Cache the signed URL with TTL matching the expiration time (convert seconds to milliseconds) - signedUrlCache.set(s3Url, signedUrl, (expiresIn * 1000) - 60000); // Subtract 1 minute to ensure it doesn't expire before use + // Cache disabled for Workers compatibility + // signedUrlCache.set(s3Url, signedUrl, (expiresIn * 1000) - 60000); return signedUrl; } catch (error) { @@ -121,14 +120,9 @@ export async function generateSignedUrlFromS3Url(s3UrlRaw: string|null, expiresI * @returns The original S3 URL if found in cache, otherwise null */ export function getOriginalUrlFromSignedUrl(signedUrl: string|null): string|null { - if (!signedUrl) { - return null; - } - - // Try to find the original URL in our cache - const originalUrl = signedUrlCache.getOriginalUrl(signedUrl); - - return originalUrl || null; + // Cache disabled for Workers compatibility - cannot retrieve original URL without cache + // To re-enable, migrate signed-url-cache to object storage (R2/S3) + return null; } /** diff --git a/apps/backend/src/lib/signed-url-cache-old.ts b/apps/backend/src/lib/signed-url-cache-old.ts new file mode 100755 index 0000000..0f4e98c --- /dev/null +++ b/apps/backend/src/lib/signed-url-cache-old.ts @@ -0,0 +1,263 @@ +import fs from 'fs'; +import path from 'path'; + +const CACHE_FILE_PATH = path.join('.', 'assets', 'signed-url-cache.json'); + +// Interface for cache entries with TTL +interface CacheEntry { + value: string; + expiresAt: number; // Timestamp when this entry expires +} + +class SignedURLCache { + private originalToSignedCache: Map; + private signedToOriginalCache: Map; + + constructor() { + this.originalToSignedCache = new Map(); + this.signedToOriginalCache = new Map(); + + // Create cache directory if it doesn't exist + const cacheDir = path.dirname(CACHE_FILE_PATH); + if (!fs.existsSync(cacheDir)) { + console.log('creating the directory') + + fs.mkdirSync(cacheDir, { recursive: true }); + } + else { + console.log('the directory is already present') + + } + } + + /** + * Get a signed URL from the cache using an original URL as the key + */ + get(originalUrl: string): string | undefined { + const entry = this.originalToSignedCache.get(originalUrl); + + // If no entry or entry has expired, return undefined + if (!entry || Date.now() > entry.expiresAt) { + if (entry) { + // Remove expired entry + this.originalToSignedCache.delete(originalUrl); + // Also remove from reverse mapping if it exists + this.signedToOriginalCache.delete(entry.value); + } + return undefined; + } + + return entry.value; + } + + /** + * Get the original URL from the cache using a signed URL as the key + */ + getOriginalUrl(signedUrl: string): string | undefined { + const entry = this.signedToOriginalCache.get(signedUrl); + + // If no entry or entry has expired, return undefined + if (!entry || Date.now() > entry.expiresAt) { + if (entry) { + // Remove expired entry + this.signedToOriginalCache.delete(signedUrl); + // Also remove from primary mapping if it exists + this.originalToSignedCache.delete(entry.value); + } + return undefined; + } + + return entry.value; + } + + /** + * Set a value in the cache with a TTL (Time To Live) + * @param originalUrl The original S3 URL + * @param signedUrl The signed URL + * @param ttlMs Time to live in milliseconds (default: 3 days) + */ + set(originalUrl: string, signedUrl: string, ttlMs: number = 259200000): void { + const expiresAt = Date.now() + ttlMs; + + const entry: CacheEntry = { + value: signedUrl, + expiresAt + }; + + const reverseEntry: CacheEntry = { + value: originalUrl, + expiresAt + }; + + this.originalToSignedCache.set(originalUrl, entry); + this.signedToOriginalCache.set(signedUrl, reverseEntry); + } + + has(originalUrl: string): boolean { + const entry = this.originalToSignedCache.get(originalUrl); + + // Entry exists and hasn't expired + return !!entry && Date.now() <= entry.expiresAt; + } + + hasSignedUrl(signedUrl: string): boolean { + const entry = this.signedToOriginalCache.get(signedUrl); + + // Entry exists and hasn't expired + return !!entry && Date.now() <= entry.expiresAt; + } + + clear(): void { + this.originalToSignedCache.clear(); + this.signedToOriginalCache.clear(); + this.saveToDisk(); + } + + /** + * Remove all expired entries from the cache + * @returns The number of expired entries that were removed + */ + clearExpired(): number { + const now = Date.now(); + let removedCount = 0; + + // Clear expired entries from original to signed cache + for (const [originalUrl, entry] of this.originalToSignedCache.entries()) { + if (now > entry.expiresAt) { + this.originalToSignedCache.delete(originalUrl); + removedCount++; + } + } + + // Clear expired entries from signed to original cache + for (const [signedUrl, entry] of this.signedToOriginalCache.entries()) { + if (now > entry.expiresAt) { + this.signedToOriginalCache.delete(signedUrl); + // No need to increment removedCount as we've already counted these in the first loop + } + } + + if (removedCount > 0) { + console.log(`SignedURLCache: Cleared ${removedCount} expired entries`); + } + + return removedCount; + } + + /** + * Save the cache to disk + */ + saveToDisk(): void { + try { + // Remove expired entries before saving + const removedCount = this.clearExpired(); + + // Convert Maps to serializable objects + const serializedOriginalToSigned: Record = {}; + const serializedSignedToOriginal: Record = {}; + + for (const [originalUrl, entry] of this.originalToSignedCache.entries()) { + serializedOriginalToSigned[originalUrl] = { + value: entry.value, + expiresAt: entry.expiresAt + }; + } + + for (const [signedUrl, entry] of this.signedToOriginalCache.entries()) { + serializedSignedToOriginal[signedUrl] = { + value: entry.value, + expiresAt: entry.expiresAt + }; + } + + const serializedCache = { + originalToSigned: serializedOriginalToSigned, + signedToOriginal: serializedSignedToOriginal + }; + + // Write to file + fs.writeFileSync( + CACHE_FILE_PATH, + JSON.stringify(serializedCache), + 'utf8' + ); + + console.log(`SignedURLCache: Saved ${this.originalToSignedCache.size} entries to disk`); + } catch (error) { + console.error('Error saving SignedURLCache to disk:', error); + } + } + + /** + * Load the cache from disk + */ + loadFromDisk(): void { + try { + if (fs.existsSync(CACHE_FILE_PATH)) { + // Read from file + const data = fs.readFileSync(CACHE_FILE_PATH, 'utf8'); + + // Parse the data + const parsedData = JSON.parse(data) as { + originalToSigned: Record, + signedToOriginal: Record + }; + + // Only load entries that haven't expired yet + const now = Date.now(); + let loadedCount = 0; + let expiredCount = 0; + + // Load original to signed mappings + if (parsedData.originalToSigned) { + for (const [originalUrl, entry] of Object.entries(parsedData.originalToSigned)) { + if (now <= entry.expiresAt) { + this.originalToSignedCache.set(originalUrl, entry); + loadedCount++; + } else { + expiredCount++; + } + } + } + + // Load signed to original mappings + if (parsedData.signedToOriginal) { + for (const [signedUrl, entry] of Object.entries(parsedData.signedToOriginal)) { + if (now <= entry.expiresAt) { + this.signedToOriginalCache.set(signedUrl, entry); + // Don't increment loadedCount as these are pairs of what we already counted + } else { + // Don't increment expiredCount as these are pairs of what we already counted + } + } + } + + console.log(`SignedURLCache: Loaded ${loadedCount} valid entries from disk (skipped ${expiredCount} expired entries)`); + } else { + console.log('SignedURLCache: No cache file found, starting with empty cache'); + } + } catch (error) { + console.error('Error loading SignedURLCache from disk:', error); + // Start with empty caches if loading fails + this.originalToSignedCache = new Map(); + this.signedToOriginalCache = new Map(); + } + } +} + +// Create a singleton instance to be used throughout the application +const signedUrlCache = new SignedURLCache(); + +process.on('SIGINT', () => { + console.log('SignedURLCache: Saving cache before shutdown...'); + signedUrlCache.saveToDisk(); + process.exit(0); +}); + +process.on('SIGTERM', () => { + console.log('SignedURLCache: Saving cache before shutdown...'); + signedUrlCache.saveToDisk(); + process.exit(0); +}); + +export default signedUrlCache; \ No newline at end of file diff --git a/apps/backend/src/lib/signed-url-cache.ts b/apps/backend/src/lib/signed-url-cache.ts old mode 100755 new mode 100644 index 0f4e98c..69a391a --- a/apps/backend/src/lib/signed-url-cache.ts +++ b/apps/backend/src/lib/signed-url-cache.ts @@ -1,263 +1,24 @@ -import fs from 'fs'; -import path from 'path'; +// SIGNED URL CACHE - DISABLED +// This file has been disabled to make the backend compatible with Cloudflare Workers. +// File system operations are not available in the Workers environment. +// +// To re-enable caching, migrate to Cloudflare R2 or another object storage solution. +// Original file saved as: signed-url-cache-old.ts +// +// Impact of disabling: +// - S3 signed URLs are generated fresh on every request +// - Increased AWS API calls (higher costs) +// - Slightly slower image loading +// - No file system dependencies (Workers-compatible) -const CACHE_FILE_PATH = path.join('.', 'assets', 'signed-url-cache.json'); - -// Interface for cache entries with TTL -interface CacheEntry { - value: string; - expiresAt: number; // Timestamp when this entry expires -} - -class SignedURLCache { - private originalToSignedCache: Map; - private signedToOriginalCache: Map; - - constructor() { - this.originalToSignedCache = new Map(); - this.signedToOriginalCache = new Map(); - - // Create cache directory if it doesn't exist - const cacheDir = path.dirname(CACHE_FILE_PATH); - if (!fs.existsSync(cacheDir)) { - console.log('creating the directory') - - fs.mkdirSync(cacheDir, { recursive: true }); - } - else { - console.log('the directory is already present') - - } - } - - /** - * Get a signed URL from the cache using an original URL as the key - */ - get(originalUrl: string): string | undefined { - const entry = this.originalToSignedCache.get(originalUrl); - - // If no entry or entry has expired, return undefined - if (!entry || Date.now() > entry.expiresAt) { - if (entry) { - // Remove expired entry - this.originalToSignedCache.delete(originalUrl); - // Also remove from reverse mapping if it exists - this.signedToOriginalCache.delete(entry.value); - } - return undefined; - } - - return entry.value; - } - - /** - * Get the original URL from the cache using a signed URL as the key - */ - getOriginalUrl(signedUrl: string): string | undefined { - const entry = this.signedToOriginalCache.get(signedUrl); - - // If no entry or entry has expired, return undefined - if (!entry || Date.now() > entry.expiresAt) { - if (entry) { - // Remove expired entry - this.signedToOriginalCache.delete(signedUrl); - // Also remove from primary mapping if it exists - this.originalToSignedCache.delete(entry.value); - } - return undefined; - } - - return entry.value; - } - - /** - * Set a value in the cache with a TTL (Time To Live) - * @param originalUrl The original S3 URL - * @param signedUrl The signed URL - * @param ttlMs Time to live in milliseconds (default: 3 days) - */ - set(originalUrl: string, signedUrl: string, ttlMs: number = 259200000): void { - const expiresAt = Date.now() + ttlMs; - - const entry: CacheEntry = { - value: signedUrl, - expiresAt - }; - - const reverseEntry: CacheEntry = { - value: originalUrl, - expiresAt - }; - - this.originalToSignedCache.set(originalUrl, entry); - this.signedToOriginalCache.set(signedUrl, reverseEntry); - } - - has(originalUrl: string): boolean { - const entry = this.originalToSignedCache.get(originalUrl); - - // Entry exists and hasn't expired - return !!entry && Date.now() <= entry.expiresAt; - } - - hasSignedUrl(signedUrl: string): boolean { - const entry = this.signedToOriginalCache.get(signedUrl); - - // Entry exists and hasn't expired - return !!entry && Date.now() <= entry.expiresAt; - } - - clear(): void { - this.originalToSignedCache.clear(); - this.signedToOriginalCache.clear(); - this.saveToDisk(); - } - - /** - * Remove all expired entries from the cache - * @returns The number of expired entries that were removed - */ - clearExpired(): number { - const now = Date.now(); - let removedCount = 0; - - // Clear expired entries from original to signed cache - for (const [originalUrl, entry] of this.originalToSignedCache.entries()) { - if (now > entry.expiresAt) { - this.originalToSignedCache.delete(originalUrl); - removedCount++; - } - } - - // Clear expired entries from signed to original cache - for (const [signedUrl, entry] of this.signedToOriginalCache.entries()) { - if (now > entry.expiresAt) { - this.signedToOriginalCache.delete(signedUrl); - // No need to increment removedCount as we've already counted these in the first loop - } - } - - if (removedCount > 0) { - console.log(`SignedURLCache: Cleared ${removedCount} expired entries`); - } - - return removedCount; - } - - /** - * Save the cache to disk - */ - saveToDisk(): void { - try { - // Remove expired entries before saving - const removedCount = this.clearExpired(); - - // Convert Maps to serializable objects - const serializedOriginalToSigned: Record = {}; - const serializedSignedToOriginal: Record = {}; - - for (const [originalUrl, entry] of this.originalToSignedCache.entries()) { - serializedOriginalToSigned[originalUrl] = { - value: entry.value, - expiresAt: entry.expiresAt - }; - } - - for (const [signedUrl, entry] of this.signedToOriginalCache.entries()) { - serializedSignedToOriginal[signedUrl] = { - value: entry.value, - expiresAt: entry.expiresAt - }; - } - - const serializedCache = { - originalToSigned: serializedOriginalToSigned, - signedToOriginal: serializedSignedToOriginal - }; - - // Write to file - fs.writeFileSync( - CACHE_FILE_PATH, - JSON.stringify(serializedCache), - 'utf8' - ); - - console.log(`SignedURLCache: Saved ${this.originalToSignedCache.size} entries to disk`); - } catch (error) { - console.error('Error saving SignedURLCache to disk:', error); - } - } - - /** - * Load the cache from disk - */ - loadFromDisk(): void { - try { - if (fs.existsSync(CACHE_FILE_PATH)) { - // Read from file - const data = fs.readFileSync(CACHE_FILE_PATH, 'utf8'); - - // Parse the data - const parsedData = JSON.parse(data) as { - originalToSigned: Record, - signedToOriginal: Record - }; - - // Only load entries that haven't expired yet - const now = Date.now(); - let loadedCount = 0; - let expiredCount = 0; - - // Load original to signed mappings - if (parsedData.originalToSigned) { - for (const [originalUrl, entry] of Object.entries(parsedData.originalToSigned)) { - if (now <= entry.expiresAt) { - this.originalToSignedCache.set(originalUrl, entry); - loadedCount++; - } else { - expiredCount++; - } - } - } - - // Load signed to original mappings - if (parsedData.signedToOriginal) { - for (const [signedUrl, entry] of Object.entries(parsedData.signedToOriginal)) { - if (now <= entry.expiresAt) { - this.signedToOriginalCache.set(signedUrl, entry); - // Don't increment loadedCount as these are pairs of what we already counted - } else { - // Don't increment expiredCount as these are pairs of what we already counted - } - } - } - - console.log(`SignedURLCache: Loaded ${loadedCount} valid entries from disk (skipped ${expiredCount} expired entries)`); - } else { - console.log('SignedURLCache: No cache file found, starting with empty cache'); - } - } catch (error) { - console.error('Error loading SignedURLCache from disk:', error); - // Start with empty caches if loading fails - this.originalToSignedCache = new Map(); - this.signedToOriginalCache = new Map(); - } - } -} - -// Create a singleton instance to be used throughout the application -const signedUrlCache = new SignedURLCache(); - -process.on('SIGINT', () => { - console.log('SignedURLCache: Saving cache before shutdown...'); - signedUrlCache.saveToDisk(); - process.exit(0); -}); - -process.on('SIGTERM', () => { - console.log('SignedURLCache: Saving cache before shutdown...'); - signedUrlCache.saveToDisk(); - process.exit(0); -}); - -export default signedUrlCache; \ No newline at end of file +export default { + get: () => undefined, + set: () => {}, + getOriginalUrl: () => undefined, + has: () => false, + hasSignedUrl: () => false, + clear: () => {}, + clearExpired: () => 0, + saveToDisk: () => {}, + loadFromDisk: () => {}, +}; diff --git a/apps/backend/src/sqliteImporter.ts b/apps/backend/src/sqliteImporter.ts new file mode 100644 index 0000000..051acd8 --- /dev/null +++ b/apps/backend/src/sqliteImporter.ts @@ -0,0 +1,294 @@ +// SQLite Importer - Intermediate layer to avoid direct db_helper_sqlite imports in dbService +// This file re-exports everything from sqliteService + +// Re-export database connection +export { db, initDb } from 'sqliteService' + +// Re-export all schema exports +export * from 'sqliteService' + +// Re-export all helper methods from sqliteService +export { + // Admin - Banner + getBanners, + getBannerById, + createBanner, + updateBanner, + deleteBanner, + // Admin - Complaint + getComplaints, + resolveComplaint, + // Admin - Constants + getAllConstants, + upsertConstants, + // Admin - Coupon + getAllCoupons, + getCouponById, + invalidateCoupon, + validateCoupon, + getReservedCoupons, + getUsersForCoupon, + createCouponWithRelations, + updateCouponWithRelations, + generateCancellationCoupon, + createReservedCouponWithProducts, + createCouponForUser, + checkUsersExist, + checkCouponExists, + checkReservedCouponExists, + getOrderWithUser, + // Admin - Order + updateOrderNotes, + getOrderDetails, + updateOrderPackaged, + updateOrderDelivered, + updateOrderItemPackaging, + removeDeliveryCharge, + getSlotOrders, + updateAddressCoords, + getAllOrders, + rebalanceSlots, + cancelOrder, + deleteOrderById, + // Admin - Product + getAllProducts, + getProductById, + deleteProduct, + createProduct, + updateProduct, + checkProductExistsByName, + checkUnitExists, + getProductImagesById, + createSpecialDealsForProduct, + updateProductDeals, + replaceProductTags, + toggleProductOutOfStock, + updateSlotProducts, + getSlotProductIds, + getSlotsProductIds, + getAllUnits, + getAllProductTags, + getAllProductTagInfos, + getProductTagInfoById, + createProductTag, + getProductTagById, + updateProductTag, + deleteProductTag, + checkProductTagExistsByName, + getProductReviews, + respondToReview, + getAllProductGroups, + createProductGroup, + updateProductGroup, + deleteProductGroup, + addProductToGroup, + removeProductFromGroup, + updateProductPrices, + // Admin - Slots + getActiveSlotsWithProducts, + getActiveSlots, + getSlotsAfterDate, + getSlotByIdWithRelations, + createSlotWithRelations, + updateSlotWithRelations, + deleteSlotById, + updateSlotCapacity, + getSlotDeliverySequence, + updateSlotDeliverySequence, + // Admin - Staff User + getStaffUserByName, + getStaffUserById, + getAllStaff, + getAllUsers, + getUserWithDetails, + updateUserSuspensionStatus, + checkStaffUserExists, + checkStaffRoleExists, + createStaffUser, + getAllRoles, + // Admin - Store + getAllStores, + getStoreById, + createStore, + updateStore, + deleteStore, + // Admin - User + createUserByMobile, + getUserByMobile, + getUnresolvedComplaintsCount, + getAllUsersWithFilters, + getOrderCountsByUserIds, + getLastOrdersByUserIds, + getSuspensionStatusesByUserIds, + getUserBasicInfo, + getUserSuspensionStatus, + getUserOrders, + getOrderStatusesByOrderIds, + getItemCountsByOrderIds, + upsertUserSuspension, + searchUsers, + getAllNotifCreds, + getAllUnloggedTokens, + getNotifTokensByUserIds, + getUserIncidentsWithRelations, + createUserIncident, + // Admin - Vendor Snippets + checkVendorSnippetExists, + getVendorSnippetById, + getVendorSnippetByCode, + getAllVendorSnippets, + createVendorSnippet, + updateVendorSnippet, + deleteVendorSnippet, + getProductsByIds, + getVendorSlotById, + getVendorOrdersBySlotId, + getOrderItemsByOrderIds, + getOrderStatusByOrderIds, + updateVendorOrderItemPackaging, + getVendorOrders, + // User - Address + getUserDefaultAddress, + getUserAddresses, + getUserAddressById, + clearUserDefaultAddress, + createUserAddress, + updateUserAddress, + deleteUserAddress, + hasOngoingOrdersForAddress, + // User - Banners + getUserActiveBanners, + // User - Cart + getUserCartItemsWithProducts, + getUserProductById, + getUserCartItemByUserProduct, + incrementUserCartItemQuantity, + insertUserCartItem, + updateUserCartItemQuantity, + deleteUserCartItem, + clearUserCart, + // User - Complaint + getUserComplaints, + createUserComplaint, + // User - Stores + getUserStoreSummaries, + getUserStoreDetail, + // User - Product + getUserProductDetailById, + getUserProductReviews, + getUserProductByIdBasic, + createUserProductReview, + getAllProductsWithUnits, + type ProductSummaryData, + // User - Slots + getUserActiveSlotsList, + getUserProductAvailability, + // User - Payments + getUserPaymentOrderById, + getUserPaymentByOrderId, + getUserPaymentByMerchantOrderId, + updateUserPaymentSuccess, + updateUserOrderPaymentStatus, + markUserPaymentFailed, + // User - Auth + getUserAuthByEmail, + getUserAuthByMobile, + getUserAuthById, + getUserAuthCreds, + getUserAuthDetails, + isUserSuspended, + createUserAuthWithCreds, + createUserAuthWithMobile, + upsertUserAuthPassword, + deleteUserAuthAccount, + // UV API helpers + createUserWithProfile, + getUserDetailsByUserId, + updateUserProfile, + // User - Coupon + getUserActiveCouponsWithRelations, + getUserAllCouponsWithRelations, + getUserReservedCouponByCode, + redeemUserReservedCoupon, + // User - Profile + getUserProfileById, + getUserProfileDetailById, + getUserWithCreds, + getUserNotifCred, + upsertUserNotifCred, + deleteUserUnloggedToken, + getUserUnloggedToken, + upsertUserUnloggedToken, + // User - Order + validateAndGetUserCoupon, + applyDiscountToUserOrder, + getUserAddressByIdAndUser, + getOrderProductById, + checkUserSuspended, + getUserSlotCapacityStatus, + placeUserOrderTransaction, + deleteUserCartItemsForOrder, + recordUserCouponUsage, + getUserOrdersWithRelations, + getUserOrderCount, + getUserOrderByIdWithRelations, + getUserCouponUsageForOrder, + getUserOrderBasic, + cancelUserOrderTransaction, + updateUserOrderNotes, + getUserRecentlyDeliveredOrderIds, + getUserProductIdsFromOrders, + getUserProductsForRecentOrders, + // Store Helpers + getAllBannersForCache, + getAllProductsForCache, + getAllStoresForCache, + getAllDeliverySlotsForCache, + getAllSpecialDealsForCache, + getAllProductTagsForCache, + getAllTagsForCache, + getAllTagProductMappings, + getAllSlotsWithProductsForCache, + getAllUserNegativityScores, + getUserNegativityScore, + type BannerData, + type ProductBasicData, + type StoreBasicData, + type DeliverySlotData, + type SpecialDealData, + type ProductTagData, + type TagBasicData, + type TagProductMapping, + type SlotWithProductsData, + type UserNegativityData, + // Automated Jobs + toggleFlashDeliveryForItems, + toggleKeyVal, + getAllKeyValStore, + // Post-order handler helpers + getOrdersByIdsWithFullData, + getOrderByIdWithFullData, + type OrderWithFullData, + type OrderWithCancellationData, + // Common API helpers + getSuspendedProductIds, + getNextDeliveryDateWithCapacity, + getStoresSummary, + healthCheck, + // Delete orders helper + deleteOrdersWithRelations, + // Seed helpers + seedUnits, + seedStaffRoles, + seedStaffPermissions, + seedRolePermissions, + seedKeyValStore, + type UnitSeedData, + type RolePermissionAssignment, + type KeyValSeedData, + type StaffRoleName, + type StaffPermissionName, + // Upload URL Helpers + createUploadUrlStatus, + claimUploadUrlStatus, +} from 'sqliteService' diff --git a/apps/backend/src/trpc/apis/admin-apis/apis/product.ts b/apps/backend/src/trpc/apis/admin-apis/apis/product.ts index 270d0a2..37d73d7 100644 --- a/apps/backend/src/trpc/apis/admin-apis/apis/product.ts +++ b/apps/backend/src/trpc/apis/admin-apis/apis/product.ts @@ -661,7 +661,7 @@ export const productRouter = router({ return { groups: groups.map(group => ({ ...group, - products: group.memberships.map(m => ({ + products: group.memberships.map((m: any) => ({ ...(m.product as AdminProduct), images: (m.product.images as string[]) || null, })), diff --git a/apps/backend/src/trpc/apis/admin-apis/apis/vendor-snippets.ts b/apps/backend/src/trpc/apis/admin-apis/apis/vendor-snippets.ts index 9d8a80b..7e3f330 100644 --- a/apps/backend/src/trpc/apis/admin-apis/apis/vendor-snippets.ts +++ b/apps/backend/src/trpc/apis/admin-apis/apis/vendor-snippets.ts @@ -420,9 +420,9 @@ export const vendorSnippetsRouter = router({ productName: item.product.name, quantity: parseFloat(item.quantity), productSize: item.product.productQuantity, - price: parseFloat(item.price.toString()), + price: parseFloat((item.price ?? 0).toString()), unit: item.product.unit?.shortNotation || 'unit', - subtotal: parseFloat(item.price.toString()) * parseFloat(item.quantity), + subtotal: parseFloat((item.price ?? 0).toString()) * parseFloat(item.quantity), is_packaged: item.is_packaged, is_package_verified: item.is_package_verified, })); @@ -604,9 +604,9 @@ export const vendorSnippetsRouter = router({ productId: item.productId, productName: item.product.name, quantity: parseFloat(item.quantity), - price: parseFloat(item.price.toString()), + price: parseFloat((item.price ?? 0).toString()), unit: item.product.unit?.shortNotation || 'unit', - subtotal: parseFloat(item.price.toString()) * parseFloat(item.quantity), + subtotal: parseFloat((item.price ?? 0).toString()) * parseFloat(item.quantity), productSize: item.product.productQuantity, is_packaged: item.is_packaged, is_package_verified: item.is_package_verified, 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 93fb98b..c54a49d 100644 --- a/apps/backend/src/trpc/apis/user-apis/apis/auth.ts +++ b/apps/backend/src/trpc/apis/user-apis/apis/auth.ts @@ -110,7 +110,9 @@ export const authRouter = router({ createdAt: foundUser.createdAt.toISOString(), profileImage: profileImageSignedUrl, bio: userDetail?.bio || null, - dateOfBirth: userDetail?.dateOfBirth || null, + dateOfBirth: userDetail?.dateOfBirth + ? new Date(userDetail.dateOfBirth as any).toISOString() + : null, gender: userDetail?.gender || null, occupation: userDetail?.occupation || null, }, @@ -370,7 +372,9 @@ export const authRouter = router({ createdAt: updatedUser.createdAt?.toISOString?.() || new Date().toISOString(), profileImage: profileImageSignedUrl, bio: userDetail?.bio || null, - dateOfBirth: userDetail?.dateOfBirth || null, + dateOfBirth: userDetail?.dateOfBirth + ? new Date(userDetail.dateOfBirth as any).toISOString() + : null, gender: userDetail?.gender || null, occupation: userDetail?.occupation || null, }, diff --git a/apps/backend/src/trpc/apis/user-apis/apis/order.ts b/apps/backend/src/trpc/apis/user-apis/apis/order.ts index 2ef55c1..a19c06b 100644 --- a/apps/backend/src/trpc/apis/user-apis/apis/order.ts +++ b/apps/backend/src/trpc/apis/user-apis/apis/order.ts @@ -1,25 +1,29 @@ import { router, protectedProcedure } from "@/src/trpc/trpc-index"; import { z } from "zod"; import { - validateAndGetUserCoupon, applyDiscountToUserOrder, - getUserAddressByIdAndUser, - getOrderProductById, + cancelUserOrderTransaction, checkUserSuspended, - getUserSlotCapacityStatus, - placeUserOrderTransaction, + db, deleteUserCartItemsForOrder, - recordUserCouponUsage, - getUserOrdersWithRelations, - getUserOrderCount, - getUserOrderByIdWithRelations, + getOrderProductById, + getUserAddressByIdAndUser, getUserCouponUsageForOrder, getUserOrderBasic, - cancelUserOrderTransaction, - updateUserOrderNotes, - getUserRecentlyDeliveredOrderIds, + getUserOrderByIdWithRelations, + getUserOrderCount, + getUserOrdersWithRelations, getUserProductIdsFromOrders, getUserProductsForRecentOrders, + getUserRecentlyDeliveredOrderIds, + getUserSlotCapacityStatus, + orders, + orderItems, + orderStatus, + placeUserOrderTransaction, + recordUserCouponUsage, + updateUserOrderNotes, + validateAndGetUserCoupon, } from "@/src/dbService"; import { getNextDeliveryDate } from "@/src/trpc/apis/common-apis/common"; import { scaffoldAssetUrl } from "@/src/lib/s3-client"; @@ -115,9 +119,10 @@ const placeOrderUtil = async (params: { const orderTotal = items.reduce( (sum, item) => { if (!item.product) return sum - const itemPrice = params.isFlash - ? parseFloat((item.product.flashPrice || item.product.price).toString()) - : parseFloat(item.product.price.toString()); + const basePrice = params.isFlash + ? (item.product.flashPrice ?? item.product.price) + : item.product.price + const itemPrice = parseFloat((basePrice ?? 0).toString()) return sum + itemPrice * item.quantity; }, 0 @@ -132,9 +137,6 @@ const placeOrderUtil = async (params: { const totalWithDelivery = totalAmount + expectedDeliveryCharge; - const { db } = await import("postgresService"); - const { orders, orderItems, orderStatus } = await import("postgresService"); - type OrderData = { order: Omit; orderItems: Omit[]; @@ -148,9 +150,10 @@ const placeOrderUtil = async (params: { const subOrderTotal = items.reduce( (sum, item) => { if (!item.product) return sum - const itemPrice = params.isFlash - ? parseFloat((item.product.flashPrice || item.product.price).toString()) - : parseFloat(item.product.price.toString()); + const basePrice = params.isFlash + ? (item.product.flashPrice ?? item.product.price) + : item.product.price + const itemPrice = parseFloat((basePrice ?? 0).toString()) return sum + itemPrice * item.quantity; }, 0 @@ -182,23 +185,26 @@ const placeOrderUtil = async (params: { isFlashDelivery: params.isFlash, }; - const orderItemsData: Omit[] = items - .filter((item) => item.product !== null && item.product !== undefined) - .map( - (item) => ({ + const validItems = items.filter( + (item): item is typeof item & { product: NonNullable } => + item.product !== null && item.product !== undefined + ) + const orderItemsData: Omit[] = validItems.map( + (item) => { + const basePrice = params.isFlash + ? (item.product.flashPrice ?? item.product.price) + : item.product.price + const priceString = (basePrice ?? 0).toString() + + return { orderId: 0, productId: item.productId, quantity: item.quantity.toString(), - price: params.isFlash - ? item.product!.flashPrice || item.product!.price - : item.product!.price, - discountedPrice: ( - params.isFlash - ? item.product!.flashPrice || item.product!.price - : item.product!.price - ).toString(), - }) - ); + price: priceString, + discountedPrice: priceString, + } + } + ); const orderStatusData: Omit = { userId, diff --git a/apps/backend/src/trpc/apis/user-apis/apis/payments.ts b/apps/backend/src/trpc/apis/user-apis/apis/payments.ts index fe94925..52a6964 100644 --- a/apps/backend/src/trpc/apis/user-apis/apis/payments.ts +++ b/apps/backend/src/trpc/apis/user-apis/apis/payments.ts @@ -65,9 +65,12 @@ export const paymentRouter = router({ }; } - // Create Razorpay order and insert payment record - const razorpayOrder = await RazorpayPaymentService.createOrder(parseInt(orderId), order.totalAmount); - await RazorpayPaymentService.insertPaymentRecord(parseInt(orderId), razorpayOrder); + // Create Razorpay order and insert payment record + if (order.totalAmount === null) { + throw new ApiError('Order total is missing', 400) + } + const razorpayOrder = await RazorpayPaymentService.createOrder(parseInt(orderId), order.totalAmount); + await RazorpayPaymentService.insertPaymentRecord(parseInt(orderId), razorpayOrder); return { razorpayOrderId: 0, 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 5d94d14..841fb74 100644 --- a/apps/backend/src/trpc/apis/user-apis/apis/user.ts +++ b/apps/backend/src/trpc/apis/user-apis/apis/user.ts @@ -59,7 +59,9 @@ export const userRouter = router({ mobile: user.mobile, profileImage: profileImageSignedUrl, bio: userDetail?.bio || null, - dateOfBirth: userDetail?.dateOfBirth || null, + dateOfBirth: userDetail?.dateOfBirth + ? new Date(userDetail.dateOfBirth as any).toISOString() + : null, gender: userDetail?.gender || null, occupation: userDetail?.occupation || null, }, diff --git a/apps/backend/tsconfig.json b/apps/backend/tsconfig.json index b74475b..7bc184b 100755 --- a/apps/backend/tsconfig.json +++ b/apps/backend/tsconfig.json @@ -35,8 +35,10 @@ "@commonTypes/*": ["../../packages/ui/shared-types/*"], "@packages/shared": ["../../packages/shared"], "@packages/shared/*": ["../../packages/shared/*"], - "postgresService": ["../../packages/db_helper_postgres"], - "postgresService/*": ["../../packages/db_helper_postgres/*"], + // "postgresService": ["../../packages/db_helper_postgres"], + // "postgresService/*": ["../../packages/db_helper_postgres/*"], + "sqliteService": ["../../packages/db_helper_sqlite"], + "sqliteService/*": ["../../packages/db_helper_sqlite/*"], "global-shared": ["../../packages/shared"], "global-shared/*": ["../../packages/shared/*"] }, @@ -122,6 +124,5 @@ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */ }, - "include": ["src", "types", "index.ts", "../shared-types", "../../packages/shared"] + "include": ["src", "types", "index.ts", "worker.ts", "../shared-types", "../../packages/shared"] } - diff --git a/apps/backend/worker.ts b/apps/backend/worker.ts new file mode 100644 index 0000000..554f329 --- /dev/null +++ b/apps/backend/worker.ts @@ -0,0 +1,10 @@ +import type { ExecutionContext } from '@cloudflare/workers-types' + +export default { + async fetch(request: Request, env: Record, ctx: ExecutionContext) { + ;(globalThis as any).ENV = env + const { createApp } = await import('./src/app') + const app = createApp() + return app.fetch(request, env, ctx) + }, +} diff --git a/apps/backend/wrangler.toml b/apps/backend/wrangler.toml new file mode 100644 index 0000000..55064df --- /dev/null +++ b/apps/backend/wrangler.toml @@ -0,0 +1,32 @@ +name = "freshyo-backend" +main = "worker.ts" +compatibility_date = "2024-12-01" +compatibility_flags = ["nodejs_compat"] + +[vars] +APP_URL = "http://localhost:4000" +JWT_SECRET = "your-jwt-secret" +S3_ACCESS_KEY_ID = "" +S3_SECRET_ACCESS_KEY = "" +S3_BUCKET_NAME = "" +S3_REGION = "" +ASSETS_DOMAIN = "" +API_CACHE_KEY = "" +CLOUDFLARE_API_TOKEN = "" +CLOUDFLARE_ZONE_ID = "" +S3_URL = "" +REDIS_URL = "" +EXPO_ACCESS_TOKEN = "" +PHONE_PE_BASE_URL = "" +PHONE_PE_CLIENT_ID = "" +PHONE_PE_CLIENT_VERSION = "" +PHONE_PE_CLIENT_SECRET = "" +PHONE_PE_MERCHANT_ID = "" +RAZORPAY_KEY = "" +RAZORPAY_SECRET = "" +OTP_SENDER_AUTH_TOKEN = "" +MIN_ORDER_VALUE = "" +DELIVERY_CHARGE = "" +TELEGRAM_BOT_TOKEN = "" +TELEGRAM_CHAT_IDS = "" +ENV_MODE = "dev" diff --git a/bun.lock b/bun.lock index 8083718..a32205e 100644 --- a/bun.lock +++ b/bun.lock @@ -113,35 +113,23 @@ "dependencies": { "@aws-sdk/client-s3": "^3.888.0", "@aws-sdk/s3-request-presigner": "^3.888.0", + "@hono/node-server": "^1.19.11", + "@hono/trpc-server": "^0.4.2", "@trpc/server": "^11.6.0", "@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", - "cors": "^2.8.5", "dayjs": "^1.11.18", "dotenv": "^17.2.1", - "drizzle-orm": "^0.44.5", "expo-server-sdk": "^4.0.0", - "express": "^5.1.0", "fuse.js": "^7.1.0", - "jsonwebtoken": "^9.0.2", - "multer": "^2.0.2", - "node-cron": "^4.2.1", - "pg": "^8.16.3", - "razorpay": "^2.9.6", - "redis": "^5.9.0", + "hono": "^4.12.9", + "jose": "^6.2.2", "zod": "^4.1.12", }, "devDependencies": { - "@types/express": "^5.0.3", "@types/node": "^24.5.2", - "@types/pg": "^8.15.5", - "drizzle-kit": "^0.31.4", "rimraf": "^6.1.2", "ts-node-dev": "^2.0.0", "tsc-alias": "^1.8.16", @@ -288,6 +276,38 @@ "typescript": "^5.9.2", }, }, + "packages/db_helper_sqlite": { + "name": "@packages/db_helper_sqlite", + "version": "1.0.0", + "dependencies": { + "dotenv": "^17.2.1", + "drizzle-orm": "^0.44.5", + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20260304.0", + "@types/node": "^24.5.2", + "drizzle-kit": "^0.31.4", + "tsx": "^4.20.5", + "typescript": "^5.9.2", + }, + }, + "packages/migrator": { + "name": "@packages/migrator", + "version": "1.0.0", + "dependencies": { + "better-sqlite3": "^12.1.0", + "dotenv": "^17.2.1", + "drizzle-orm": "^0.44.5", + "pg": "^8.16.3", + }, + "devDependencies": { + "@types/better-sqlite3": "^7.6.13", + "@types/node": "^24.5.2", + "@types/pg": "^8.15.5", + "tsx": "^4.20.5", + "typescript": "^5.9.2", + }, + }, "packages/shared": { "name": "@packages/shared", "version": "1.0.0", @@ -631,6 +651,8 @@ "@callstack/react-theme-provider": ["@callstack/react-theme-provider@3.0.9", "", { "dependencies": { "deepmerge": "^3.2.0", "hoist-non-react-statics": "^3.3.0" }, "peerDependencies": { "react": ">=16.3.0" } }, "sha512-tTQ0uDSCL0ypeMa8T/E9wAZRGKWj8kXP7+6RYgPTfOPs9N07C9xM8P02GJ3feETap4Ux5S69D9nteq9mEj86NA=="], + "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260317.1", "", {}, "sha512-+G4eVwyCpm8Au1ex8vQBCuA9wnwqetz4tPNRoB/53qvktERWBRMQnrtvC1k584yRE3emMThtuY0gWshvSJ++PQ=="], + "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], "@dimforge/rapier3d-compat": ["@dimforge/rapier3d-compat@0.12.0", "", {}, "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow=="], @@ -767,6 +789,10 @@ "@expo/xcpretty": ["@expo/xcpretty@4.4.1", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-KZNxZvnGCtiM2aYYZ6Wz0Ix5r47dAvpNLApFtZWnSoERzAdOMzVBOPysBoM0JlF6FKWZ8GPqgn6qt3dV/8Zlpg=="], + "@hono/node-server": ["@hono/node-server@1.19.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g=="], + + "@hono/trpc-server": ["@hono/trpc-server@0.4.2", "", { "peerDependencies": { "@trpc/server": "^10.10.0 || >11.0.0-rc", "hono": ">=4.0.0" } }, "sha512-3TDrc42CZLgcTFkXQba+y7JlRWRiyw1AqhLqztWyNS2IFT+3bHld0lxKdGBttCtGKHYx0505dM67RMazjhdZqw=="], + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], @@ -777,8 +803,6 @@ "@ide/backoff": ["@ide/backoff@1.0.0", "", {}, "sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g=="], - "@ioredis/commands": ["@ioredis/commands@1.5.0", "", {}, "sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow=="], - "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], @@ -833,18 +857,6 @@ "@monogrid/gainmap-js": ["@monogrid/gainmap-js@3.4.0", "", { "dependencies": { "promise-worker-transferable": "^1.0.4" }, "peerDependencies": { "three": ">= 0.159.0" } }, "sha512-2Z0FATFHaoYJ8b+Y4y4Hgfn3FRFwuU5zRrk+9dFWp4uGAdHGqVEdP7HP+gLA3X469KXHmfupJaUbKo1b/aDKIg=="], - "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="], - - "@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw=="], - - "@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3", "", { "os": "linux", "cpu": "arm" }, "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw=="], - - "@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg=="], - - "@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg=="], - - "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="], - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -857,6 +869,10 @@ "@packages/db_helper_postgres": ["@packages/db_helper_postgres@workspace:packages/db_helper_postgres"], + "@packages/db_helper_sqlite": ["@packages/db_helper_sqlite@workspace:packages/db_helper_sqlite"], + + "@packages/migrator": ["@packages/migrator@workspace:packages/migrator"], + "@packages/shared": ["@packages/shared@workspace:packages/shared"], "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], @@ -913,16 +929,6 @@ "@react-three/fiber": ["@react-three/fiber@9.5.0", "", { "dependencies": { "@babel/runtime": "^7.17.8", "@types/webxr": "*", "base64-js": "^1.5.1", "buffer": "^6.0.3", "its-fine": "^2.0.0", "react-use-measure": "^2.1.7", "scheduler": "^0.27.0", "suspend-react": "^0.1.3", "use-sync-external-store": "^1.4.0", "zustand": "^5.0.3" }, "peerDependencies": { "expo": ">=43.0", "expo-asset": ">=8.4", "expo-file-system": ">=11.0", "expo-gl": ">=11.0", "react": ">=19 <19.3", "react-dom": ">=19 <19.3", "react-native": ">=0.78", "three": ">=0.156" }, "optionalPeers": ["expo", "expo-asset", "expo-file-system", "expo-gl", "react-dom", "react-native"] }, "sha512-FiUzfYW4wB1+PpmsE47UM+mCads7j2+giRBltfwH7SNhah95rqJs3ltEs9V3pP8rYdS0QlNne+9Aj8dS/SiaIA=="], - "@redis/bloom": ["@redis/bloom@5.11.0", "", { "peerDependencies": { "@redis/client": "^5.11.0" } }, "sha512-KYiVilAhAFN3057afUb/tfYJpsEyTkQB+tQcn5gVVA7DgcNOAj8lLxe4j8ov8BF6I9C1Fe/kwlbuAICcTMX8Lw=="], - - "@redis/client": ["@redis/client@5.11.0", "", { "dependencies": { "cluster-key-slot": "1.1.2" }, "peerDependencies": { "@node-rs/xxhash": "^1.1.0" }, "optionalPeers": ["@node-rs/xxhash"] }, "sha512-GHoprlNQD51Xq2Ztd94HHV94MdFZQ3CVrpA04Fz8MVoHM0B7SlbmPEVIjwTbcv58z8QyjnrOuikS0rWF03k5dQ=="], - - "@redis/json": ["@redis/json@5.11.0", "", { "peerDependencies": { "@redis/client": "^5.11.0" } }, "sha512-1iAy9kAtcD0quB21RbPTbUqqy+T2Uu2JxucwE+B4A+VaDbIRvpZR6DMqV8Iqaws2YxJYB3GC5JVNzPYio2ErUg=="], - - "@redis/search": ["@redis/search@5.11.0", "", { "peerDependencies": { "@redis/client": "^5.11.0" } }, "sha512-g1l7f3Rnyk/xI99oGHIgWHSKFl45Re5YTIcO8j/JE8olz389yUFyz2+A6nqVy/Zi031VgPDWscbbgOk8hlhZ3g=="], - - "@redis/time-series": ["@redis/time-series@5.11.0", "", { "peerDependencies": { "@redis/client": "^5.11.0" } }, "sha512-TWFeOcU4xkj0DkndnOyhtxvX1KWD+78UHT3XX3x3XRBUGWeQrKo3jqzDsZwxbggUgf9yLJr/akFHXru66X5UQA=="], - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="], @@ -1389,24 +1395,16 @@ "@types/bcryptjs": ["@types/bcryptjs@2.4.6", "", {}, "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ=="], - "@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="], + "@types/better-sqlite3": ["@types/better-sqlite3@7.6.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA=="], "@types/canvas-confetti": ["@types/canvas-confetti@1.9.0", "", {}, "sha512-aBGj/dULrimR1XDZLtG9JwxX1b4HPRF6CX9Yfwh3NvstZEm1ZL7RBnel4keCPSqs1ANRu1u2Aoz9R+VmtjYuTg=="], - "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], - - "@types/cors": ["@types/cors@2.8.19", "", { "dependencies": { "@types/node": "*" } }, "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg=="], - "@types/d3-voronoi": ["@types/d3-voronoi@1.1.12", "", {}, "sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw=="], "@types/draco3d": ["@types/draco3d@1.4.10", "", {}, "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], - "@types/express": ["@types/express@5.0.6", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", "@types/serve-static": "^2" } }, "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA=="], - - "@types/express-serve-static-core": ["@types/express-serve-static-core@5.1.1", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A=="], - "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="], "@types/geojson-vt": ["@types/geojson-vt@3.2.5", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g=="], @@ -1419,8 +1417,6 @@ "@types/hoist-non-react-statics": ["@types/hoist-non-react-statics@3.3.7", "", { "dependencies": { "hoist-non-react-statics": "^3.3.0" }, "peerDependencies": { "@types/react": "*" } }, "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g=="], - "@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="], - "@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="], "@types/istanbul-lib-report": ["@types/istanbul-lib-report@3.0.3", "", { "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA=="], @@ -1431,18 +1427,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=="], @@ -1451,10 +1441,6 @@ "@types/pg": ["@types/pg@8.18.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-gT+oueVQkqnj6ajGJXblFR4iavIXWsGAFCk3dP4Kki5+a9R4NMt0JARdk6s8cUKcfUoqP5dAtDSLU8xYUTFV+Q=="], - "@types/qs": ["@types/qs@6.15.0", "", {}, "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow=="], - - "@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="], - "@types/react": ["@types/react@19.0.14", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-ixLZ7zG7j1fM0DijL9hDArwhwcCb4vqmePgwtV0GfnkHRSCUEv4LvzarcTdhoqgyMznUx/EhoTUv31CKZzkQlw=="], "@types/react-dom": ["@types/react-dom@19.0.6", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-lo6MuY+rFr8kIiFnr+7TzO+Av0wUPcEcepiPV4epGP0eTQpkDfp9czudg73isV8UxKauCUNlL1N8fXhcnx4iBw=="], @@ -1463,10 +1449,6 @@ "@types/react-reconciler": ["@types/react-reconciler@0.28.9", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg=="], - "@types/send": ["@types/send@1.2.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ=="], - - "@types/serve-static": ["@types/serve-static@2.2.0", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*" } }, "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ=="], - "@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="], "@types/stats.js": ["@types/stats.js@0.17.4", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="], @@ -1559,7 +1541,7 @@ "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], - "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], + "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], @@ -1585,8 +1567,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=="], @@ -1671,6 +1651,8 @@ "better-opn": ["better-opn@3.0.2", "", { "dependencies": { "open": "^8.0.4" } }, "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ=="], + "better-sqlite3": ["better-sqlite3@12.8.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ=="], + "bidi-js": ["bidi-js@1.0.3", "", { "dependencies": { "require-from-string": "^2.0.2" } }, "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw=="], "big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="], @@ -1679,7 +1661,11 @@ "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], - "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], + "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="], + + "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], + + "body-parser": ["body-parser@1.20.4", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.14.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA=="], "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], @@ -1699,14 +1685,8 @@ "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=="], @@ -1759,8 +1739,6 @@ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], - "cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="], - "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], @@ -1781,15 +1759,13 @@ "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=="], "constantinople": ["constantinople@4.0.1", "", { "dependencies": { "@babel/parser": "^7.6.0", "@babel/types": "^7.6.1" } }, "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw=="], - "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="], + "content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -1799,20 +1775,16 @@ "cookie-es": ["cookie-es@2.0.0", "", {}, "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg=="], - "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], + "cookie-signature": ["cookie-signature@1.0.7", "", {}, "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="], "copy-anything": ["copy-anything@4.0.5", "", { "dependencies": { "is-what": "^5.2.0" } }, "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA=="], "core-js-compat": ["core-js-compat@3.48.0", "", { "dependencies": { "browserslist": "^4.28.1" } }, "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q=="], - "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="], - "cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="], "create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="], - "cron-parser": ["cron-parser@4.9.0", "", { "dependencies": { "luxon": "^3.2.1" } }, "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q=="], - "cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="], "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], @@ -1853,6 +1825,8 @@ "decode-uri-component": ["decode-uri-component@0.2.2", "", {}, "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="], + "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], + "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], @@ -1869,15 +1843,13 @@ "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], - "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="], - "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], "detect-gpu": ["detect-gpu@5.0.70", "", { "dependencies": { "webgl-constants": "^1.1.1" } }, "sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w=="], - "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], @@ -1917,8 +1889,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=="], @@ -1927,6 +1897,8 @@ "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], + "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "env-editor": ["env-editor@0.4.2", "", {}, "sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA=="], @@ -2003,6 +1975,8 @@ "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], + "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], + "expo": ["expo@53.0.27", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "0.24.24", "@expo/config": "~11.0.13", "@expo/config-plugins": "~10.1.2", "@expo/fingerprint": "0.13.4", "@expo/metro-config": "0.20.18", "@expo/vector-icons": "^14.0.0", "babel-preset-expo": "~13.2.5", "expo-asset": "~11.1.7", "expo-constants": "~17.1.8", "expo-file-system": "~18.1.11", "expo-font": "~13.3.2", "expo-keep-awake": "~14.1.4", "expo-modules-autolinking": "2.1.15", "expo-modules-core": "2.5.0", "react-native-edge-to-edge": "1.6.0", "whatwg-url-without-unicode": "8.0.0-3" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-iQwe2uWLb88opUY4vBYEW1d2GUq3lsa43gsMBEdDV+6pw0Oek93l/4nDLe0ODDdrBRjIJm/rdhKqJC/ehHCUqw=="], "expo-application": ["expo-application@6.1.5", "", { "peerDependencies": { "expo": "*" } }, "sha512-ToImFmzw8luY043pWFJhh2ZMm4IwxXoHXxNoGdlhD4Ym6+CCmkAvCglg0FK8dMLzAb+/XabmOE7Rbm8KZb6NZg=="], @@ -2085,7 +2059,7 @@ "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="], - "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], + "express": ["express@4.22.1", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "~1.20.3", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.3.1", "fresh": "~0.5.2", "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", "serve-static": "~1.16.2", "setprototypeof": "1.2.0", "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g=="], "fallback-ui": ["fallback-ui@workspace:apps/fallback-ui"], @@ -2115,11 +2089,13 @@ "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + "file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="], + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "filter-obj": ["filter-obj@1.1.0", "", {}, "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="], - "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], + "finalhandler": ["finalhandler@1.3.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "statuses": "~2.0.2", "unpipe": "~1.0.0" } }, "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg=="], "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], @@ -2147,7 +2123,9 @@ "freeport-async": ["freeport-async@2.0.0", "", {}, "sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ=="], - "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], + "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], + + "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], @@ -2189,6 +2167,8 @@ "getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="], + "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="], + "gl-matrix": ["gl-matrix@3.4.4", "", {}, "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ=="], "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], @@ -2233,6 +2213,8 @@ "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], + "hono": ["hono@4.12.9", "", {}, "sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA=="], + "hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], @@ -2241,7 +2223,7 @@ "hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="], - "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], + "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], @@ -2267,8 +2249,6 @@ "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="], - "ioredis": ["ioredis@5.9.3", "", { "dependencies": { "@ioredis/commands": "1.5.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-VI5tMCdeoxZWU5vjHWsiE/Su76JGhBvWF1MJnV9ZtGltHk9BmD48oDq8Tj8haZ85aceXZMxLNDQZRVo5QKNgXA=="], - "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "is-arguments": ["is-arguments@1.2.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA=="], @@ -2321,7 +2301,7 @@ "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], - "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="], + "is-promise": ["is-promise@2.2.2", "", {}, "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="], "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], @@ -2383,6 +2363,8 @@ "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], + "jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="], + "js-stringify": ["js-stringify@1.0.2", "", {}, "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g=="], "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], @@ -2405,18 +2387,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=="], @@ -2471,26 +2447,8 @@ "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], - "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=="], @@ -2499,8 +2457,6 @@ "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - "luxon": ["luxon@3.7.2", "", {}, "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew=="], - "maath": ["maath@0.10.8", "", { "peerDependencies": { "@types/three": ">=0.134.0", "three": ">=0.134.0" } }, "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g=="], "make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="], @@ -2515,11 +2471,11 @@ "mdn-data": ["mdn-data@2.0.14", "", {}, "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="], - "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], + "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], "memoize-one": ["memoize-one@5.2.1", "", {}, "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="], - "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="], + "merge-descriptors": ["merge-descriptors@1.0.3", "", {}, "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="], "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], @@ -2563,12 +2519,14 @@ "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="], + "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], + "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], @@ -2579,14 +2537,10 @@ "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "msgpackr": ["msgpackr@1.11.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA=="], - - "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=="], @@ -2595,15 +2549,17 @@ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], + "napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="], "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], "nested-error-stacks": ["nested-error-stacks@2.0.1", "", {}, "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A=="], - "node-abort-controller": ["node-abort-controller@3.1.1", "", {}, "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ=="], + "node-abi": ["node-abi@3.89.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA=="], "node-cron": ["node-cron@4.2.1", "", {}, "sha512-lgimEHPE/QDgFlywTd8yTR61ptugX3Qer29efeyWw2rv259HtGBNn1vZVmp8lB9uo9wC0t/AT4iGqXxia+CJFg=="], @@ -2613,8 +2569,6 @@ "node-forge": ["node-forge@1.3.3", "", {}, "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg=="], - "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="], - "node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="], "node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="], @@ -2761,6 +2715,8 @@ "potpack": ["potpack@2.1.0", "", {}, "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ=="], + "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], "pretty-bytes": ["pretty-bytes@5.6.0", "", {}, "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg=="], @@ -2815,11 +2771,13 @@ "pug-walk": ["pug-walk@2.0.0", "", {}, "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ=="], + "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "qrcode-terminal": ["qrcode-terminal@0.11.0", "", { "bin": { "qrcode-terminal": "./bin/qrcode-terminal.js" } }, "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ=="], - "qs": ["qs@6.15.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ=="], + "qs": ["qs@6.14.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q=="], "query-string": ["query-string@7.1.3", "", { "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", "split-on-first": "^1.0.0", "strict-uri-encode": "^2.0.0" } }, "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg=="], @@ -2833,9 +2791,7 @@ "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], - "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], - - "razorpay": ["razorpay@2.9.6", "", { "dependencies": { "axios": "^1.6.8" } }, "sha512-zsHAQzd6e1Cc6BNoCNZQaf65ElL6O6yw0wulxmoG5VQDr363fZC90Mp1V5EktVzG45yPyNomNXWlf4cQ3622gQ=="], + "raw-body": ["raw-body@2.5.3", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "unpipe": "~1.0.0" } }, "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA=="], "rbush": ["rbush@3.0.1", "", { "dependencies": { "quickselect": "^2.0.0" } }, "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w=="], @@ -2907,12 +2863,6 @@ "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=="], - - "redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="], - - "redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="], - "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="], @@ -2959,8 +2909,6 @@ "rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="], - "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], - "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="], @@ -2981,7 +2929,7 @@ "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], + "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], "serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], @@ -2989,7 +2937,7 @@ "seroval-plugins": ["seroval-plugins@1.5.1", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-4FbuZ/TMl02sqv0RTFexu0SP6V+ywaIe5bAWCCEik0fk17BhALgwvUDVF7e3Uvf9pxmwCEJsRPmlkUE6HdzLAw=="], - "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="], + "serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], "server-only": ["server-only@0.0.1", "", {}, "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="], @@ -3023,6 +2971,10 @@ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="], + + "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="], + "simple-plist": ["simple-plist@1.3.1", "", { "dependencies": { "bplist-creator": "0.1.0", "bplist-parser": "0.3.1", "plist": "^3.0.5" } }, "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw=="], "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], @@ -3057,8 +3009,6 @@ "stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="], - "standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="], - "stats-gl": ["stats-gl@2.4.2", "", { "dependencies": { "@types/three": "*", "three": "^0.170.0" } }, "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ=="], "stats.js": ["stats.js@0.17.0", "", {}, "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw=="], @@ -3069,8 +3019,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=="], @@ -3129,6 +3077,10 @@ "tar": ["tar@7.5.11", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ=="], + "tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="], + + "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], + "temp-dir": ["temp-dir@2.0.0", "", {}, "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg=="], "terminal-link": ["terminal-link@2.1.1", "", { "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" } }, "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ=="], @@ -3201,6 +3153,8 @@ "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="], + "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], + "tunnel-rat": ["tunnel-rat@0.1.2", "", { "dependencies": { "zustand": "^4.3.2" } }, "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ=="], "turbo": ["turbo@2.8.17", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.17", "turbo-darwin-arm64": "2.8.17", "turbo-linux-64": "2.8.17", "turbo-linux-arm64": "2.8.17", "turbo-windows-64": "2.8.17", "turbo-windows-arm64": "2.8.17" }, "bin": { "turbo": "bin/turbo" } }, "sha512-YwPsNSqU2f/RXU/+Kcb7cPkPZARxom4+me7LKEdN5jsvy2tpfze3zDZ4EiGrJnvOm9Avu9rK0aaYsP7qZ3iz7A=="], @@ -3225,7 +3179,7 @@ "type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], - "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], + "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], @@ -3235,8 +3189,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=="], @@ -3279,7 +3231,7 @@ "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], - "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "uuid": ["uuid@7.0.3", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="], "v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="], @@ -3383,8 +3335,6 @@ "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], - "@expo/cli/accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], - "@expo/cli/arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], "@expo/cli/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], @@ -3395,8 +3345,6 @@ "@expo/cli/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], - "@expo/cli/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], - "@expo/cli/undici": ["undici@6.24.1", "", {}, "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA=="], "@expo/cli/ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], @@ -3459,14 +3407,20 @@ "@packages/db_helper_postgres/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "@packages/db_helper_sqlite/drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="], + + "@packages/db_helper_sqlite/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "@packages/migrator/drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="], + + "@packages/migrator/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "@react-native/community-cli-plugin/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "@react-native/community-cli-plugin/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "@react-native/dev-middleware/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "@react-native/dev-middleware/serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], - "@react-navigation/core/react-is": ["react-is@19.2.4", "", {}, "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA=="], "@turf/tesselate/earcut": ["earcut@2.2.4", "", {}, "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="], @@ -3485,15 +3439,15 @@ "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "backend/drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="], - "backend/expo-server-sdk": ["expo-server-sdk@4.0.0", "", { "dependencies": { "node-fetch": "^2.6.0", "promise-limit": "^2.7.0", "promise-retry": "^2.0.1" } }, "sha512-zi83XtG2pqyP3gyn1JIRYkydo2i6HU3CYaWo/VvhZG/F29U+QIDv6LBEUsWf4ddZlVE7c9WN1N8Be49rHgO8OQ=="], "backend/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], "better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], - "bullmq/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + "bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + + "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "caller-callsite/callsites": ["callsites@2.0.0", "", {}, "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ=="], @@ -3505,6 +3459,8 @@ "common-ui/react-native-pager-view": ["react-native-pager-view@6.9.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-uUT0MMMbNtoSbxe9pRvdJJKEi9snjuJ3fXlZhG8F2vVMOBJVt/AFtqMPUHu9yMflmqOr08PewKzj9EPl/Yj+Gw=="], + "compressible/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "compression/negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], @@ -3547,6 +3503,8 @@ "expo-updates/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], + "express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + "fallback-ui/@types/node": ["@types/node@20.19.37", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw=="], "fallback-ui/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -3557,7 +3515,7 @@ "fbjs/ua-parser-js": ["ua-parser-js@1.0.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug=="], - "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "formik/react-fast-compare": ["react-fast-compare@2.0.4", "", {}, "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="], @@ -3581,33 +3539,25 @@ "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=="], "lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "log-symbols/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], + "lightningcss/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], - "metro/accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + "log-symbols/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], "metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], "metro/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="], - "metro/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], "metro-babel-transformer/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="], "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=="], + "node-abi/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "npm-package-arg/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], @@ -3617,8 +3567,6 @@ "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], - "promise-worker-transferable/is-promise": ["is-promise@2.2.2", "", {}, "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="], - "prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], "rbush/quickselect": ["quickselect@2.0.0", "", {}, "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="], @@ -3653,7 +3601,7 @@ "rimraf/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], - "router/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], + "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "simple-plist/bplist-parser": ["bplist-parser@0.3.1", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA=="], @@ -3677,12 +3625,12 @@ "sweepline-intersections/tinyqueue": ["tinyqueue@2.0.3", "", {}, "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA=="], - "symbuyote-info-site/express": ["express@4.22.1", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "~1.20.3", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.3.1", "fresh": "~0.5.2", "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", "serve-static": "~1.16.2", "setprototypeof": "1.2.0", "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g=="], - "tailwindcss/arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], "tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], + "tar-fs/chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="], + "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "three-stdlib/fflate": ["fflate@0.6.10", "", {}, "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg=="], @@ -3717,8 +3665,6 @@ "write-file-atomic/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - "xcode/uuid": ["uuid@7.0.3", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="], - "xml2js/xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], "@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], @@ -3777,16 +3723,8 @@ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], - "@expo/cli/accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - - "@expo/cli/accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], - "@expo/cli/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "@expo/cli/send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "@expo/cli/send/fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], - "@expo/config-plugins/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], "@expo/config/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], @@ -3809,10 +3747,10 @@ "@react-native/dev-middleware/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "@react-native/dev-middleware/serve-static/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], + "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], @@ -3833,9 +3771,11 @@ "expo-updates/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "fallback-ui/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "geojson-polygon-self-intersections/rbush/quickselect": ["quickselect@1.1.1", "", {}, "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ=="], @@ -3851,16 +3791,8 @@ "metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="], - "metro/accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], - "metro/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="], - "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=="], @@ -3873,32 +3805,10 @@ "rimraf/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], + "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "sucrase/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - "symbuyote-info-site/express/accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], - - "symbuyote-info-site/express/body-parser": ["body-parser@1.20.4", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.14.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA=="], - - "symbuyote-info-site/express/content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], - - "symbuyote-info-site/express/cookie-signature": ["cookie-signature@1.0.7", "", {}, "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="], - - "symbuyote-info-site/express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "symbuyote-info-site/express/finalhandler": ["finalhandler@1.3.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "statuses": "~2.0.2", "unpipe": "~1.0.0" } }, "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg=="], - - "symbuyote-info-site/express/fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], - - "symbuyote-info-site/express/merge-descriptors": ["merge-descriptors@1.0.3", "", {}, "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="], - - "symbuyote-info-site/express/qs": ["qs@6.14.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q=="], - - "symbuyote-info-site/express/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], - - "symbuyote-info-site/express/serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], - - "symbuyote-info-site/express/type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], - "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="], "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="], @@ -3961,18 +3871,12 @@ "@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], - "@expo/cli/accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - - "@expo/cli/send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "@expo/config-plugins/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "@expo/config/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], - "@react-native/dev-middleware/serve-static/send/fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], - "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "expo-modules-autolinking/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], @@ -3983,8 +3887,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=="], @@ -3997,20 +3899,6 @@ "sucrase/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "symbuyote-info-site/express/accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - - "symbuyote-info-site/express/accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], - - "symbuyote-info-site/express/body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], - - "symbuyote-info-site/express/body-parser/raw-body": ["raw-body@2.5.3", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "unpipe": "~1.0.0" } }, "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA=="], - - "symbuyote-info-site/express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "symbuyote-info-site/express/type-is/media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], - - "symbuyote-info-site/express/type-is/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], @@ -4020,9 +3908,5 @@ "ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - - "symbuyote-info-site/express/accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - - "symbuyote-info-site/express/type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], } } diff --git a/packages/db_helper_sqlite/src/admin-apis/coupon.ts b/packages/db_helper_sqlite/src/admin-apis/coupon.ts index fb2e4b4..9b917d4 100644 --- a/packages/db_helper_sqlite/src/admin-apis/coupon.ts +++ b/packages/db_helper_sqlite/src/admin-apis/coupon.ts @@ -487,7 +487,7 @@ export async function getUsersForCoupon( }) return { - users: userList.map((user: typeof users.$inferSelect) => ({ + users: userList.map((user) => ({ id: user.id, name: user.name || 'Unknown', mobile: user.mobile, diff --git a/packages/db_helper_sqlite/src/admin-apis/order.ts b/packages/db_helper_sqlite/src/admin-apis/order.ts index d990219..343a972 100644 --- a/packages/db_helper_sqlite/src/admin-apis/order.ts +++ b/packages/db_helper_sqlite/src/admin-apis/order.ts @@ -143,7 +143,7 @@ export async function getOrderDetails(orderId: number): Promise 0) { let totalDiscountAmount = 0 - const orderTotal = parseFloat(orderData.totalAmount.toString()) + const orderTotal = parseFloat((orderData.totalAmount ?? '0').toString()) for (const usage of couponUsageData) { let discountAmount = 0 diff --git a/packages/db_helper_sqlite/src/user-apis/order.ts b/packages/db_helper_sqlite/src/user-apis/order.ts index 2d248ad..6e54317 100644 --- a/packages/db_helper_sqlite/src/user-apis/order.ts +++ b/packages/db_helper_sqlite/src/user-apis/order.ts @@ -407,7 +407,7 @@ export async function getOrdersWithRelations( }, }, }, - orderBy: (ordersTable: typeof orders) => [desc(ordersTable.createdAt)], + orderBy: [desc(orders.createdAt)], limit: pageSize, offset: offset, }) as Promise diff --git a/packages/migrated.db b/packages/migrated.db new file mode 100644 index 0000000000000000000000000000000000000000..dac38382770aff374b925ad19cc58cb4a14e15f5 GIT binary patch literal 12288 zcmeI#O>fgM7zc1WX~TMez-gyRUc@A-y(sYtDw8G%BUF>JuC%T|aHzc2-6Ew;l%!~! z5aP_817C;>UxPcB9RLXzC@P?wxJ`d6j-S}^WBYe=?{OFvij9+OA`7-lt`kbheZ~kO zmae9*i(=@YviQ&~U5d*>i|oApa#fES*FF&2(JvGTKmY;|fB*y_009U<00Izz!2bw5 zF|5^%4VoA7BvysWi$SK+I2y|3*gWV4z6hA`AA|vOmWLd6%ZWw~J8X-f6?9qqSg>|K z4C}9-(<`fMYxGU+N9r_7Mzdj&FIwZzl#A}NbX&}s%87EA2%hQ%el4PV(<~b5ZoR*7 zxm&)FQ9M7=zdK_OgGYWp6l^TxT+Aox7Yr+p1V}-K_0bj;E><&vNE*^6gXE->zxVx?aF+ zCCO>5SSLDHF>BHrN!g5sVNp-#H+piC&-9jBGM48rS&uj9&5N>GF12c#dX}H2dX?zs zF}&Nf`KoNj{Qhs+pNaj|zR(Q{1Rwwb2tWV=5P$##AOHafKmY=lLclZ)s;fcgPwhK( C*{8e! literal 0 HcmV?d00001 diff --git a/packages/migrator/README.md b/packages/migrator/README.md new file mode 100644 index 0000000..6ceb8bd --- /dev/null +++ b/packages/migrator/README.md @@ -0,0 +1,84 @@ +# @packages/migrator + +Database migration tool for moving data between PostgreSQL and SQLite. + +## Setup + +Install dependencies: +```bash +npm install +``` + +## Configuration + +Edit `src/config.ts` directly to configure database settings: + +```typescript +// PostgreSQL Configuration +export const postgresConfig = { + connectionString: 'postgresql://postgres:postgres@localhost:5432/freshyo', + ssl: false, +}; + +// SQLite Configuration +export const sqliteConfig = { + filename: './data/migrated.db', +}; + +// Migration Settings +export const migrationConfig = { + batchSize: 1000, // Rows per batch + truncateBeforeInsert: true, // Clear tables before migration + excludedTables: [], // Tables to skip + includedTables: [], // Tables to include (empty = all) +}; + +// Logging +export const logConfig = { + verbose: true, + logFile: './migration.log', +}; +``` + +## Usage + +### PostgreSQL to SQLite + +Migrate data from PostgreSQL to SQLite: + +```bash +npm run migrate:pg-to-sqlite +``` + +### SQLite to PostgreSQL + +Migrate data from SQLite to PostgreSQL: + +```bash +npm run migrate:sqlite-to-pg +``` + +### Full Cycle (Testing) + +Run both migrations in sequence: + +```bash +npm run migrate:full-cycle +``` + +## Features + +- ✅ Automatic schema conversion between PostgreSQL and SQLite +- ✅ Batch processing for large datasets +- ✅ Type mapping between databases +- ✅ JSON/array handling +- ✅ Configurable table filtering +- ✅ Progress logging +- ✅ Transaction support + +## Notes + +- Arrays and JSON data are stored as TEXT in SQLite and parsed back when migrating to PostgreSQL +- Date/timestamps are stored as ISO strings in SQLite +- Foreign key constraints are enabled in SQLite +- Edit `src/config.ts` to change any settings diff --git a/packages/migrator/data/migrated.db b/packages/migrator/data/migrated.db new file mode 100644 index 0000000000000000000000000000000000000000..dac38382770aff374b925ad19cc58cb4a14e15f5 GIT binary patch literal 12288 zcmeI#O>fgM7zc1WX~TMez-gyRUc@A-y(sYtDw8G%BUF>JuC%T|aHzc2-6Ew;l%!~! z5aP_817C;>UxPcB9RLXzC@P?wxJ`d6j-S}^WBYe=?{OFvij9+OA`7-lt`kbheZ~kO zmae9*i(=@YviQ&~U5d*>i|oApa#fES*FF&2(JvGTKmY;|fB*y_009U<00Izz!2bw5 zF|5^%4VoA7BvysWi$SK+I2y|3*gWV4z6hA`AA|vOmWLd6%ZWw~J8X-f6?9qqSg>|K z4C}9-(<`fMYxGU+N9r_7Mzdj&FIwZzl#A}NbX&}s%87EA2%hQ%el4PV(<~b5ZoR*7 zxm&)FQ9M7=zdK_OgGYWp6l^TxT+Aox7Yr+p1V}-K_0bj;E><&vNE*^6gXE->zxVx?aF+ zCCO>5SSLDHF>BHrN!g5sVNp-#H+piC&-9jBGM48rS&uj9&5N>GF12c#dX}H2dX?zs zF}&Nf`KoNj{Qhs+pNaj|zR(Q{1Rwwb2tWV=5P$##AOHafKmY=lLclZ)s;fcgPwhK( C*{8e! literal 0 HcmV?d00001 diff --git a/packages/migrator/package.json b/packages/migrator/package.json new file mode 100644 index 0000000..0eb9da3 --- /dev/null +++ b/packages/migrator/package.json @@ -0,0 +1,26 @@ +{ + "name": "@packages/migrator", + "version": "1.0.0", + "description": "Database migration tool between PostgreSQL and SQLite", + "main": "index.ts", + "types": "index.ts", + "private": true, + "scripts": { + "migrate:pg-to-sqlite": "tsx src/postgresToSqlite/index.ts", + "migrate:sqlite-to-pg": "tsx src/sqliteToPostgres/index.ts", + "migrate:full-cycle": "npm run migrate:pg-to-sqlite && npm run migrate:sqlite-to-pg" + }, + "dependencies": { + "better-sqlite3": "^12.1.0", + "dotenv": "^17.2.1", + "drizzle-orm": "^0.44.5", + "pg": "^8.16.3" + }, + "devDependencies": { + "@types/better-sqlite3": "^7.6.13", + "@types/node": "^24.5.2", + "@types/pg": "^8.15.5", + "tsx": "^4.20.5", + "typescript": "^5.9.2" + } +} diff --git a/packages/migrator/src/config.ts b/packages/migrator/src/config.ts new file mode 100644 index 0000000..ef854e2 --- /dev/null +++ b/packages/migrator/src/config.ts @@ -0,0 +1,36 @@ +/** + * Database migration configuration + * Edit this file directly to configure migration settings + */ + +// PostgreSQL Configuration +export const postgresConfig = { + connectionString: 'postgresql://postgres:meatfarmer_master_password@57.128.212.174:7447/meatfarmer', + ssl: false as boolean | { rejectUnauthorized: boolean }, +}; + +// SQLite Configuration +export const sqliteConfig = { + filename: './data/migrated.db', +}; + +// Migration Settings +export const migrationConfig = { + // Batch size for bulk inserts (to avoid memory issues) + batchSize: 1000, + + // Enable/disable table truncation before migration + truncateBeforeInsert: true, + + // Tables to exclude from migration + excludedTables: [] as string[], + + // Tables to include (if empty, includes all) + includedTables: [] as string[], +}; + +// Logging +export const logConfig = { + verbose: true, + logFile: './migration.log', +}; diff --git a/packages/migrator/src/postgresToSqlite/index.ts b/packages/migrator/src/postgresToSqlite/index.ts new file mode 100644 index 0000000..6f2a52a --- /dev/null +++ b/packages/migrator/src/postgresToSqlite/index.ts @@ -0,0 +1,288 @@ +import { Client } from 'pg'; +import Database from 'better-sqlite3'; +import { postgresConfig, sqliteConfig, migrationConfig, logConfig } from '../config'; +import * as fs from 'fs'; +import * as path from 'path'; + +interface TableInfo { + tableName: string; + columns: ColumnInfo[]; +} + +interface ColumnInfo { + name: string; + type: string; + isNullable: boolean; + defaultValue: string | null; +} + +/** + * Maps PostgreSQL data types to SQLite data types + */ +function mapPostgresTypeToSqlite(pgType: string): string { + const typeMap: Record = { + 'bigint': 'INTEGER', + 'bigserial': 'INTEGER', + 'boolean': 'INTEGER', + 'character': 'TEXT', + 'character varying': 'TEXT', + 'date': 'TEXT', + 'double precision': 'REAL', + 'integer': 'INTEGER', + 'json': 'TEXT', + 'jsonb': 'TEXT', + 'numeric': 'REAL', + 'real': 'REAL', + 'serial': 'INTEGER', + 'smallint': 'INTEGER', + 'text': 'TEXT', + 'timestamp with time zone': 'TEXT', + 'timestamp without time zone': 'TEXT', + 'uuid': 'TEXT', + 'ARRAY': 'TEXT', // Arrays stored as JSON text + }; + + // Check for array types + if (pgType.endsWith('[]')) { + return 'TEXT'; + } + + return typeMap[pgType] || 'TEXT'; +} + +/** + * Gets all table names from PostgreSQL + */ +async function getPostgresTables(client: Client): Promise { + const result = await client.query(` + SELECT table_name + FROM information_schema.tables + WHERE table_schema = 'public' + AND table_type = 'BASE TABLE' + ORDER BY table_name + `); + + return result.rows.map(row => row.table_name); +} + +/** + * Gets column information for a specific table + */ +async function getTableColumns(client: Client, tableName: string): Promise { + const result = await client.query(` + SELECT + column_name, + data_type, + is_nullable, + column_default + FROM information_schema.columns + WHERE table_name = $1 + AND table_schema = 'public' + ORDER BY ordinal_position + `, [tableName]); + + return result.rows.map(row => ({ + name: row.column_name, + type: row.data_type, + isNullable: row.is_nullable === 'YES', + defaultValue: row.column_default, + })); +} + +/** + * Creates SQLite table based on PostgreSQL schema + */ +function createSqliteTable(db: Database.Database, tableName: string, columns: ColumnInfo[]): void { + const columnDefs = columns.map(col => { + let def = `"${col.name}" ${mapPostgresTypeToSqlite(col.type)}`; + if (!col.isNullable) { + def += ' NOT NULL'; + } + if (col.defaultValue !== null) { + // Convert PostgreSQL default values to SQLite + let defaultVal = col.defaultValue; + if (defaultVal.includes('nextval')) { + // Skip auto-increment defaults, SQLite handles this with INTEGER PRIMARY KEY + } else if (defaultVal === 'now()' || defaultVal.includes('CURRENT_TIMESTAMP')) { + def += ` DEFAULT CURRENT_TIMESTAMP`; + } else { + def += ` DEFAULT ${defaultVal}`; + } + } + return def; + }).join(', '); + + const createSql = `CREATE TABLE IF NOT EXISTS "${tableName}" (${columnDefs})`; + + if (logConfig.verbose) { + console.log(`Creating table: ${tableName}`); + console.log(createSql); + } + + db.exec(createSql); +} + +/** + * Migrates data from PostgreSQL to SQLite + */ +async function migrateTableData( + pgClient: Client, + sqliteDb: Database.Database, + tableName: string, + columns: ColumnInfo[] +): Promise { + // Check if table should be excluded + if (migrationConfig.excludedTables.includes(tableName)) { + console.log(`Skipping excluded table: ${tableName}`); + return 0; + } + + // Check if only specific tables should be included + if (migrationConfig.includedTables.length > 0 && !migrationConfig.includedTables.includes(tableName)) { + console.log(`Skipping table not in include list: ${tableName}`); + return 0; + } + + console.log(`Migrating table: ${tableName}`); + + // Get total count first + const countResult = await pgClient.query(`SELECT COUNT(*) FROM "${tableName}"`); + const totalRows = parseInt(countResult.rows[0].count); + console.log(` Total rows to migrate: ${totalRows}`); + + if (totalRows === 0) { + console.log(` No data to migrate`); + return 0; + } + + // Clear existing data if configured + if (migrationConfig.truncateBeforeInsert) { + sqliteDb.exec(`DELETE FROM "${tableName}"`); + console.log(` Cleared existing data`); + } + + // Get column names + const columnNames = columns.map(c => `"${c.name}"`).join(', '); + const placeholders = columns.map(() => '?').join(', '); + const insertStmt = sqliteDb.prepare(`INSERT INTO "${tableName}" (${columnNames}) VALUES (${placeholders})`); + + let migratedCount = 0; + let offset = 0; + + while (offset < totalRows) { + const result = await pgClient.query( + `SELECT * FROM "${tableName}" ORDER BY 1 LIMIT $1 OFFSET $2`, + [migrationConfig.batchSize, offset] + ); + + const insertMany = sqliteDb.transaction((rows) => { + for (const row of rows) { + const values = columns.map(col => { + const val = row[col.name]; + // Handle special cases + if (val === null || val === undefined) return null; + if (typeof val === 'boolean') return val ? 1 : 0; + if (val instanceof Date) return val.toISOString(); + if (Array.isArray(val)) return JSON.stringify(val); + if (typeof val === 'object') return JSON.stringify(val); + // Ensure it's a primitive type SQLite can handle + if (typeof val === 'number') return val; + if (typeof val === 'bigint') return Number(val); + return String(val); + }); + insertStmt.run(values); + } + }); + + insertMany(result.rows); + migratedCount += result.rows.length; + offset += migrationConfig.batchSize; + + if (logConfig.verbose || offset % 10000 === 0) { + console.log(` Progress: ${migratedCount}/${totalRows} rows`); + } + } + + console.log(` Completed: ${migratedCount} rows migrated`); + return migratedCount; +} + +/** + * Main migration function + */ +async function migratePostgresToSqlite(): Promise { + console.log('Starting PostgreSQL to SQLite migration...\n'); + + // Ensure SQLite directory exists + const sqliteDir = path.dirname(sqliteConfig.filename); + if (!fs.existsSync(sqliteDir)) { + fs.mkdirSync(sqliteDir, { recursive: true }); + } + + // Remove existing SQLite file if starting fresh + if (migrationConfig.truncateBeforeInsert && fs.existsSync(sqliteConfig.filename)) { + fs.unlinkSync(sqliteConfig.filename); + console.log('Removed existing SQLite database'); + } + + // Connect to PostgreSQL + const pgClient = new Client(postgresConfig); + await pgClient.connect(); + console.log('Connected to PostgreSQL'); + + // Connect to SQLite + const sqliteDb = new Database(sqliteConfig.filename); + console.log('Connected to SQLite'); + + // Enable foreign keys + sqliteDb.exec('PRAGMA foreign_keys = ON'); + + try { + // Get all tables + const tables = await getPostgresTables(pgClient); + console.log(`\nFound ${tables.length} tables to migrate\n`); + + let totalMigrated = 0; + + // Migrate each table + for (const tableName of tables) { + try { + const columns = await getTableColumns(pgClient, tableName); + + // Create table in SQLite + createSqliteTable(sqliteDb, tableName, columns); + + // Migrate data + const migrated = await migrateTableData(pgClient, sqliteDb, tableName, columns); + totalMigrated += migrated; + + console.log(''); + } catch (error) { + console.error(`Error migrating table ${tableName}:`, error); + if (logConfig.verbose) { + throw error; + } + } + } + + console.log('================================='); + console.log('Migration completed successfully!'); + console.log(`Total rows migrated: ${totalMigrated}`); + console.log(`SQLite database: ${sqliteConfig.filename}`); + console.log('================================='); + + } catch (error) { + console.error('Migration failed:', error); + throw error; + } finally { + await pgClient.end(); + sqliteDb.close(); + } +} + +// Run migration if called directly +if (require.main === module) { + migratePostgresToSqlite().catch(console.error); +} + +export { migratePostgresToSqlite }; diff --git a/packages/migrator/src/sqliteToPostgres/index.ts b/packages/migrator/src/sqliteToPostgres/index.ts new file mode 100644 index 0000000..73fe860 --- /dev/null +++ b/packages/migrator/src/sqliteToPostgres/index.ts @@ -0,0 +1,273 @@ +import { Client } from 'pg'; +import Database from 'better-sqlite3'; +import { postgresConfig, sqliteConfig, migrationConfig, logConfig } from '../config'; + +interface TableInfo { + tableName: string; + columns: ColumnInfo[]; +} + +interface ColumnInfo { + name: string; + type: string; + notNull: boolean; + defaultValue: string | null; + primaryKey: boolean; +} + +/** + * Maps SQLite data types back to PostgreSQL data types + * This is a best-effort mapping and may need adjustment based on specific use cases + */ +function mapSqliteTypeToPostgres(sqliteType: string): string { + const typeMap: Record = { + 'INTEGER': 'INTEGER', + 'REAL': 'DOUBLE PRECISION', + 'TEXT': 'TEXT', + 'BLOB': 'BYTEA', + 'NUMERIC': 'NUMERIC', + }; + + return typeMap[sqliteType.toUpperCase()] || 'TEXT'; +} + +/** + * Gets all table names from SQLite + */ +function getSqliteTables(db: Database.Database): string[] { + const result = db.prepare(` + SELECT name FROM sqlite_master + WHERE type = 'table' + AND name NOT LIKE 'sqlite_%' + ORDER BY name + `).all() as { name: string }[]; + + return result.map(row => row.name); +} + +/** + * Gets column information for a specific table from SQLite + */ +function getSqliteTableColumns(db: Database.Database, tableName: string): ColumnInfo[] { + const result = db.prepare(`PRAGMA table_info("${tableName}")`).all() as any[]; + + return result.map(row => ({ + name: row.name, + type: row.type, + notNull: row.notnull === 1, + defaultValue: row.dflt_value, + primaryKey: row.pk === 1, + })); +} + +/** + * Creates PostgreSQL table based on SQLite schema + */ +async function createPostgresTable( + pgClient: Client, + tableName: string, + columns: ColumnInfo[] +): Promise { + // Check if table exists + const existsResult = await pgClient.query(` + SELECT EXISTS ( + SELECT FROM information_schema.tables + WHERE table_schema = 'public' + AND table_name = $1 + ) + `, [tableName]); + + const tableExists = existsResult.rows[0].exists; + + if (tableExists && migrationConfig.truncateBeforeInsert) { + // Drop existing table to recreate + await pgClient.query(`DROP TABLE IF EXISTS "${tableName}" CASCADE`); + console.log(` Dropped existing table: ${tableName}`); + } else if (tableExists) { + console.log(` Table already exists, will append data: ${tableName}`); + return; + } + + const columnDefs = columns.map(col => { + let def = `"${col.name}" ${mapSqliteTypeToPostgres(col.type)}`; + if (col.notNull) { + def += ' NOT NULL'; + } + if (col.primaryKey) { + def += ' PRIMARY KEY'; + } + if (col.defaultValue !== null) { + def += ` DEFAULT ${col.defaultValue}`; + } + return def; + }).join(', '); + + const createSql = `CREATE TABLE "${tableName}" (${columnDefs})`; + + if (logConfig.verbose) { + console.log(`Creating table: ${tableName}`); + console.log(createSql); + } + + await pgClient.query(createSql); +} + +/** + * Attempts to parse JSON values that were stored as TEXT in SQLite + */ +function parseValue(value: any, columnName: string): any { + if (value === null) return null; + if (typeof value !== 'string') return value; + + // Try to parse as JSON (for arrays/objects that were stringified) + if ((value.startsWith('[') && value.endsWith(']')) || + (value.startsWith('{') && value.endsWith('}'))) { + try { + return JSON.parse(value); + } catch { + return value; + } + } + + return value; +} + +/** + * Migrates data from SQLite to PostgreSQL + */ +async function migrateTableData( + sqliteDb: Database.Database, + pgClient: Client, + tableName: string, + columns: ColumnInfo[] +): Promise { + // Check if table should be excluded + if (migrationConfig.excludedTables.includes(tableName)) { + console.log(`Skipping excluded table: ${tableName}`); + return 0; + } + + // Check if only specific tables should be included + if (migrationConfig.includedTables.length > 0 && !migrationConfig.includedTables.includes(tableName)) { + console.log(`Skipping table not in include list: ${tableName}`); + return 0; + } + + console.log(`Migrating table: ${tableName}`); + + // Get total count + const countResult = sqliteDb.prepare(`SELECT COUNT(*) as count FROM "${tableName}"`).get() as { count: number }; + const totalRows = countResult.count; + console.log(` Total rows to migrate: ${totalRows}`); + + if (totalRows === 0) { + console.log(` No data to migrate`); + return 0; + } + + // Clear existing data if configured (and table wasn't just created) + if (migrationConfig.truncateBeforeInsert) { + await pgClient.query(`DELETE FROM "${tableName}"`); + console.log(` Cleared existing data`); + } + + // Get column names + const columnNames = columns.map(c => `"${c.name}"`).join(', '); + const placeholders = columns.map((_, i) => `$${i + 1}`).join(', '); + + let migratedCount = 0; + let offset = 0; + + while (offset < totalRows) { + const rows = sqliteDb.prepare(` + SELECT * FROM "${tableName}" + ORDER BY ROWID + LIMIT ? OFFSET ? + `).all(migrationConfig.batchSize, offset) as any[]; + + for (const row of rows) { + const values = columns.map(col => parseValue(row[col.name], col.name)); + + await pgClient.query( + `INSERT INTO "${tableName}" (${columnNames}) VALUES (${placeholders})`, + values + ); + } + + migratedCount += rows.length; + offset += migrationConfig.batchSize; + + if (logConfig.verbose || offset % 10000 === 0) { + console.log(` Progress: ${migratedCount}/${totalRows} rows`); + } + } + + console.log(` Completed: ${migratedCount} rows migrated`); + return migratedCount; +} + +/** + * Main migration function + */ +async function migrateSqliteToPostgres(): Promise { + console.log('Starting SQLite to PostgreSQL migration...\n'); + + // Connect to SQLite + const sqliteDb = new Database(sqliteConfig.filename); + console.log('Connected to SQLite'); + + // Connect to PostgreSQL + const pgClient = new Client(postgresConfig); + await pgClient.connect(); + console.log('Connected to PostgreSQL'); + + try { + // Get all tables + const tables = getSqliteTables(sqliteDb); + console.log(`\nFound ${tables.length} tables to migrate\n`); + + let totalMigrated = 0; + + // Migrate each table + for (const tableName of tables) { + try { + const columns = getSqliteTableColumns(sqliteDb, tableName); + + // Create table in PostgreSQL + await createPostgresTable(pgClient, tableName, columns); + + // Migrate data + const migrated = await migrateTableData(sqliteDb, pgClient, tableName, columns); + totalMigrated += migrated; + + console.log(''); + } catch (error) { + console.error(`Error migrating table ${tableName}:`, error); + if (logConfig.verbose) { + throw error; + } + } + } + + console.log('================================='); + console.log('Migration completed successfully!'); + console.log(`Total rows migrated: ${totalMigrated}`); + console.log(`Source: ${sqliteConfig.filename}`); + console.log(`Target: PostgreSQL`); + console.log('================================='); + + } catch (error) { + console.error('Migration failed:', error); + throw error; + } finally { + sqliteDb.close(); + await pgClient.end(); + } +} + +// Run migration if called directly +if (require.main === module) { + migrateSqliteToPostgres().catch(console.error); +} + +export { migrateSqliteToPostgres }; diff --git a/packages/migrator/tsconfig.json b/packages/migrator/tsconfig.json new file mode 100644 index 0000000..bc2ffa3 --- /dev/null +++ b/packages/migrator/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./dist", + "rootDir": ".", + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "include": ["src/**/*", "index.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/progress.md b/progress.md deleted file mode 100644 index d3aedda..0000000 --- a/progress.md +++ /dev/null @@ -1,183 +0,0 @@ -# Progress Summary - Meat Farmer Monorepo - -## User UI Development Progress - -### Profile Image & User Details System - -#### Database Schema Updates -- **Added `user_details` table** with fields: bio, dateOfBirth, gender, occupation, profileImage -- **Established one-to-one relationship** between users and user_details tables -- **Updated relations** in schema for proper data fetching - -#### Backend API Enhancements -- **Updated auth controller** (`login`, `register`, `getProfile`) to query userDetails and return complete user information -- **Added `updateProfile` API** with comprehensive validation and transaction-based updates -- **Implemented signed URLs** for secure profile image access (3-day expiration) -- **Enhanced tRPC `getSelfData`** to include all user details with signed URLs - -#### Frontend Auth System -- **Extended AuthContext** with `userDetails` state and `updateUserDetails` function -- **Modified tRPC queries** for fresh data on every app startup (no caching) -- **Added `useUserDetails` hook** for accessing detailed user information -- **Updated login/register flows** to populate complete user data - -### Edit Profile Functionality - -#### Page Implementation -- **Created edit-profile page** with pre-populated form values -- **Conditional form rendering** - password fields hidden in edit mode -- **Profile image upload** support with existing image display -- **Form validation** adjusted for edit vs registration modes - -#### API Integration -- **Added `useUpdateProfile` hook** using React Query for profile updates -- **Multipart form data handling** for profile image uploads -- **Error handling and loading states** with proper user feedback -- **Context synchronization** after successful profile updates - -### UI/UX Improvements - -#### Drawer Layout Enhancements -- **Profile image display** in drawer header with fallback to person icon -- **User details integration** showing name and mobile from userDetails -- **Circular avatar styling** for profile images - -#### Me Page Redesign -- **2x2 grid layout** replacing vertical button list -- **MaterialIcons integration** with relevant icons for each section: - - Orders: `shopping-bag` (blue) - - Complaints: `report-problem` (green) - - Coupons: `local-offer` (purple) - - Profile: `person` (orange) -- **Enhanced styling** with rounded corners, shadows, and better typography -- **Responsive design** with proper spacing and touch targets - -### Registration Form Updates -- **Edit mode support** with `isEdit` prop -- **Conditional field rendering** (passwords/terms hidden in edit mode) -- **Initial values support** for pre-populating form data -- **Profile image handling** for both new uploads and existing images - -## Files Modified - -### Backend -- `apps/backend/src/db/schema.ts` - Added user_details table, vendor_snippets table, and relations definitions -- `apps/backend/src/uv-apis/auth.controller.ts` - Enhanced auth APIs with userDetails and signed URLs -- `apps/backend/src/uv-apis/auth.router.ts` - Added update profile route -- `apps/backend/src/trpc/user-apis/user.ts` - Updated getSelfData with userDetails -- `apps/backend/src/trpc/admin-apis/vendor-snippets.ts` - Complete CRUD API for vendor snippets management - -### Frontend -- `apps/user-ui/src/types/auth.ts` - Added UserDetails interface and updated AuthState -- `apps/user-ui/src/contexts/AuthContext.tsx` - Enhanced with userDetails state and hooks -- `apps/user-ui/src/api-hooks/auth.api.ts` - Added updateProfile API and hook -- `apps/user-ui/components/registration-form.tsx` - Added edit mode support -- `apps/user-ui/app/(drawer)/edit-profile/index.tsx` - New edit profile page -- `apps/user-ui/app/(drawer)/_layout.tsx` - Updated drawer with profile image -- `apps/user-ui/app/(drawer)/me/index.tsx` - Redesigned with 2x2 grid and icons - -### Admin UI (New Vendor Snippets Feature) -- `apps/admin-ui/app/(drawer)/vendor-snippets/index.tsx` - Main vendor snippets management page -- `apps/admin-ui/app/(drawer)/_layout.tsx` - Added vendor snippets to drawer navigation -- `apps/admin-ui/components/VendorSnippetForm.tsx` - Create/edit form with validation -- `apps/admin-ui/components/SnippetOrdersView.tsx` - Orders viewing component with matching highlights -- `apps/admin-ui/src/api-hooks/vendor-snippets.api.ts` - tRPC hooks for vendor snippets operations -- `apps/admin-ui/src/trpc-client.ts` - Updated imports for tRPC client usage - -## Key Features Implemented - -### User UI Features -✅ **Complete user profile system** with detailed information storage -✅ **Secure image handling** with signed URLs and S3 integration -✅ **Edit profile functionality** with pre-populated forms and validation -✅ **Beautiful UI components** with icons and modern design patterns -✅ **Fresh data fetching** on app startup with no caching -✅ **Transaction-safe updates** with proper error handling -✅ **Responsive grid layouts** optimized for mobile experience - -### Admin UI Features (Vendor Snippets) -✅ **Complete vendor snippets management system** with full CRUD operations -✅ **Advanced order matching logic** that finds orders by slot and product criteria -✅ **Interactive forms** with slot/product selection and validation -✅ **Orders viewing interface** with product matching highlights and statistics -✅ **Automatic data refresh** using focus callbacks for fresh data -✅ **Proper relations handling** in Drizzle ORM with foreign key relationships -✅ **Error handling and loading states** throughout the user journey -✅ **Navigation integration** with drawer menu and proper routing - -## Admin UI Changes - -### Vendor Snippets Management System - -#### Database Schema Updates -- **Added `vendor_snippets` table** with fields: id, snippetCode, slotId, productIds, validTill, createdAt -- **Established foreign key relationship** between vendorSnippets and deliverySlotInfo tables -- **Added relations definition** (`vendorSnippetsRelations`) for proper Drizzle ORM queries -- **Array field support** for storing multiple product IDs per snippet - -#### Backend API Implementation -- **Complete CRUD operations** for vendor snippets: - - `create`: Validates slot/product existence, prevents duplicate codes - - `getAll`: Returns snippets with slot relations, ordered by creation date - - `getById`: Fetches individual snippet with slot details - - `update`: Partial updates with validation and uniqueness checks - - `delete`: Soft delete by setting expiry to current time -- **`getOrdersBySnippet` API**: Advanced order matching logic that: - - Finds orders with matching delivery slots - - Filters orders containing at least one snippet product - - Returns formatted order data with product matching highlights - - Includes customer details, pricing, and delivery information - -#### Admin UI Implementation -- **Vendor Snippets List Page**: Complete management interface with: - - Snippet cards showing code, slot info, product count, expiry dates - - Action buttons for View Orders, Edit, and Delete operations - - Empty state with call-to-action for first snippet creation - - Loading states and error handling -- **Create/Edit Forms**: Comprehensive form components using: - - BottomDropdown for slot selection (replacing custom dropdowns) - - MultiSelectDropdown for product selection with search - - DatePicker for expiry date management - - Form validation with real-time error feedback - - Auto-generated snippet codes for new entries - -#### Orders Viewing System -- **SnippetOrdersView Component**: Dedicated screen for viewing matched orders: - - Order cards with customer details, amounts, and delivery slots - - Product lists with matching highlights (⭐ indicators) - - Summary statistics (total orders, revenue) - - Responsive design with proper spacing and typography - -#### Navigation & UX Enhancements -- **Drawer Integration**: Added "Vendor Snippets" to admin navigation menu -- **Focus-based Refetching**: Implemented `useFocusCallback` for automatic data refresh when returning to the screen -- **Error Handling**: Fixed tRPC client vs hooks usage (`trpcClient` for direct queries) -- **Loading States**: Proper loading indicators and user feedback throughout the flow - -#### Technical Improvements -- **Relations Fix**: Resolved Drizzle ORM error by adding missing relations definition -- **API Client Usage**: Corrected tRPC usage patterns (hooks vs direct client) -- **Type Safety**: Proper TypeScript interfaces and error handling -- **Performance**: Efficient queries with proper indexing and filtering - -### Previous Admin UI Changes - -#### Slot Selection Centralization -- **Moved slot dropdown** from individual pages to Manage Orders hub page -- **Updated navigation** with slotId query parameters -- **Streamlined child pages** with URL param reading - -#### UI Cleanup & Improvements -- **Removed redundant elements** from drawer navigation -- **Compacted order displays** for better space utilization -- **Enhanced delivery sequences** layout - -## Important Notes -- **Do not run build, compile, or migration commands** - These should be handled manually by developers -- Avoid running `npm run build`, `tsc`, `drizzle-kit generate`, or similar compilation/migration commands -- Schema changes should be committed and migrations generated manually -- **Signed URLs** are used for secure image access with 3-day expiration -- **React Query** handles all API state management with proper loading/error states -- **Vendor Snippets**: Relations definitions are critical for Drizzle ORM queries - always define relations for foreign key relationships -- **tRPC Usage**: Use `trpc` for React hooks and `trpcClient` for direct API calls outside components -- **Focus Callbacks**: Implemented for automatic data refresh when screens regain focus