This commit is contained in:
shafi54 2026-04-02 00:52:07 +05:30
parent 15991f46db
commit 982d3027f8
35 changed files with 5383 additions and 4049 deletions

1
.gitignore vendored
View file

@ -8,6 +8,7 @@ yarn-error.log*
lerna-debug.log* lerna-debug.log*
.pnpm-debug.log* .pnpm-debug.log*
**/.wrangler/*
# Diagnostic reports (https://nodejs.org/api/report.html) # Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

View file

@ -1,11 +0,0 @@
import worker, * as OTHER_EXPORTS from "/Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/worker.ts";
import * as __MIDDLEWARE_0__ from "/Users/mohammedshafiuddin/WebDev/freshyo/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts";
import * as __MIDDLEWARE_1__ from "/Users/mohammedshafiuddin/WebDev/freshyo/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts";
export * from "/Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/worker.ts";
export const __INTERNAL_WRANGLER_MIDDLEWARE__ = [
__MIDDLEWARE_0__.default,__MIDDLEWARE_1__.default
]
export default worker;

View file

@ -1,134 +0,0 @@
// This loads all middlewares exposed on the middleware object and then starts
// the invocation chain. The big idea is that we can add these to the middleware
// export dynamically through wrangler, or we can potentially let users directly
// add them as a sort of "plugin" system.
import ENTRY, { __INTERNAL_WRANGLER_MIDDLEWARE__ } from "/Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/.wrangler/tmp/bundle-l1tHq1/middleware-insertion-facade.js";
import { __facade_invoke__, __facade_register__, Dispatcher } from "/Users/mohammedshafiuddin/WebDev/freshyo/node_modules/wrangler/templates/middleware/common.ts";
import type { WorkerEntrypointConstructor } from "/Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/.wrangler/tmp/bundle-l1tHq1/middleware-insertion-facade.js";
// Preserve all the exports from the worker
export * from "/Users/mohammedshafiuddin/WebDev/freshyo/apps/backend/.wrangler/tmp/bundle-l1tHq1/middleware-insertion-facade.js";
class __Facade_ScheduledController__ implements ScheduledController {
readonly #noRetry: ScheduledController["noRetry"];
constructor(
readonly scheduledTime: number,
readonly cron: string,
noRetry: ScheduledController["noRetry"]
) {
this.#noRetry = noRetry;
}
noRetry() {
if (!(this instanceof __Facade_ScheduledController__)) {
throw new TypeError("Illegal invocation");
}
// Need to call native method immediately in case uncaught error thrown
this.#noRetry();
}
}
function wrapExportedHandler(worker: ExportedHandler): ExportedHandler {
// If we don't have any middleware defined, just return the handler as is
if (
__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||
__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0
) {
return worker;
}
// Otherwise, register all middleware once
for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {
__facade_register__(middleware);
}
const fetchDispatcher: ExportedHandlerFetchHandler = function (
request,
env,
ctx
) {
if (worker.fetch === undefined) {
throw new Error("Handler does not export a fetch() function.");
}
return worker.fetch(request, env, ctx);
};
return {
...worker,
fetch(request, env, ctx) {
const dispatcher: Dispatcher = function (type, init) {
if (type === "scheduled" && worker.scheduled !== undefined) {
const controller = new __Facade_ScheduledController__(
Date.now(),
init.cron ?? "",
() => {}
);
return worker.scheduled(controller, env, ctx);
}
};
return __facade_invoke__(request, env, ctx, dispatcher, fetchDispatcher);
},
};
}
function wrapWorkerEntrypoint(
klass: WorkerEntrypointConstructor
): WorkerEntrypointConstructor {
// If we don't have any middleware defined, just return the handler as is
if (
__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||
__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0
) {
return klass;
}
// Otherwise, register all middleware once
for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {
__facade_register__(middleware);
}
// `extend`ing `klass` here so other RPC methods remain callable
return class extends klass {
#fetchDispatcher: ExportedHandlerFetchHandler<Record<string, unknown>> = (
request,
env,
ctx
) => {
this.env = env;
this.ctx = ctx;
if (super.fetch === undefined) {
throw new Error("Entrypoint class does not define a fetch() function.");
}
return super.fetch(request);
};
#dispatcher: Dispatcher = (type, init) => {
if (type === "scheduled" && super.scheduled !== undefined) {
const controller = new __Facade_ScheduledController__(
Date.now(),
init.cron ?? "",
() => {}
);
return super.scheduled(controller);
}
};
fetch(request: Request<unknown, IncomingRequestCfProperties>) {
return __facade_invoke__(
request,
this.env,
this.ctx,
this.#dispatcher,
this.#fetchDispatcher
);
}
};
}
let WRAPPED_ENTRY: ExportedHandler | WorkerEntrypointConstructor | undefined;
if (typeof ENTRY === "object") {
WRAPPED_ENTRY = wrapExportedHandler(ENTRY);
} else if (typeof ENTRY === "function") {
WRAPPED_ENTRY = wrapWorkerEntrypoint(ENTRY);
}
export default WRAPPED_ENTRY;

View file

@ -1,13 +0,0 @@
function stripCfConnectingIPHeader(input, init) {
const request = new Request(input, init);
request.headers.delete("CF-Connecting-IP");
return request;
}
globalThis.fetch = new Proxy(globalThis.fetch, {
apply(target, thisArg, argArray) {
return Reflect.apply(target, thisArg, [
stripCfConnectingIPHeader.apply(null, argArray),
]);
},
});

View file

@ -9566,9 +9566,9 @@ async function incrementCacheVersion() {
}); });
const nextValue = parseCacheVersion(existing?.value) + 1; const nextValue = parseCacheVersion(existing?.value) + 1;
if (existing) { if (existing) {
await tx.update(keyValStore).set({ value: nextValue }).where(eq(keyValStore.key, CACHE_VERSION_KEY)); await tx.update(keyValStore).set({ value: nextValue + "" }).where(eq(keyValStore.key, CACHE_VERSION_KEY));
} else { } else {
await tx.insert(keyValStore).values({ key: CACHE_VERSION_KEY, value: nextValue }); await tx.insert(keyValStore).values({ key: CACHE_VERSION_KEY, value: nextValue + "" });
} }
return nextValue; return nextValue;
}); });

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,7 @@
"zod": "^4.1.12" "zod": "^4.1.12"
}, },
"devDependencies": { "devDependencies": {
"@cloudflare/workers-types": "^4.20260304.0", "@cloudflare/workers-types": "^4.20260401.1",
"@types/node": "^24.5.2", "@types/node": "^24.5.2",
"rimraf": "^6.1.2", "rimraf": "^6.1.2",
"ts-node-dev": "^2.0.0", "ts-node-dev": "^2.0.0",

View file

@ -1,5 +1,6 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { initializeAllStores } from '@/src/stores/store-initializer' import { initializeAllStores } from '@/src/stores/store-initializer'
import { initDb } from '@/src/dbService'
const LAST_TRIGGER_KEY = 'lastTrigger' const LAST_TRIGGER_KEY = 'lastTrigger'
const ALARM_DELAY_MINUTES = 0.5 const ALARM_DELAY_MINUTES = 0.5
@ -7,11 +8,32 @@ const ALARM_DELAY_MINUTES = 0.5
export class CacheCreator { export class CacheCreator {
private state: any private state: any
private env: any
constructor(state: any) { constructor(state: any, env: any) {
this.state = state this.state = state
this.env = env
;(globalThis as any).ENV = env
} }
async schedule(): Promise<void> {
console.log( 'from the fetch method of durable object')
// if (request.method === 'POST' && url.pathname === '/schedule') {
const now = Date.now()
await this.state.storage.put(LAST_TRIGGER_KEY, now)
const alarmAt = dayjs(now).add(ALARM_DELAY_MINUTES, 'minute').valueOf()
await this.state.storage.setAlarm(alarmAt)
// return new Response('OK')
// }
// if (request.method === 'POST' && url.pathname === '/clear') {
await this.state.storage.deleteAll()
// return new Response('OK')
// }
// return new Response('CacheCreator ready', { status: 200 })
}
async fetch(request: Request): Promise<Response> { async fetch(request: Request): Promise<Response> {
const url = new URL(request.url) const url = new URL(request.url)
if (request.method === 'POST' && url.pathname === '/schedule') { if (request.method === 'POST' && url.pathname === '/schedule') {
@ -30,6 +52,10 @@ export class CacheCreator {
} }
async alarm(): Promise<void> { async alarm(): Promise<void> {
;(globalThis as any).ENV = this.env
if (this.env?.DB) {
initDb(this.env.DB)
}
const lastTrigger = await this.state.storage.get(LAST_TRIGGER_KEY) const lastTrigger = await this.state.storage.get(LAST_TRIGGER_KEY)
if (!lastTrigger) { if (!lastTrigger) {
return return

View file

@ -1,294 +1,294 @@
// Postgres Importer - Intermediate layer to avoid direct postgresService imports in dbService // // Postgres Importer - Intermediate layer to avoid direct postgresService imports in dbService
// This file re-exports everything from postgresService // // This file re-exports everything from postgresService
//
// Re-export database connection // // Re-export database connection
export { db } from 'postgresService' // export { db } from 'postgresService'
//
// Re-export all schema exports // // Re-export all schema exports
export * from 'postgresService' // export * from 'postgresService'
//
// Re-export all helper methods from postgresService // // Re-export all helper methods from postgresService
export { // export {
// Admin - Banner // // Admin - Banner
getBanners, // getBanners,
getBannerById, // getBannerById,
createBanner, // createBanner,
updateBanner, // updateBanner,
deleteBanner, // deleteBanner,
// Admin - Complaint // // Admin - Complaint
getComplaints, // getComplaints,
resolveComplaint, // resolveComplaint,
// Admin - Constants // // Admin - Constants
getAllConstants, // getAllConstants,
upsertConstants, // upsertConstants,
// Admin - Coupon // // Admin - Coupon
getAllCoupons, // getAllCoupons,
getCouponById, // getCouponById,
invalidateCoupon, // invalidateCoupon,
validateCoupon, // validateCoupon,
getReservedCoupons, // getReservedCoupons,
getUsersForCoupon, // getUsersForCoupon,
createCouponWithRelations, // createCouponWithRelations,
updateCouponWithRelations, // updateCouponWithRelations,
generateCancellationCoupon, // generateCancellationCoupon,
createReservedCouponWithProducts, // createReservedCouponWithProducts,
createCouponForUser, // createCouponForUser,
checkUsersExist, // checkUsersExist,
checkCouponExists, // checkCouponExists,
checkReservedCouponExists, // checkReservedCouponExists,
getOrderWithUser, // getOrderWithUser,
// Admin - Order // // Admin - Order
updateOrderNotes, // updateOrderNotes,
getOrderDetails, // getOrderDetails,
updateOrderPackaged, // updateOrderPackaged,
updateOrderDelivered, // updateOrderDelivered,
updateOrderItemPackaging, // updateOrderItemPackaging,
removeDeliveryCharge, // removeDeliveryCharge,
getSlotOrders, // getSlotOrders,
updateAddressCoords, // updateAddressCoords,
getAllOrders, // getAllOrders,
rebalanceSlots, // rebalanceSlots,
cancelOrder, // cancelOrder,
deleteOrderById, // deleteOrderById,
// Admin - Product // // Admin - Product
getAllProducts, // getAllProducts,
getProductById, // getProductById,
deleteProduct, // deleteProduct,
createProduct, // createProduct,
updateProduct, // updateProduct,
checkProductExistsByName, // checkProductExistsByName,
checkUnitExists, // checkUnitExists,
getProductImagesById, // getProductImagesById,
createSpecialDealsForProduct, // createSpecialDealsForProduct,
updateProductDeals, // updateProductDeals,
replaceProductTags, // replaceProductTags,
toggleProductOutOfStock, // toggleProductOutOfStock,
updateSlotProducts, // updateSlotProducts,
getSlotProductIds, // getSlotProductIds,
getSlotsProductIds, // getSlotsProductIds,
getAllUnits, // getAllUnits,
getAllProductTags, // getAllProductTags,
getAllProductTagInfos, // getAllProductTagInfos,
getProductTagInfoById, // getProductTagInfoById,
createProductTag, // createProductTag,
getProductTagById, // getProductTagById,
updateProductTag, // updateProductTag,
deleteProductTag, // deleteProductTag,
checkProductTagExistsByName, // checkProductTagExistsByName,
getProductReviews, // getProductReviews,
respondToReview, // respondToReview,
getAllProductGroups, // getAllProductGroups,
createProductGroup, // createProductGroup,
updateProductGroup, // updateProductGroup,
deleteProductGroup, // deleteProductGroup,
addProductToGroup, // addProductToGroup,
removeProductFromGroup, // removeProductFromGroup,
updateProductPrices, // updateProductPrices,
// Admin - Slots // // Admin - Slots
getActiveSlotsWithProducts, // getActiveSlotsWithProducts,
getActiveSlots, // getActiveSlots,
getSlotsAfterDate, // getSlotsAfterDate,
getSlotByIdWithRelations, // getSlotByIdWithRelations,
createSlotWithRelations, // createSlotWithRelations,
updateSlotWithRelations, // updateSlotWithRelations,
deleteSlotById, // deleteSlotById,
updateSlotCapacity, // updateSlotCapacity,
getSlotDeliverySequence, // getSlotDeliverySequence,
updateSlotDeliverySequence, // updateSlotDeliverySequence,
// Admin - Staff User // // Admin - Staff User
getStaffUserByName, // getStaffUserByName,
getStaffUserById, // getStaffUserById,
getAllStaff, // getAllStaff,
getAllUsers, // getAllUsers,
getUserWithDetails, // getUserWithDetails,
updateUserSuspensionStatus, // updateUserSuspensionStatus,
checkStaffUserExists, // checkStaffUserExists,
checkStaffRoleExists, // checkStaffRoleExists,
createStaffUser, // createStaffUser,
getAllRoles, // getAllRoles,
// Admin - Store // // Admin - Store
getAllStores, // getAllStores,
getStoreById, // getStoreById,
createStore, // createStore,
updateStore, // updateStore,
deleteStore, // deleteStore,
// Admin - User // // Admin - User
createUserByMobile, // createUserByMobile,
getUserByMobile, // getUserByMobile,
getUnresolvedComplaintsCount, // getUnresolvedComplaintsCount,
getAllUsersWithFilters, // getAllUsersWithFilters,
getOrderCountsByUserIds, // getOrderCountsByUserIds,
getLastOrdersByUserIds, // getLastOrdersByUserIds,
getSuspensionStatusesByUserIds, // getSuspensionStatusesByUserIds,
getUserBasicInfo, // getUserBasicInfo,
getUserSuspensionStatus, // getUserSuspensionStatus,
getUserOrders, // getUserOrders,
getOrderStatusesByOrderIds, // getOrderStatusesByOrderIds,
getItemCountsByOrderIds, // getItemCountsByOrderIds,
upsertUserSuspension, // upsertUserSuspension,
searchUsers, // searchUsers,
getAllNotifCreds, // getAllNotifCreds,
getAllUnloggedTokens, // getAllUnloggedTokens,
getNotifTokensByUserIds, // getNotifTokensByUserIds,
getUserIncidentsWithRelations, // getUserIncidentsWithRelations,
createUserIncident, // createUserIncident,
// Admin - Vendor Snippets // // Admin - Vendor Snippets
checkVendorSnippetExists, // checkVendorSnippetExists,
getVendorSnippetById, // getVendorSnippetById,
getVendorSnippetByCode, // getVendorSnippetByCode,
getAllVendorSnippets, // getAllVendorSnippets,
createVendorSnippet, // createVendorSnippet,
updateVendorSnippet, // updateVendorSnippet,
deleteVendorSnippet, // deleteVendorSnippet,
getProductsByIds, // getProductsByIds,
getVendorSlotById, // getVendorSlotById,
getVendorOrdersBySlotId, // getVendorOrdersBySlotId,
getOrderItemsByOrderIds, // getOrderItemsByOrderIds,
getOrderStatusByOrderIds, // getOrderStatusByOrderIds,
updateVendorOrderItemPackaging, // updateVendorOrderItemPackaging,
getVendorOrders, // getVendorOrders,
// User - Address // // User - Address
getUserDefaultAddress, // getUserDefaultAddress,
getUserAddresses, // getUserAddresses,
getUserAddressById, // getUserAddressById,
clearUserDefaultAddress, // clearUserDefaultAddress,
createUserAddress, // createUserAddress,
updateUserAddress, // updateUserAddress,
deleteUserAddress, // deleteUserAddress,
hasOngoingOrdersForAddress, // hasOngoingOrdersForAddress,
// User - Banners // // User - Banners
getUserActiveBanners, // getUserActiveBanners,
// User - Cart // // User - Cart
getUserCartItemsWithProducts, // getUserCartItemsWithProducts,
getUserProductById, // getUserProductById,
getUserCartItemByUserProduct, // getUserCartItemByUserProduct,
incrementUserCartItemQuantity, // incrementUserCartItemQuantity,
insertUserCartItem, // insertUserCartItem,
updateUserCartItemQuantity, // updateUserCartItemQuantity,
deleteUserCartItem, // deleteUserCartItem,
clearUserCart, // clearUserCart,
// User - Complaint // // User - Complaint
getUserComplaints, // getUserComplaints,
createUserComplaint, // createUserComplaint,
// User - Stores // // User - Stores
getUserStoreSummaries, // getUserStoreSummaries,
getUserStoreDetail, // getUserStoreDetail,
// User - Product // // User - Product
getUserProductDetailById, // getUserProductDetailById,
getUserProductReviews, // getUserProductReviews,
getUserProductByIdBasic, // getUserProductByIdBasic,
createUserProductReview, // createUserProductReview,
getAllProductsWithUnits, // getAllProductsWithUnits,
type ProductSummaryData, // type ProductSummaryData,
// User - Slots // // User - Slots
getUserActiveSlotsList, // getUserActiveSlotsList,
getUserProductAvailability, // getUserProductAvailability,
// User - Payments // // User - Payments
getUserPaymentOrderById, // getUserPaymentOrderById,
getUserPaymentByOrderId, // getUserPaymentByOrderId,
getUserPaymentByMerchantOrderId, // getUserPaymentByMerchantOrderId,
updateUserPaymentSuccess, // updateUserPaymentSuccess,
updateUserOrderPaymentStatus, // updateUserOrderPaymentStatus,
markUserPaymentFailed, // markUserPaymentFailed,
// User - Auth // // User - Auth
getUserAuthByEmail, // getUserAuthByEmail,
getUserAuthByMobile, // getUserAuthByMobile,
getUserAuthById, // getUserAuthById,
getUserAuthCreds, // getUserAuthCreds,
getUserAuthDetails, // getUserAuthDetails,
isUserSuspended, // isUserSuspended,
createUserAuthWithCreds, // createUserAuthWithCreds,
createUserAuthWithMobile, // createUserAuthWithMobile,
upsertUserAuthPassword, // upsertUserAuthPassword,
deleteUserAuthAccount, // deleteUserAuthAccount,
// UV API helpers // // UV API helpers
createUserWithProfile, // createUserWithProfile,
getUserDetailsByUserId, // getUserDetailsByUserId,
updateUserProfile, // updateUserProfile,
// User - Coupon // // User - Coupon
getUserActiveCouponsWithRelations, // getUserActiveCouponsWithRelations,
getUserAllCouponsWithRelations, // getUserAllCouponsWithRelations,
getUserReservedCouponByCode, // getUserReservedCouponByCode,
redeemUserReservedCoupon, // redeemUserReservedCoupon,
// User - Profile // // User - Profile
getUserProfileById, // getUserProfileById,
getUserProfileDetailById, // getUserProfileDetailById,
getUserWithCreds, // getUserWithCreds,
getUserNotifCred, // getUserNotifCred,
upsertUserNotifCred, // upsertUserNotifCred,
deleteUserUnloggedToken, // deleteUserUnloggedToken,
getUserUnloggedToken, // getUserUnloggedToken,
upsertUserUnloggedToken, // upsertUserUnloggedToken,
// User - Order // // User - Order
validateAndGetUserCoupon, // validateAndGetUserCoupon,
applyDiscountToUserOrder, // applyDiscountToUserOrder,
getUserAddressByIdAndUser, // getUserAddressByIdAndUser,
getOrderProductById, // getOrderProductById,
checkUserSuspended, // checkUserSuspended,
getUserSlotCapacityStatus, // getUserSlotCapacityStatus,
placeUserOrderTransaction, // placeUserOrderTransaction,
deleteUserCartItemsForOrder, // deleteUserCartItemsForOrder,
recordUserCouponUsage, // recordUserCouponUsage,
getUserOrdersWithRelations, // getUserOrdersWithRelations,
getUserOrderCount, // getUserOrderCount,
getUserOrderByIdWithRelations, // getUserOrderByIdWithRelations,
getUserCouponUsageForOrder, // getUserCouponUsageForOrder,
getUserOrderBasic, // getUserOrderBasic,
cancelUserOrderTransaction, // cancelUserOrderTransaction,
updateUserOrderNotes, // updateUserOrderNotes,
getUserRecentlyDeliveredOrderIds, // getUserRecentlyDeliveredOrderIds,
getUserProductIdsFromOrders, // getUserProductIdsFromOrders,
getUserProductsForRecentOrders, // getUserProductsForRecentOrders,
// Store Helpers // // Store Helpers
getAllBannersForCache, // getAllBannersForCache,
getAllProductsForCache, // getAllProductsForCache,
getAllStoresForCache, // getAllStoresForCache,
getAllDeliverySlotsForCache, // getAllDeliverySlotsForCache,
getAllSpecialDealsForCache, // getAllSpecialDealsForCache,
getAllProductTagsForCache, // getAllProductTagsForCache,
getAllTagsForCache, // getAllTagsForCache,
getAllTagProductMappings, // getAllTagProductMappings,
getAllSlotsWithProductsForCache, // getAllSlotsWithProductsForCache,
getAllUserNegativityScores, // getAllUserNegativityScores,
getUserNegativityScore, // getUserNegativityScore,
type BannerData, // type BannerData,
type ProductBasicData, // type ProductBasicData,
type StoreBasicData, // type StoreBasicData,
type DeliverySlotData, // type DeliverySlotData,
type SpecialDealData, // type SpecialDealData,
type ProductTagData, // type ProductTagData,
type TagBasicData, // type TagBasicData,
type TagProductMapping, // type TagProductMapping,
type SlotWithProductsData, // type SlotWithProductsData,
type UserNegativityData, // type UserNegativityData,
// Automated Jobs // // Automated Jobs
toggleFlashDeliveryForItems, // toggleFlashDeliveryForItems,
toggleKeyVal, // toggleKeyVal,
getAllKeyValStore, // getAllKeyValStore,
// Post-order handler helpers // // Post-order handler helpers
getOrdersByIdsWithFullData, // getOrdersByIdsWithFullData,
getOrderByIdWithFullData, // getOrderByIdWithFullData,
type OrderWithFullData, // type OrderWithFullData,
type OrderWithCancellationData, // type OrderWithCancellationData,
// Common API helpers // // Common API helpers
getSuspendedProductIds, // getSuspendedProductIds,
getNextDeliveryDateWithCapacity, // getNextDeliveryDateWithCapacity,
getStoresSummary, // getStoresSummary,
healthCheck, // healthCheck,
// Delete orders helper // // Delete orders helper
deleteOrdersWithRelations, // deleteOrdersWithRelations,
// Seed helpers // // Seed helpers
seedUnits, // seedUnits,
seedStaffRoles, // seedStaffRoles,
seedStaffPermissions, // seedStaffPermissions,
seedRolePermissions, // seedRolePermissions,
seedKeyValStore, // seedKeyValStore,
type UnitSeedData, // type UnitSeedData,
type RolePermissionAssignment, // type RolePermissionAssignment,
type KeyValSeedData, // type KeyValSeedData,
type StaffRoleName, // type StaffRoleName,
type StaffPermissionName, // type StaffPermissionName,
// Upload URL Helpers // // Upload URL Helpers
createUploadUrlStatus, // createUploadUrlStatus,
claimUploadUrlStatus, // claimUploadUrlStatus,
} from 'postgresService' // } from 'postgresService'

View file

@ -2,7 +2,17 @@
// This file re-exports everything from sqliteService // This file re-exports everything from sqliteService
// Re-export database connection // Re-export database connection
export { db, initDb } from 'sqliteService' import type { D1Database } from '@cloudflare/workers-types'
import { db, initDb as initDbBase } from 'sqliteService'
export { db }
let dbInitialized = false
export const initDb = (database: D1Database) => {
if (dbInitialized) return
initDbBase(database)
dbInitialized = true
}
// Re-export all schema exports // Re-export all schema exports
export * from 'sqliteService' export * from 'sqliteService'

View file

@ -42,7 +42,8 @@ export const initializeAllStores = async (): Promise<void> => {
} }
}; };
export const scheduleStoreInitialization = (): void => { export const scheduleStoreInitialization = async (): Promise<void> => {
console.log("scheduling store initialization")
const env = (globalThis as { ENV?: { CACHE_CREATOR?: DurableObjectNamespace } }).ENV const env = (globalThis as { ENV?: { CACHE_CREATOR?: DurableObjectNamespace } }).ENV
if (!env?.CACHE_CREATOR) { if (!env?.CACHE_CREATOR) {
console.warn('CACHE_CREATOR durable object binding not available for store initialization') console.warn('CACHE_CREATOR durable object binding not available for store initialization')
@ -50,6 +51,11 @@ export const scheduleStoreInitialization = (): void => {
} }
const id = env.CACHE_CREATOR.idFromName('store-init') const id = env.CACHE_CREATOR.idFromName('store-init')
const stub = env.CACHE_CREATOR.get(id) // const stub = env.CACHE_CREATOR.get(id)
void stub.fetch('https://cache-creator/schedule', { method: 'POST' }) const stub = env.CACHE_CREATOR.getByName('store-init')
try {
await stub.fetch('https://cache-creator/schedule', { method: 'POST' })
} catch (error) {
console.error('Failed to schedule store initialization:', error)
}
} }

View file

@ -137,7 +137,7 @@ export const bannerRouter = router({
*/ */
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return banner; return banner;
} catch (error) { } catch (error) {
@ -204,7 +204,7 @@ export const bannerRouter = router({
*/ */
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return banner; return banner;
} catch (error) { } catch (error) {
@ -226,7 +226,7 @@ export const bannerRouter = router({
*/ */
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { success: true }; return { success: true };
}), }),

View file

@ -169,7 +169,7 @@ export const productRouter = router({
} }
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: 'Product deleted successfully', message: 'Product deleted successfully',
@ -208,7 +208,7 @@ export const productRouter = router({
throw new ApiError('Product not found', 404) throw new ApiError('Product not found', 404)
} }
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
product: updatedProduct, product: updatedProduct,
@ -282,7 +282,7 @@ export const productRouter = router({
await Promise.all(uploadUrls.map(url => claimUploadUrl(url))) await Promise.all(uploadUrls.map(url => claimUploadUrl(url)))
} }
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
product: newProduct, product: newProduct,
@ -370,7 +370,7 @@ export const productRouter = router({
await Promise.all(uploadUrls.map(url => claimUploadUrl(url))) await Promise.all(uploadUrls.map(url => claimUploadUrl(url)))
} }
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
product: updatedProduct, product: updatedProduct,
@ -430,7 +430,7 @@ export const productRouter = router({
} }
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: "Slot products updated successfully", message: "Slot products updated successfully",
@ -439,7 +439,7 @@ export const productRouter = router({
}; };
*/ */
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: 'Slot products updated successfully', message: 'Slot products updated successfully',
@ -701,7 +701,7 @@ export const productRouter = router({
} }
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
group: newGroup, group: newGroup,
@ -709,7 +709,7 @@ export const productRouter = router({
}; };
*/ */
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
group: newGroup, group: newGroup,
@ -761,7 +761,7 @@ export const productRouter = router({
} }
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
group: updatedGroup, group: updatedGroup,
@ -773,7 +773,7 @@ export const productRouter = router({
throw new ApiError('Group not found', 404) throw new ApiError('Group not found', 404)
} }
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
group: updatedGroup, group: updatedGroup,
@ -806,7 +806,7 @@ export const productRouter = router({
} }
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: 'Group deleted successfully', message: 'Group deleted successfully',
@ -817,7 +817,7 @@ export const productRouter = router({
throw new ApiError('Group not found', 404) throw new ApiError('Group not found', 404)
} }
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: 'Group deleted successfully', message: 'Group deleted successfully',
@ -881,7 +881,7 @@ export const productRouter = router({
await Promise.all(updatePromises); await Promise.all(updatePromises);
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: `Updated prices for ${updates.length} product(s)`, message: `Updated prices for ${updates.length} product(s)`,
@ -893,7 +893,7 @@ export const productRouter = router({
throw new ApiError(`Invalid product IDs: ${result.invalidIds.join(', ')}`, 400) throw new ApiError(`Invalid product IDs: ${result.invalidIds.join(', ')}`, 400)
} }
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: `Updated prices for ${result.updatedCount} product(s)`, message: `Updated prices for ${result.updatedCount} product(s)`,
@ -967,7 +967,7 @@ export const productRouter = router({
await Promise.all(uploadUrls.map((url) => claimUploadUrl(url))) await Promise.all(uploadUrls.map((url) => claimUploadUrl(url)))
} }
scheduleStoreInitialization() await scheduleStoreInitialization()
const { products, ...createdTagInfo } = createdTag const { products, ...createdTagInfo } = createdTag
@ -1017,7 +1017,7 @@ export const productRouter = router({
await Promise.all(uploadUrls.map((url) => claimUploadUrl(url))) await Promise.all(uploadUrls.map((url) => claimUploadUrl(url)))
} }
scheduleStoreInitialization() await scheduleStoreInitialization()
const { products, ...updatedTagInfo } = updatedTag const { products, ...updatedTagInfo } = updatedTag
@ -1045,7 +1045,7 @@ export const productRouter = router({
await deleteProductTagInDb(input.id) await deleteProductTagInDb(input.id)
scheduleStoreInitialization() await scheduleStoreInitialization()
return { message: 'Tag deleted successfully' } return { message: 'Tag deleted successfully' }
}), }),

View file

@ -256,7 +256,7 @@ export const slotsRouter = router({
} }
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: "Slot products updated successfully", message: "Slot products updated successfully",
@ -265,7 +265,7 @@ export const slotsRouter = router({
}; };
*/ */
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: result.message, message: result.message,
@ -360,7 +360,7 @@ export const slotsRouter = router({
*/ */
// Reinitialize stores to reflect changes (outside transaction) // Reinitialize stores to reflect changes (outside transaction)
scheduleStoreInitialization() await scheduleStoreInitialization()
return result return result
}), }),
@ -543,7 +543,7 @@ export const slotsRouter = router({
} }
// Reinitialize stores to reflect changes (outside transaction) // Reinitialize stores to reflect changes (outside transaction)
scheduleStoreInitialization() await scheduleStoreInitialization()
return result return result
} }
@ -582,7 +582,7 @@ export const slotsRouter = router({
} }
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
message: 'Slot deleted successfully', message: 'Slot deleted successfully',
@ -717,7 +717,7 @@ export const slotsRouter = router({
} }
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
success: true, success: true,
@ -730,7 +730,7 @@ export const slotsRouter = router({
throw new ApiError('Slot not found', 404) throw new ApiError('Slot not found', 404)
} }
scheduleStoreInitialization() await scheduleStoreInitialization()
return result return result
}), }),

