import { router, publicProcedure, protectedProcedure } from '@/src/trpc/trpc-index' import { commonRouter } from '@/src/trpc/apis/common-apis/common' import { getStoresSummary, healthCheck, getCacheVersion, } from '@/src/dbService' import type { StoresSummaryResponse } from '@packages/shared' import * as turf from '@turf/turf'; import { z } from 'zod'; import { mbnrGeoJson } from '@/src/lib/mbnr-geojson' import { generateUploadUrl } from '@/src/lib/s3-client' import { ApiError } from '@/src/lib/api-error' import { getAllConstValues } from '@/src/lib/const-store' import { CONST_KEYS } from '@/src/lib/const-keys' import { getAssetsDomain, getApiCacheKey } from '@/src/lib/env-exporter' const polygon = turf.polygon(mbnrGeoJson.features[0].geometry.coordinates); export async function scaffoldEssentialConsts() { const consts = await getAllConstValues(); const cacheVersion = await getCacheVersion() return { freeDeliveryThreshold: consts[CONST_KEYS.freeDeliveryThreshold] ?? 200, deliveryCharge: consts[CONST_KEYS.deliveryCharge] ?? 0, flashFreeDeliveryThreshold: consts[CONST_KEYS.flashFreeDeliveryThreshold] ?? 500, flashDeliveryCharge: consts[CONST_KEYS.flashDeliveryCharge] ?? 69, popularItems: consts[CONST_KEYS.popularItems], versionNum: consts[CONST_KEYS.versionNum], playStoreUrl: consts[CONST_KEYS.playStoreUrl], appStoreUrl: consts[CONST_KEYS.appStoreUrl], webViewHtml: null, webviewHtml: null, isWebviewClosable: true, isFlashDeliveryEnabled: consts[CONST_KEYS.isFlashDeliveryEnabled] ?? false, supportMobile: consts[CONST_KEYS.supportMobile] ?? '', supportEmail: consts[CONST_KEYS.supportEmail] ?? '', assetsDomain: getAssetsDomain(), apiCacheKey: getApiCacheKey(), cacheVersion, }; } export const commonApiRouter = router({ product: commonRouter, getStoresSummary: publicProcedure .query(async (): Promise => { /* // Old implementation - direct DB queries: import { db } from '@/src/db/db_index' import { storeInfo } from '@/src/db/schema' const stores = await db.query.storeInfo.findMany({ columns: { id: true, name: true, description: true, }, }); */ const stores = await getStoresSummary(); return { stores, }; }), checkLocationInPolygon: publicProcedure .input(z.object({ lat: z.number().min(-90).max(90), lng: z.number().min(-180).max(180), })) .query(({ input }) => { try { const { lat, lng } = input; const point = turf.point([lng, lat]); // GeoJSON: [longitude, latitude] const isInside = turf.booleanPointInPolygon(point, polygon); return { isInside }; } catch (error) { throw new Error('Invalid coordinates or polygon data'); } }), generateUploadUrls: protectedProcedure .input(z.object({ contextString: z.enum(['review', 'review_response', 'product_info', 'notification', 'store', 'complaint', 'profile', 'tags']), mimeTypes: z.array(z.string()), })) .mutation(async ({ input }): Promise<{ uploadUrls: string[] }> => { const { contextString, mimeTypes } = input; const uploadUrls: string[] = []; const keys: string[] = []; for (const mimeType of mimeTypes) { // Generate key based on context and mime type let folder: string; if (contextString === 'review') { folder = 'review-images'; } else if (contextString === 'product_info') { folder = 'product-images'; } else if (contextString === 'store') { folder = 'store-images'; } else if (contextString === 'review_response') { folder = 'review-response-images'; } else if (contextString === 'complaint') { folder = 'complaint-images'; } else if (contextString === 'profile') { folder = 'profile-images'; } else if (contextString === 'tags') { folder = 'tags'; } else { folder = ''; } const extension = mimeType === 'image/jpeg' ? '.jpg' : mimeType === 'image/png' ? '.png' : mimeType === 'image/gif' ? '.gif' : '.jpg'; const key = `${folder}/${Date.now()}${extension}`; try { const uploadUrl = await generateUploadUrl(key, mimeType); uploadUrls.push(uploadUrl); keys.push(key); } catch (error) { console.error('Error generating upload URL:', error); throw new ApiError('Failed to generate upload URL', 500); } } return { uploadUrls }; }), healthCheck: publicProcedure .query(async () => { /* // Old implementation - direct DB queries: import { db } from '@/src/db/db_index' import { keyValStore, productInfo } from '@/src/db/schema' // Test DB connection by selecting product names // await db.select({ name: productInfo.name }).from(productInfo).limit(1); await db.select({ key: keyValStore.key }).from(keyValStore).limit(1); */ const result = await healthCheck(); return result; }), essentialConsts: publicProcedure .query(async ({ ctx }) => { const requestUrl = ctx.req.url const host = new URL(requestUrl).host console.log('essentialConsts request', { host, url: requestUrl }) const updateNotice = `

You're using an old version of app. please restart to update. Just close and open

With love, from Freshyo

` const response = await scaffoldEssentialConsts(); const shouldShowNotice = host.includes('raw') || host.includes('mf') return { ...response, webviewHtml: shouldShowNotice ? updateNotice : null, isWebviewClosable: shouldShowNotice ? false : true }; }), }); export type CommonApiRouter = typeof commonApiRouter;