This commit is contained in:
shafi54 2026-03-04 19:18:59 +05:30
parent ffaade32d6
commit 1a74efdd3c
13 changed files with 51 additions and 33 deletions

View file

@ -1,6 +1,6 @@
ENV_MODE=PROD ENV_MODE=PROD
# DATABASE_URL=postgresql://postgres:meatfarmer_master_password@57.128.212.174:7447/meatfarmer #technocracy DATABASE_URL=postgresql://postgres:meatfarmer_master_password@57.128.212.174:7447/meatfarmer #technocracy
DATABASE_URL=postgres://postgres:meatfarmer_master_password@5.223.55.14:7447/meatfarmer #hetzner # DATABASE_URL=postgres://postgres:meatfarmer_master_password@5.223.55.14:7447/meatfarmer #hetzner
PHONE_PE_BASE_URL=https://api-preprod.phonepe.com/ PHONE_PE_BASE_URL=https://api-preprod.phonepe.com/
PHONE_PE_CLIENT_ID=TEST-M23F2IGP34ZAR_25090 PHONE_PE_CLIENT_ID=TEST-M23F2IGP34ZAR_25090
PHONE_PE_CLIENT_VERSION=1 PHONE_PE_CLIENT_VERSION=1
@ -20,6 +20,7 @@ S3_URL=https://da9b1aa7c1951c23e2c0c3246ba68a58.r2.cloudflarestorage.com
S3_BUCKET_NAME=meatfarmer S3_BUCKET_NAME=meatfarmer
EXPO_ACCESS_TOKEN=Asvpy8cByRh6T4ksnWScO6PLcio2n35-BwES5zK- EXPO_ACCESS_TOKEN=Asvpy8cByRh6T4ksnWScO6PLcio2n35-BwES5zK-
JWT_SECRET=my_meatfarmer_jwt_secret_key JWT_SECRET=my_meatfarmer_jwt_secret_key
ASSETS_DOMAIN=https://assets.freshyo.in/
# REDIS_URL=redis://default:redis_shafi_password@5.223.55.14:6379 # REDIS_URL=redis://default:redis_shafi_password@5.223.55.14:6379
REDIS_URL=redis://default:redis_shafi_password@57.128.212.174:6379 REDIS_URL=redis://default:redis_shafi_password@57.128.212.174:6379
APP_URL=http://localhost:4000 APP_URL=http://localhost:4000

File diff suppressed because one or more lines are too long

View file