View file

@ -93,7 +93,7 @@ export const storeRouter = router({
*/ */
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
store: newStore, store: newStore,
@ -184,7 +184,7 @@ export const storeRouter = router({
*/ */
// Reinitialize stores to reflect changes // Reinitialize stores to reflect changes
scheduleStoreInitialization() await scheduleStoreInitialization()
return { return {
store: updatedStore, store: updatedStore,
@ -227,7 +227,7 @@ export const storeRouter = router({
*/ */
// Reinitialize stores to reflect changes (outside transaction) // Reinitialize stores to reflect changes (outside transaction)
scheduleStoreInitialization() await scheduleStoreInitialization()
return result; return result;
}), }),

View file

@ -7,7 +7,6 @@ import { scaffoldAssetUrl } from '@/src/lib/s3-client'
import { import {
getUserProfileById as getUserProfileByIdInDb, getUserProfileById as getUserProfileByIdInDb,
getUserProfileDetailById as getUserProfileDetailByIdInDb, getUserProfileDetailById as getUserProfileDetailByIdInDb,
getUserWithCreds as getUserWithCredsInDb,
upsertUserNotifCred as upsertUserNotifCredInDb, upsertUserNotifCred as upsertUserNotifCredInDb,
deleteUserUnloggedToken as deleteUserUnloggedTokenInDb, deleteUserUnloggedToken as deleteUserUnloggedTokenInDb,
getUserUnloggedToken as getUserUnloggedTokenInDb, getUserUnloggedToken as getUserUnloggedTokenInDb,
@ -15,7 +14,6 @@ import {
} from '@/src/dbService' } from '@/src/dbService'
import type { import type {
UserSelfDataResponse, UserSelfDataResponse,
UserProfileCompleteResponse,
UserSavePushTokenResponse, UserSavePushTokenResponse,
} from '@packages/shared' } from '@packages/shared'
@ -69,25 +67,6 @@ export const userRouter = router({
} }
}), }),
checkProfileComplete: protectedProcedure
.query(async ({ ctx }): Promise<UserProfileCompleteResponse> => {
const userId = ctx.user.userId;
if (!userId) {
throw new ApiError('User not authenticated', 401);
}
const result = await getUserWithCredsInDb(userId)
if (!result) {
throw new ApiError('User not found', 404)
}
return {
isComplete: !!(result.user.name && result.user.email && result.creds),
};
}),
savePushToken: publicProcedure savePushToken: publicProcedure
.input(z.object({ token: z.string() })) .input(z.object({ token: z.string() }))
.mutation(async ({ input, ctx }): Promise<UserSavePushTokenResponse> => { .mutation(async ({ input, ctx }): Promise<UserSavePushTokenResponse> => {

View file

@ -4,6 +4,8 @@ import type {
DurableObjectNamespace, DurableObjectNamespace,
} from '@cloudflare/workers-types' } from '@cloudflare/workers-types'
import { CacheCreator } from './src/jobs/cache-creator' import { CacheCreator } from './src/jobs/cache-creator'
import { createApp } from './src/app'
import { initDb } from './src/dbService'
import { import {
handleNotifQueue, handleNotifQueue,
handleOrderPlacedQueue, handleOrderPlacedQueue,
@ -31,8 +33,6 @@ export default {
ctx: ExecutionContext ctx: ExecutionContext
) { ) {
;(globalThis as any).ENV = env ;(globalThis as any).ENV = env
const { createApp } = await import('./src/app')
const { initDb } = await import('./src/dbService')
if (env.DB) { if (env.DB) {
initDb(env.DB) initDb(env.DB)
} }

View file

@ -2,37 +2,58 @@ name = "freshyo-backend"
main = "worker.ts" main = "worker.ts"
compatibility_date = "2024-12-01" compatibility_date = "2024-12-01"
compatibility_flags = ["nodejs_compat"] compatibility_flags = ["nodejs_compat"]
routes = [
{ pattern = "api.freshyo.in/*", zone_name = "freshyo.in" }
]
[[d1_databases]] [[d1_databases]]
binding = "DB" binding = "DB"
database_name = "freshyo-dev" database_name = "freshyo-dev"
database_id = "45e81d12-9043-45ad-a8ba-3b93127dc5ea" database_id = "ed09e4a2-4b36-472f-8ff3-dd6c704b1b99"
[durable_objects] [durable_objects]
bindings = [ bindings = [
{ name = "CACHE_CREATOR", class_name = "CacheCreator" }, { name = "CACHE_CREATOR", class_name = "CacheCreator" },
] ]
[[migrations]]
tag = "cache-creator-v1"
new_classes = ["CacheCreator"]
[[queues.producers]] [[queues.producers]]
binding = "NOTIF_QUEUE" binding = "NOTIF_QUEUE"
queue = "notif_queue" queue = "notif-queue-dev"
[[queues.producers]] [[queues.producers]]
binding = "ORDER_PLACED_QUEUE" binding = "ORDER_PLACED_QUEUE"
queue = "order_placed_queue" queue = "order-placed-queue-dev"
[[queues.producers]] [[queues.producers]]
binding = "ORDER_CANCELLED_QUEUE" binding = "ORDER_CANCELLED_QUEUE"
queue = "order_cancelled_queue" queue = "order-cancelled-queue-dev"
[[queues.consumers]] [[queues.consumers]]
queue = "notif_queue" queue = "notif-queue-dev"
[[queues.consumers]] [[queues.consumers]]
queue = "order_placed_queue" queue = "order-placed-queue-dev"
[[queues.consumers]] [[queues.consumers]]
queue = "order_cancelled_queue" queue = "order-cancelled-queue-dev"
[observability]
enabled = false
head_sampling_rate = 1
[observability.logs]
enabled = true
head_sampling_rate = 1
persist = true
invocation_logs = true
[observability.traces]
enabled = false
persist = true
head_sampling_rate = 1
[vars] [vars]
ENV_MODE = "PROD" ENV_MODE = "PROD"

BIN
apps/test2.sqlite Normal file

Binary file not shown.

Binary file not shown.

View file

@ -9,7 +9,6 @@ import { LinearGradient } from "expo-linear-gradient";
import { Ionicons } from "@expo/vector-icons"; import { Ionicons } from "@expo/vector-icons";
import { useAuth } from "@/src/contexts/AuthContext"; import { useAuth } from "@/src/contexts/AuthContext";
import { tw, theme, MyTouchableOpacity, MyText } from "common-ui"; import { tw, theme, MyTouchableOpacity, MyText } from "common-ui";
import ProfileChecker from "@/components/ProfileChecker";
import HomeIcon from "@/components/icons/HomeIcon"; import HomeIcon from "@/components/icons/HomeIcon";
import StoresIcon from "@/components/icons/StoresIcon"; import StoresIcon from "@/components/icons/StoresIcon";
import OrderAgainIcon from "@/components/icons/OrderAgainIcon"; import OrderAgainIcon from "@/components/icons/OrderAgainIcon";
@ -114,7 +113,6 @@ export default function Layout() {
}} }}
/> />
</Tabs> </Tabs>
<ProfileChecker />
</> </>
); );
} }