@ -2,7 +2,7 @@ import { eq, gt, and, sql, inArray } from "drizzle-orm";
import { Request, Response } from "express"; import { Request, Response } from "express";
import { db } from "../db/db_index"; import { db } from "../db/db_index";
import { productInfo, units, productSlots, deliverySlotInfo, productTags } from "../db/schema"; import { productInfo, units, productSlots, deliverySlotInfo, productTags } from "../db/schema";
import { generateSignedUrlsFromS3Urls } from "../lib/s3-client"; import { scaffoldAssetUrl } from "../lib/s3-client";
/** /**
* Get next delivery date for a product * Get next delivery date for a product
@ -89,7 +89,7 @@ export const getAllProductsSummary = async (req: Request, res: Response) => {
productQuantity: product.productQuantity, productQuantity: product.productQuantity,
isOutOfStock: product.isOutOfStock, isOutOfStock: product.isOutOfStock,
nextDeliveryDate: nextDeliveryDate ? nextDeliveryDate.toISOString() : null, nextDeliveryDate: nextDeliveryDate ? nextDeliveryDate.toISOString() : null,
images: await generateSignedUrlsFromS3Urls((product.images as string[]) || []), images: scaffoldAssetUrl((product.images as string[]) || []),
}; };
}) })
); );

View file

@ -15,6 +15,8 @@ export const s3BucketName = process.env.S3_BUCKET_NAME as string
export const s3Region = process.env.S3_REGION as string export const s3Region = process.env.S3_REGION as string
export const assetsDomain = process.env.ASSETS_DOMAIN as string;
export const s3Url = process.env.S3_URL as string export const s3Url = process.env.S3_URL as string
export const redisUrl = process.env.REDIS_URL as string export const redisUrl = process.env.REDIS_URL as string

View file

@ -2,7 +2,7 @@
import { DeleteObjectCommand, DeleteObjectsCommand, PutObjectCommand, S3Client, GetObjectCommand } from "@aws-sdk/client-s3" import { DeleteObjectCommand, DeleteObjectsCommand, PutObjectCommand, S3Client, GetObjectCommand } from "@aws-sdk/client-s3"
import { getSignedUrl } from "@aws-sdk/s3-request-presigner" import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
import signedUrlCache from "./signed-url-cache" import signedUrlCache from "./signed-url-cache"
import { s3AccessKeyId, s3Region, s3Url, s3SecretAccessKey, s3BucketName } from "./env-exporter"; import { s3AccessKeyId, s3Region, s3Url, s3SecretAccessKey, s3BucketName, assetsDomain } from "./env-exporter";
import { db } from "../db/db_index"; // Adjust path if needed import { db } from "../db/db_index"; // Adjust path if needed
import { uploadUrlStatus } from "../db/schema"; import { uploadUrlStatus } from "../db/schema";
import { and, eq } from 'drizzle-orm'; import { and, eq } from 'drizzle-orm';
@ -60,6 +60,22 @@ export async function deleteImageUtil({bucket = s3BucketName, keys}:{bucket?:str
} }
} }
export function scaffoldAssetUrl(input: string | null): string
export function scaffoldAssetUrl(input: (string | null)[]): string[]
export function scaffoldAssetUrl(input: string | null | (string | null)[]): string | string[] {
if (Array.isArray(input)) {
return input.map(key => scaffoldAssetUrl(key) as string);
}
if (!input) {
return '';
}
const normalizedKey = input.replace(/^\/+/, '');
const domain = assetsDomain.endsWith('/')
? assetsDomain.slice(0, -1)
: assetsDomain;
return `${domain}/${normalizedKey}`;
}
/** /**
* Generate a signed URL from an S3 URL * Generate a signed URL from an S3 URL

View file

@ -3,7 +3,7 @@ import redisClient from 'src/lib/redis-client';
import { db } from '../db/db_index'; import { db } from '../db/db_index';
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productTags, productTagInfo } from '../db/schema'; import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productTags, productTagInfo } from '../db/schema';
import { eq, and, gt, sql } from 'drizzle-orm'; import { eq, and, gt, sql } from 'drizzle-orm';
import { generateSignedUrlsFromS3Urls } from 'src/lib/s3-client'; import { generateSignedUrlsFromS3Urls, scaffoldAssetUrl } from 'src/lib/s3-client';
// Uniform Product Type (matches getProductDetails return) // Uniform Product Type (matches getProductDetails return)
interface Product { interface Product {
@ -113,7 +113,7 @@ export async function initializeProducts(): Promise<void> {
// Store each product in Redis // Store each product in Redis
for (const product of productsData) { for (const product of productsData) {
const signedImages = await generateSignedUrlsFromS3Urls((product.images as string[]) || []); const signedImages = scaffoldAssetUrl((product.images as string[]) || []);
const store = product.storeId ? storeMap.get(product.storeId) || null : null; const store = product.storeId ? storeMap.get(product.storeId) || null : null;
const deliverySlots = deliverySlotsMap.get(product.id) || []; const deliverySlots = deliverySlotsMap.get(product.id) || [];
const specialDeals = specialDealsMap.get(product.id) || []; const specialDeals = specialDealsMap.get(product.id) || [];

View file

@ -2,7 +2,7 @@ import redisClient from 'src/lib/redis-client';
import { db } from '../db/db_index'; import { db } from '../db/db_index';
import { deliverySlotInfo, productSlots, productInfo, units } from '../db/schema'; import { deliverySlotInfo, productSlots, productInfo, units } from '../db/schema';
import { eq, and, gt, asc } from 'drizzle-orm'; import { eq, and, gt, asc } from 'drizzle-orm';
import { generateSignedUrlsFromS3Urls } from 'src/lib/s3-client'; import { generateSignedUrlsFromS3Urls, scaffoldAssetUrl } from 'src/lib/s3-client';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
// Define the structure for slot with products // Define the structure for slot with products
@ -78,7 +78,7 @@ export async function initializeSlotStore(): Promise<void> {
price: productSlot.product.price.toString(), price: productSlot.product.price.toString(),
marketPrice: productSlot.product.marketPrice?.toString() || null, marketPrice: productSlot.product.marketPrice?.toString() || null,
unit: productSlot.product.unit?.shortNotation || null, unit: productSlot.product.unit?.shortNotation || null,
images: await generateSignedUrlsFromS3Urls( images: scaffoldAssetUrl(
(productSlot.product.images as string[]) || [], (productSlot.product.images as string[]) || [],
), ),
isOutOfStock: productSlot.product.isOutOfStock, isOutOfStock: productSlot.product.isOutOfStock,

View file

@ -4,7 +4,7 @@ import { db } from '../../db/db_index';
import { cartItems, productInfo, units, productSlots, deliverySlotInfo } from '../../db/schema'; import { cartItems, productInfo, units, productSlots, deliverySlotInfo } from '../../db/schema';
import { eq, and, sql, inArray, gt } from 'drizzle-orm'; import { eq, and, sql, inArray, gt } from 'drizzle-orm';
import { ApiError } from '../../lib/api-error'; import { ApiError } from '../../lib/api-error';
import { generateSignedUrlsFromS3Urls } from '../../lib/s3-client'; import { generateSignedUrlsFromS3Urls, scaffoldAssetUrl } from '../../lib/s3-client';
import { getProductSlots, getMultipleProductsSlots } from '../../stores/slot-store'; import { getProductSlots, getMultipleProductsSlots } from '../../stores/slot-store';
interface CartResponse { interface CartResponse {
@ -46,7 +46,7 @@ const getCartData = async (userId: number): Promise<CartResponse> => {
productQuantity: item.productQuantity, productQuantity: item.productQuantity,
unit: item.unitShortNotation, unit: item.unitShortNotation,
isOutOfStock: item.isOutOfStock, isOutOfStock: item.isOutOfStock,
images: await generateSignedUrlsFromS3Urls((item.productImages as string[]) || []), images: scaffoldAssetUrl((item.productImages as string[]) || []),
}, },
subtotal: parseFloat(item.productPrice.toString()) * parseFloat(item.quantity), subtotal: parseFloat(item.productPrice.toString()) * parseFloat(item.quantity),
})) }))

View file

@ -17,7 +17,7 @@ import {
userDetails, userDetails,
} from "../../db/schema"; } from "../../db/schema";
import { eq, and, inArray, desc, gte, lte } from "drizzle-orm"; import { eq, and, inArray, desc, gte, lte } from "drizzle-orm";
import { generateSignedUrlsFromS3Urls } from "../../lib/s3-client"; import { scaffoldAssetUrl } from "../../lib/s3-client";
import { ApiError } from "../../lib/api-error"; import { ApiError } from "../../lib/api-error";
import { import {
sendOrderPlacedNotification, sendOrderPlacedNotification,
@ -518,7 +518,7 @@ export const orderRouter = router({
order.orderItems.map(async (item) => { order.orderItems.map(async (item) => {
const signedImages = item.product.images const signedImages = item.product.images
? await generateSignedUrlsFromS3Urls( ? scaffoldAssetUrl(
item.product.images as string[] item.product.images as string[]
) )
: []; : [];
@ -682,7 +682,7 @@ export const orderRouter = router({
const items = await Promise.all( const items = await Promise.all(
order.orderItems.map(async (item) => { order.orderItems.map(async (item) => {
const signedImages = item.product.images const signedImages = item.product.images
? await generateSignedUrlsFromS3Urls( ? scaffoldAssetUrl(
item.product.images as string[] item.product.images as string[]
) )
: []; : [];
@ -974,7 +974,7 @@ export const orderRouter = router({
nextDeliveryDate: nextDeliveryDate nextDeliveryDate: nextDeliveryDate
? nextDeliveryDate.toISOString() ? nextDeliveryDate.toISOString()
: null, : null,
images: await generateSignedUrlsFromS3Urls( images: scaffoldAssetUrl(
(product.images as string[]) || [] (product.images as string[]) || []
), ),
}; };

View file

@ -2,7 +2,7 @@ import { router, publicProcedure, protectedProcedure } from '../trpc-index';
import { z } from 'zod'; import { z } from 'zod';
import { db } from '../../db/db_index'; import { db } from '../../db/db_index';
import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productTagInfo, productTags, productReviews, users } from '../../db/schema'; import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, storeInfo, productTagInfo, productTags, productReviews, users } from '../../db/schema';
import { generateSignedUrlsFromS3Urls, generateSignedUrlFromS3Url, generateUploadUrl, claimUploadUrl, extractKeyFromPresignedUrl } from '../../lib/s3-client'; import { claimUploadUrl, extractKeyFromPresignedUrl, scaffoldAssetUrl } from '../../lib/s3-client';
import { ApiError } from '../../lib/api-error'; import { ApiError } from '../../lib/api-error';
import { eq, and, gt, sql, inArray, desc } from 'drizzle-orm'; import { eq, and, gt, sql, inArray, desc } from 'drizzle-orm';
import { getProductById as getProductByIdFromCache, getAllProducts as getAllProductsFromCache } from '../../stores/product-store'; import { getProductById as getProductByIdFromCache, getAllProducts as getAllProductsFromCache } from '../../stores/product-store';
@ -131,7 +131,7 @@ export const productRouter = router({
.orderBy(specialDeals.quantity); .orderBy(specialDeals.quantity);
// Generate signed URLs for images // Generate signed URLs for images
const signedImages = await generateSignedUrlsFromS3Urls((product.images as string[]) || []); const signedImages = scaffoldAssetUrl((product.images as string[]) || []);
const response: Product = { const response: Product = {
id: product.id, id: product.id,
@ -188,7 +188,7 @@ export const productRouter = router({
const reviewsWithSignedUrls = await Promise.all( const reviewsWithSignedUrls = await Promise.all(
reviews.map(async (review) => ({ reviews.map(async (review) => ({
...review, ...review,
signedImageUrls: await generateSignedUrlsFromS3Urls((review.imageUrls as string[]) || []), signedImageUrls: scaffoldAssetUrl((review.imageUrls as string[]) || []),
})) }))
); );

View file

@ -8,7 +8,6 @@ import {
units, units,
} from "../../db/schema"; } from "../../db/schema";
import { eq, and, gt, asc } from "drizzle-orm"; import { eq, and, gt, asc } from "drizzle-orm";
import { generateSignedUrlsFromS3Urls } from "../../lib/s3-client";
import { getAllSlots as getAllSlotsFromCache, getSlotById as getSlotByIdFromCache } from "../../stores/slot-store"; import { getAllSlots as getAllSlotsFromCache, getSlotById as getSlotByIdFromCache } from "../../stores/slot-store";
import dayjs from 'dayjs'; import dayjs from 'dayjs';

View file

@ -3,7 +3,7 @@ import { z } from 'zod';
import { db } from '../../db/db_index'; import { db } from '../../db/db_index';
import { storeInfo, productInfo, units } from '../../db/schema'; import { storeInfo, productInfo, units } from '../../db/schema';
import { eq, and, sql } from 'drizzle-orm'; import { eq, and, sql } from 'drizzle-orm';
import { generateSignedUrlsFromS3Urls, generateSignedUrlFromS3Url } from '../../lib/s3-client'; import { scaffoldAssetUrl } from '../../lib/s3-client';
import { ApiError } from '../../lib/api-error'; import { ApiError } from '../../lib/api-error';
export const storesRouter = router({ export const storesRouter = router({
@ -27,7 +27,7 @@ export const storesRouter = router({
// Generate signed URLs for store images and fetch sample products // Generate signed URLs for store images and fetch sample products
const storesWithDetails = await Promise.all( const storesWithDetails = await Promise.all(
storesData.map(async (store) => { storesData.map(async (store) => {
const signedImageUrl = store.imageUrl ? await generateSignedUrlFromS3Url(store.imageUrl) : null; const signedImageUrl = store.imageUrl ? scaffoldAssetUrl(store.imageUrl) : null;
// Fetch up to 3 products for this store // Fetch up to 3 products for this store
const sampleProducts = await db const sampleProducts = await db
@ -47,7 +47,7 @@ export const storesRouter = router({
return { return {
id: product.id, id: product.id,
name: product.name, name: product.name,
signedImageUrl: (images && images.length > 0) ? await generateSignedUrlFromS3Url(images[0]) : null, signedImageUrl: (images && images.length > 0) ? scaffoldAssetUrl(images[0]) : null,
}; };
}) })
); );
@ -91,7 +91,7 @@ export const storesRouter = router({
} }
// Generate signed URL for store image // Generate signed URL for store image
const signedImageUrl = storeData.imageUrl ? await generateSignedUrlFromS3Url(storeData.imageUrl) : null; const signedImageUrl = storeData.imageUrl ? scaffoldAssetUrl(storeData.imageUrl) : null;
// Fetch products for this store // Fetch products for this store
const productsData = await db const productsData = await db
@ -124,7 +124,7 @@ export const storesRouter = router({
incrementStep: product.incrementStep, incrementStep: product.incrementStep,
unit: product.unitShortNotation, unit: product.unitShortNotation,
unitNotation: product.unitNotation, unitNotation: product.unitNotation,
images: await generateSignedUrlsFromS3Urls((product.images as string[]) || []), images: scaffoldAssetUrl((product.images as string[]) || []),
isOutOfStock: product.isOutOfStock, isOutOfStock: product.isOutOfStock,
productQuantity: product.productQuantity productQuantity: product.productQuantity
})) }))

View file

@ -63,7 +63,7 @@ const isDevMode = Constants.executionEnvironment !== "standalone";
// const BASE_API_URL = API_URL; // const BASE_API_URL = API_URL;
// const BASE_API_URL = 'http://10.0.2.2:4000'; // const BASE_API_URL = 'http://10.0.2.2:4000';
// const BASE_API_URL = 'http://192.168.100.101:4000'; // const BASE_API_URL = 'http://192.168.100.101:4000';
// const BASE_API_URL = 'http://192.168.1.6:4000'; // const BASE_API_URL = 'http://192.168.1.5:4000';
let BASE_API_URL = "https://mf.freshyo.in"; let BASE_API_URL = "https://mf.freshyo.in";
// let BASE_API_URL = 'http://192.168.100.104:4000'; // let BASE_API_URL = 'http://192.168.100.104:4000';
// let BASE_API_URL = 'http://192.168.29.176:4000'; // let BASE_API_URL = 'http://192.168.29.176:4000';