View file

@ -9,6 +9,7 @@ import { trpc } from '@/src/trpc-client';
import { Image } from 'expo-image'; import { Image } from 'expo-image';
import { orderStatusManipulator } from '@/src/lib/string-manipulators'; import { orderStatusManipulator } from '@/src/lib/string-manipulators';
import { useGetEssentialConsts } from '@/src/hooks/prominent-api-hooks'; import { useGetEssentialConsts } from '@/src/hooks/prominent-api-hooks';
import { useUserDetails } from '@/src/contexts/AuthContext';
interface OrderItem { interface OrderItem {
productName: string; productName: string;
@ -42,10 +43,13 @@ interface Order {
export default function NextOrderGlimpse() { export default function NextOrderGlimpse() {
const router = useRouter(); const router = useRouter();
const { setNavigationTarget } = useNavigationTarget(); const { setNavigationTarget } = useNavigationTarget();
const userDetails = useUserDetails();
const { data: ordersData, isLoading: ordersLoading } = trpc.user.order.getOrders.useQuery({ const { data: ordersData, isLoading: ordersLoading } = trpc.user.order.getOrders.useQuery({
page: 1, page: 1,
pageSize: 50, pageSize: 50,
}, {
enabled: !!userDetails,
}); });
const { data: essentialConsts } = useGetEssentialConsts(); const { data: essentialConsts } = useGetEssentialConsts();
@ -76,6 +80,10 @@ export default function NextOrderGlimpse() {
const nextOrder = upcomingOrders[0] || null; const nextOrder = upcomingOrders[0] || null;
if (!userDetails) {
return null;
}
if (ordersLoading) { if (ordersLoading) {
return ( return (
<View style={tw`px-6 mb-4`}> <View style={tw`px-6 mb-4`}>

Binary file not shown.

View file

@ -54,7 +54,6 @@ export function useAllProducts() {
export function useStores() { export function useStores() {
const cacheUrl = useCacheUrl(CACHE_FILENAMES.stores) const cacheUrl = useCacheUrl(CACHE_FILENAMES.stores)
console.log(cacheUrl)
return useQuery<StoresResponse>({ return useQuery<StoresResponse>({
queryKey: ['stores', cacheUrl], queryKey: ['stores', cacheUrl],
queryFn: async () => { queryFn: async () => {

View file

@ -129,7 +129,7 @@
"zod": "^4.1.12", "zod": "^4.1.12",
}, },
"devDependencies": { "devDependencies": {
"@cloudflare/workers-types": "^4.20260304.0", "@cloudflare/workers-types": "^4.20260401.1",
"@types/node": "^24.5.2", "@types/node": "^24.5.2",
"rimraf": "^6.1.2", "rimraf": "^6.1.2",
"ts-node-dev": "^2.0.0", "ts-node-dev": "^2.0.0",
@ -3553,6 +3553,8 @@
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"backend/@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260401.1", "", {}, "sha512-tKBeV/ySfJjbO0qMKkFrstHDdWzZHAcW4vCpO5QaqjB/667y9lhZt9gZyTKeJ0gluIBwpeQ/efBjqRLqpkgw9g=="],
"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/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=="], "backend/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],

View file

@ -66,11 +66,11 @@ export async function incrementCacheVersion(): Promise<number> {
if (existing) { if (existing) {
await tx.update(keyValStore) await tx.update(keyValStore)
.set({ value: nextValue }) .set({ value: nextValue +'' })
.where(eq(keyValStore.key, CACHE_VERSION_KEY)) .where(eq(keyValStore.key, CACHE_VERSION_KEY))
} else { } else {
await tx.insert(keyValStore) await tx.insert(keyValStore)
.values({ key: CACHE_VERSION_KEY, value: nextValue }) .values({ key: CACHE_VERSION_KEY, value: nextValue+'' })
} }
return nextValue return nextValue

View file

@ -46,7 +46,7 @@ const numericText = (name: string) =>
})(name) })(name)
const timestampText = (name: string) => const timestampText = (name: string) =>
customType<{ data: Date | null; driverData: string | number | null }>({ customType<{ data: Date; driverData: string | number | null }>({
dataType() { dataType() {
return 'text' return 'text'
}, },
@ -56,8 +56,8 @@ const timestampText = (name: string) =>
return String(value) return String(value)
}, },
fromDriver(value) { fromDriver(value) {
if (value === null || value === undefined) return null if (value === null || value === undefined) return new Date(0)
return coerceDate(value) return coerceDate(value) || new Date(0)
}, },
})(name) })(name)

View file

@ -1,6 +1,7 @@
import { db } from '../db/db_index' import { db } from '../db/db_index'
import { productInfo, keyValStore } from '../db/schema' import { productInfo, keyValStore } from '../db/schema'
import { inArray, eq } from 'drizzle-orm' import { inArray, eq } from 'drizzle-orm'
import { castConstValue } from '../lib/const-keys'
/** /**
* Toggle flash delivery availability for specific products * Toggle flash delivery availability for specific products
@ -28,7 +29,7 @@ export async function toggleKeyVal(
): Promise<void> { ): Promise<void> {
await db await db
.update(keyValStore) .update(keyValStore)
.set({ value }) .set({ value: value+'' })
.where(eq(keyValStore.key, key)) .where(eq(keyValStore.key, key))
} }
@ -37,5 +38,9 @@ export async function toggleKeyVal(
* @returns Array of all key-value pairs * @returns Array of all key-value pairs
*/ */
export async function getAllKeyValStore(): Promise<Array<{ key: string; value: any }>> { export async function getAllKeyValStore(): Promise<Array<{ key: string; value: any }>> {
return db.select().from(keyValStore) const records = await db.select().from(keyValStore)
return records.map((record) => ({
key: record.key,
value: castConstValue(record.key, record.value),
}))
} }

View file

@ -8,8 +8,8 @@ type SlotRow = InferSelectModel<typeof deliverySlotInfo>
const mapSlot = (slot: SlotRow): UserDeliverySlot => ({ const mapSlot = (slot: SlotRow): UserDeliverySlot => ({
id: slot.id, id: slot.id,
deliveryTime: slot.deliveryTime, deliveryTime: slot.deliveryTime!,
freezeTime: slot.freezeTime, freezeTime: slot.freezeTime!,
isActive: slot.isActive, isActive: slot.isActive,
isFlash: slot.isFlash, isFlash: slot.isFlash,
isCapacityFull: slot.isCapacityFull, isCapacityFull: slot.isCapacityFull,

Binary file not shown.

View file

@ -1,4 +1,4 @@
import { Client } from 'pg'; import { Client, types as pgTypes } from 'pg';
import Database from 'better-sqlite3'; import Database from 'better-sqlite3';
import { postgresConfig, sqliteConfig, migrationConfig, logConfig } from '../config'; import { postgresConfig, sqliteConfig, migrationConfig, logConfig } from '../config';
import * as fs from 'fs'; import * as fs from 'fs';
@ -17,6 +17,74 @@ interface ColumnInfo {
isPrimaryKey: boolean; isPrimaryKey: boolean;
} }
const KOLKATA_OFFSET_MINUTES = 330
const pad = (value: number, size: number = 2) => String(value).padStart(size, '0')
function formatDatePartsInKolkata(
year: number,
month: number,
day: number,
hour: number,
minute: number,
second: number,
millisecond: number
): string {
return `${year}-${pad(month)}-${pad(day)}T${pad(hour)}:${pad(minute)}:${pad(second)}.${pad(millisecond, 3)}Z`
}
function formatDateInKolkata(date: Date): string {
const shifted = new Date(date.getTime() + KOLKATA_OFFSET_MINUTES * 60 * 1000)
return formatDatePartsInKolkata(
shifted.getUTCFullYear(),
shifted.getUTCMonth() + 1,
shifted.getUTCDate(),
shifted.getUTCHours(),
shifted.getUTCMinutes(),
shifted.getUTCSeconds(),
shifted.getUTCMilliseconds()
)
}
function formatStringDateInKolkata(value: string): string | null {
const trimmed = value.trim()
if (!trimmed) return null
const hasTimezone = /[Zz]|[+-]\d{2}:?\d{2}$/.test(trimmed)
if (hasTimezone) {
const parsed = new Date(trimmed)
return Number.isNaN(parsed.getTime()) ? null : formatDateInKolkata(parsed)
}
const match = trimmed.match(
/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,6}))?)?)?$/
)
if (!match) return null
const year = Number(match[1])
const month = Number(match[2])
const day = Number(match[3])
const hour = match[4] ? Number(match[4]) : 0
const minute = match[5] ? Number(match[5]) : 0
const second = match[6] ? Number(match[6]) : 0
const msRaw = match[7] ? match[7].slice(0, 3).padEnd(3, '0') : '000'
const millisecond = Number(msRaw)
if (
Number.isNaN(year) ||
Number.isNaN(month) ||
Number.isNaN(day) ||
Number.isNaN(hour) ||
Number.isNaN(minute) ||
Number.isNaN(second) ||
Number.isNaN(millisecond)
) {
return null
}
return formatDatePartsInKolkata(year, month, day, hour, minute, second, millisecond)
}
/** /**
* Maps PostgreSQL data types to SQLite data types * Maps PostgreSQL data types to SQLite data types
*/ */
@ -224,13 +292,27 @@ async function migrateTableData(
); );
const insertMany = sqliteDb.transaction((rows) => { const insertMany = sqliteDb.transaction((rows) => {
console.log(rows.at(-1))
for (const row of rows) { for (const row of rows) {
const values = columns.map(col => { const values = columns.map(col => {
const val = row[col.name]; const val = row[col.name];
// Handle special cases // Handle special cases
if (val === null || val === undefined) return null; if (val === null || val === undefined) return null;
if (typeof val === 'boolean') return val ? 1 : 0; if (typeof val === 'boolean') return val ? 1 : 0;
if (val instanceof Date) return val.toISOString(); if (val instanceof Date) {
const formattedDate = formatDateInKolkata(val)
console.log({formattedDate, id: row['id']})
return formattedDate
}
if (
typeof val === 'string' &&
(col.type === 'date' || col.type.startsWith('timestamp'))
) {
const formatted = formatStringDateInKolkata(val)
console.log({formatted, id: row['id']})
if (formatted) return formatted
}
if (Array.isArray(val)) return JSON.stringify(val); if (Array.isArray(val)) return JSON.stringify(val);
if (typeof val === 'object') return JSON.stringify(val); if (typeof val === 'object') return JSON.stringify(val);
// Ensure it's a primitive type SQLite can handle // Ensure it's a primitive type SQLite can handle
@ -261,6 +343,14 @@ async function migrateTableData(
async function migratePostgresToSqlite(): Promise<void> { async function migratePostgresToSqlite(): Promise<void> {
console.log('Starting PostgreSQL to SQLite migration...\n'); console.log('Starting PostgreSQL to SQLite migration...\n');
pgTypes.setTypeParser(1114, (value) => value)
pgTypes.setTypeParser(1184, (value) => value)
pgTypes.setTypeParser(1082, (value) => value)
pgTypes.setTypeParser(1114, (value) => value)
pgTypes.setTypeParser(1184, (value) => value)
pgTypes.setTypeParser(1082, (value) => value)
// Ensure SQLite directory exists // Ensure SQLite directory exists
const sqliteDir = path.dirname(sqliteConfig.filename); const sqliteDir = path.dirname(sqliteConfig.filename);
if (!fs.existsSync(sqliteDir)) { if (!fs.existsSync(sqliteDir)) {
@ -287,7 +377,8 @@ async function migratePostgresToSqlite(): Promise<void> {
try { try {
// Get all tables // Get all tables
const tables = await getPostgresTables(pgClient); let tables = await getPostgresTables(pgClient);
// tables = tables.filter(item => item === 'delivery_slot_info')
console.log(`\nFound ${tables.length} tables to migrate\n`); console.log(`\nFound ${tables.length} tables to migrate\n`);
let totalMigrated = 0; let totalMigrated = 0;

View file

@ -65,10 +65,11 @@ const isDevMode = Constants.executionEnvironment !== "standalone";
// 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.5:4000'; // const BASE_API_URL = 'http://192.168.1.5:4000';
const BASE_API_URL = 'http://192.168.1.5:8787'; // const BASE_API_URL = 'http://192.168.1.5:8787';
// let BASE_API_URL = "https://mf.freshyo.in"; // let BASE_API_URL = "https://mf.freshyo.in";
let BASE_API_URL = "https://worker.freshyo.in";
// let BASE_API_URL = "https://freshyo.technocracy.ovh"; // let BASE_API_URL = "https://freshyo.technocracy.ovh";
// let BASE_API_URL = 'http://192.168.100.107:4000'; // let BASE_API_URL = 'http://192.168.100.109:8787';
// let BASE_API_URL = 'http://192.168.29.176:4000'; // let BASE_API_URL = 'http://192.168.29.176:4000';
// if(isDevMode) { // if(isDevMode) {