@timardex/cluemart-server-shared 1.0.161 → 1.0.163
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Relation-BQhULTU-.d.mts +47 -0
- package/dist/Relation-Dvgd2CFi.d.ts +47 -0
- package/dist/{chunk-YJEFAISD.mjs → chunk-RGSAG3WZ.mjs} +4 -2
- package/dist/{chunk-YJEFAISD.mjs.map → chunk-RGSAG3WZ.mjs.map} +1 -1
- package/dist/index.cjs +17 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.mjs +16 -1
- package/dist/index.mjs.map +1 -1
- package/dist/mongoose/index.cjs +2 -1
- package/dist/mongoose/index.cjs.map +1 -1
- package/dist/mongoose/index.d.mts +3 -44
- package/dist/mongoose/index.d.ts +3 -44
- package/dist/mongoose/index.mjs +1 -1
- package/dist/service/index.cjs +17 -1
- package/dist/service/index.cjs.map +1 -1
- package/dist/service/index.d.mts +9 -2
- package/dist/service/index.d.ts +9 -2
- package/dist/service/index.mjs +16 -1
- package/dist/service/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/service/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { f as SchemaCreateBulkNotificationInput, O as ObjectId } from '../Chat-Ctmtatmi.mjs';
|
|
2
|
-
import { EnumUserLicence } from '@timardex/cluemart-shared';
|
|
2
|
+
import { EnumUserLicence, DateTimeWithPriceType } from '@timardex/cluemart-shared';
|
|
3
|
+
import { S as SchemaRelationType } from '../Relation-BQhULTU-.mjs';
|
|
3
4
|
import 'mongoose';
|
|
4
5
|
import '@timardex/cluemart-shared/types';
|
|
5
6
|
import 'express';
|
|
@@ -51,4 +52,10 @@ type EventOrMarket = {
|
|
|
51
52
|
*/
|
|
52
53
|
declare function findEventOrImportedMarketById(resourceId: ObjectId | string | null | undefined): Promise<EventOrMarket>;
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Helper: Update relationDates based on event's dateTime
|
|
57
|
+
* Marks dates as UNAVAILABLE if they no longer exist in the event's dateTime.
|
|
58
|
+
*/
|
|
59
|
+
declare function updateRelationDatesToUnavailable(relationDates: SchemaRelationType["relationDates"], eventDateTime: DateTimeWithPriceType[] | undefined): SchemaRelationType["relationDates"];
|
|
60
|
+
|
|
61
|
+
export { connectToDatabase, convertObjectIdsToStrings, findEventOrImportedMarketById, saveNotificationsInDb, sendPushNotifications, updateAdStatuses, updateRelationDatesToUnavailable, updateVendorBasedOnUserLicense };
|
package/dist/service/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { f as SchemaCreateBulkNotificationInput, O as ObjectId } from '../Chat-Ctmtatmi.js';
|
|
2
|
-
import { EnumUserLicence } from '@timardex/cluemart-shared';
|
|
2
|
+
import { EnumUserLicence, DateTimeWithPriceType } from '@timardex/cluemart-shared';
|
|
3
|
+
import { S as SchemaRelationType } from '../Relation-Dvgd2CFi.js';
|
|
3
4
|
import 'mongoose';
|
|
4
5
|
import '@timardex/cluemart-shared/types';
|
|
5
6
|
import 'express';
|
|
@@ -51,4 +52,10 @@ type EventOrMarket = {
|
|
|
51
52
|
*/
|
|
52
53
|
declare function findEventOrImportedMarketById(resourceId: ObjectId | string | null | undefined): Promise<EventOrMarket>;
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Helper: Update relationDates based on event's dateTime
|
|
57
|
+
* Marks dates as UNAVAILABLE if they no longer exist in the event's dateTime.
|
|
58
|
+
*/
|
|
59
|
+
declare function updateRelationDatesToUnavailable(relationDates: SchemaRelationType["relationDates"], eventDateTime: DateTimeWithPriceType[] | undefined): SchemaRelationType["relationDates"];
|
|
60
|
+
|
|
61
|
+
export { connectToDatabase, convertObjectIdsToStrings, findEventOrImportedMarketById, saveNotificationsInDb, sendPushNotifications, updateAdStatuses, updateRelationDatesToUnavailable, updateVendorBasedOnUserLicense };
|
package/dist/service/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
ChatModel,
|
|
4
4
|
EnumAdStatus,
|
|
5
5
|
EnumChatType,
|
|
6
|
+
EnumInviteStatus,
|
|
6
7
|
EnumResourceType,
|
|
7
8
|
EnumUserLicence,
|
|
8
9
|
EventModel,
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
PushTokenModel,
|
|
12
13
|
UserModel,
|
|
13
14
|
VendorModel
|
|
14
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-RGSAG3WZ.mjs";
|
|
15
16
|
import "../chunk-3QS3WKRC.mjs";
|
|
16
17
|
|
|
17
18
|
// src/service/database.ts
|
|
@@ -376,6 +377,19 @@ async function findEventOrImportedMarketById(resourceId) {
|
|
|
376
377
|
]);
|
|
377
378
|
return eventDoc ?? googleImportedDoc;
|
|
378
379
|
}
|
|
380
|
+
|
|
381
|
+
// src/service/relations.ts
|
|
382
|
+
function updateRelationDatesToUnavailable(relationDates, eventDateTime) {
|
|
383
|
+
return relationDates.map((relationDate) => {
|
|
384
|
+
const existsInEvent = eventDateTime?.some(
|
|
385
|
+
(dt) => dt.startDate === relationDate.dateTime.startDate && dt.startTime === relationDate.dateTime.startTime
|
|
386
|
+
) ?? false;
|
|
387
|
+
return {
|
|
388
|
+
...relationDate,
|
|
389
|
+
status: existsInEvent ? relationDate.status : EnumInviteStatus.UNAVAILABLE
|
|
390
|
+
};
|
|
391
|
+
});
|
|
392
|
+
}
|
|
379
393
|
export {
|
|
380
394
|
connectToDatabase,
|
|
381
395
|
convertObjectIdsToStrings,
|
|
@@ -383,6 +397,7 @@ export {
|
|
|
383
397
|
saveNotificationsInDb,
|
|
384
398
|
sendPushNotifications,
|
|
385
399
|
updateAdStatuses,
|
|
400
|
+
updateRelationDatesToUnavailable,
|
|
386
401
|
updateVendorBasedOnUserLicense
|
|
387
402
|
};
|
|
388
403
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/service/database.ts","../../src/service/saveNotificationsInDb.ts","../../src/service/sendPushNotifications.ts","../../src/service/updateAdStatus.ts","../../src/service/associate.ts","../../src/service/vendor.ts","../../src/service/objectIdToString.ts","../../src/service/event.ts"],"sourcesContent":["import mongoose from \"mongoose\";\n\n/**\n * Connect to MongoDB using Mongoose.\n * Supports both local MongoDB (via MONGODB_URI) and MongoDB Atlas (via individual env vars).\n */\nexport const connectToDatabase = async ({\n appName,\n dbName,\n dbPassword,\n dbUser,\n mongodbUri,\n}: {\n appName: string;\n dbName: string;\n dbPassword: string;\n dbUser: string;\n mongodbUri: string;\n}) => {\n try {\n // Check if MONGODB_URI is provided (for local Docker MongoDB)\n const mongoUri = mongodbUri\n ? mongodbUri\n : // Fallback to MongoDB Atlas connection string\n `mongodb+srv://${dbUser}:${dbPassword}@${dbName}.mongodb.net/?retryWrites=true&w=majority&appName=${appName}`;\n\n await mongoose.connect(mongoUri);\n\n const connectionType = mongodbUri ? \"Local MongoDB\" : \"MongoDB Atlas\";\n console.log(\n `${connectionType} connected from server/src/service/database.ts`,\n );\n } catch (err) {\n console.error(\"Error connecting to MongoDB:\", err);\n throw err; // You can throw the error if you want to stop the server in case of connection failure\n }\n};\n","import {\n SchemaCreateBulkNotificationInput,\n NotificationModel,\n} from \"src/mongoose/Notification\";\nimport { ObjectId } from \"src/types\";\n\n/**\n * Create notifications in the database for multiple users\n * This is typically called when sending push notifications\n */\nexport async function saveNotificationsInDb(\n payload: SchemaCreateBulkNotificationInput,\n): Promise<ObjectId[]> {\n const { data, message, title, type, userIds } = payload;\n try {\n const notifications = userIds.map((userId) => ({\n data,\n isRead: false,\n message,\n title,\n type,\n userId,\n }));\n\n // Save notifications to database\n await NotificationModel.insertMany(notifications);\n console.log(\n `Created ${notifications.length} notifications for ${userIds.length} users`,\n );\n\n return [...new Set(userIds)];\n } catch (error) {\n console.error(\"Failed to create notifications:\", error);\n return [];\n //throw new Error(`Failed to create notifications: ${error}`);\n }\n}\n","import { NotificationDataType } from \"@timardex/cluemart-shared\";\nimport { Expo, ExpoPushMessage, ExpoPushTicket } from \"expo-server-sdk\";\n\nimport { SchemaCreateBulkNotificationInput } from \"src/mongoose/Notification\";\nimport { PushTokenModel } from \"src/mongoose/PushToken\";\n\nconst expo = new Expo();\n\n/**\n * Safely extract tokens from ExpoPushMessage handling both string and array cases\n */\nfunction extractTokensFromMessage(message: ExpoPushMessage): string[] {\n return Array.isArray(message.to) ? message.to : [message.to];\n}\n\ninterface CreatePushMessagesOptions {\n tokens: string[];\n message: string;\n title: string;\n data: NotificationDataType;\n}\n\n/**\n * Create push messages from valid tokens\n */\nfunction createPushMessages({\n tokens,\n message,\n title,\n data,\n}: CreatePushMessagesOptions): {\n messages: ExpoPushMessage[];\n invalidTokens: string[];\n} {\n const messages: ExpoPushMessage[] = [];\n const invalidTokens: string[] = [];\n\n for (const token of tokens) {\n if (!Expo.isExpoPushToken(token)) {\n invalidTokens.push(token);\n continue;\n }\n\n messages.push({\n body: message,\n data: { ...data },\n sound: \"default\",\n title,\n to: token,\n });\n }\n\n return { invalidTokens, messages };\n}\n\n/**\n * Process chunk results and extract failed tokens\n */\nfunction processChunkResults(\n tickets: ExpoPushTicket[],\n chunk: ExpoPushMessage[],\n): { successCount: number; failedTokens: string[] } {\n let successCount = 0;\n const failedTokens: string[] = [];\n\n for (const [ticketIndex, ticket] of tickets.entries()) {\n if (ticket.status === \"error\") {\n const message = chunk[ticketIndex];\n if (message) {\n const tokens = extractTokensFromMessage(message);\n if (ticket.details?.error === \"DeviceNotRegistered\") {\n failedTokens.push(...tokens);\n }\n console.log(\"Push notification error\", {\n error: ticket.details?.error,\n tokens,\n });\n }\n } else {\n successCount++;\n }\n }\n\n return { failedTokens, successCount };\n}\n\n/**\n * Send a single chunk of push notifications\n */\nasync function sendChunk(\n chunk: ExpoPushMessage[],\n chunkIndex: number,\n): Promise<{ successCount: number; failedTokens: string[] }> {\n try {\n const tickets = await expo.sendPushNotificationsAsync(chunk);\n const { successCount, failedTokens } = processChunkResults(tickets, chunk);\n\n console.log(\n `Chunk ${chunkIndex + 1}: Sent ${successCount}/${chunk.length} notifications successfully`,\n );\n\n return { failedTokens, successCount };\n } catch (error) {\n console.log(\"Error sending Expo push notification chunk\", {\n chunkIndex,\n chunkSize: chunk.length,\n error: error instanceof Error ? error.message : String(error),\n });\n return { failedTokens: [], successCount: 0 };\n }\n}\n\nexport async function sendPushNotifications({\n data,\n message,\n title,\n userIds,\n}: SchemaCreateBulkNotificationInput) {\n const pushTokens = await PushTokenModel.find({ userId: { $in: userIds } });\n const expoTokens = pushTokens.map((token) => token.token);\n\n if (!data) return;\n\n const { messages, invalidTokens } = createPushMessages({\n data,\n message,\n title,\n tokens: expoTokens,\n });\n\n // Log invalid tokens\n if (invalidTokens.length > 0) {\n console.log(`Found ${invalidTokens.length} invalid push tokens`);\n }\n\n if (messages.length === 0) {\n console.log(\"No valid messages to send after filtering tokens\");\n return;\n }\n\n // Send notifications in chunks\n const chunks = expo.chunkPushNotifications(messages);\n let totalSuccessCount = 0;\n const allFailedTokens: string[] = [];\n\n for (const [chunkIndex, chunk] of chunks.entries()) {\n const { successCount, failedTokens } = await sendChunk(\n chunk,\n chunkIndex + 1,\n );\n totalSuccessCount += successCount;\n allFailedTokens.push(...failedTokens);\n }\n\n // Log final results\n console.log(\n `Sent push notification to ${totalSuccessCount}/${messages.length} tokens across ${chunks.length} chunks`,\n );\n\n if (allFailedTokens.length > 0) {\n console.log(`Found ${allFailedTokens.length} failed push tokens`);\n }\n}\n","import { EnumAdStatus } from \"@timardex/cluemart-shared\";\n\nimport { AdModel } from \"src/mongoose\";\n\n/**\n * Updates ad statuses based on start/end dates and validity\n */\nexport async function updateAdStatuses(): Promise<void> {\n const now = new Date();\n\n // invalid\n const invalidResult = await AdModel.updateMany(\n {\n $or: [\n { start: { $exists: false } },\n { end: { $exists: false } },\n { $expr: { $gt: [\"$start\", \"$end\"] } },\n ],\n status: { $ne: EnumAdStatus.PAUSED },\n },\n { $set: { status: EnumAdStatus.PAUSED } },\n );\n\n // expired\n const expiredResult = await AdModel.updateMany(\n { end: { $lte: now }, status: { $ne: EnumAdStatus.EXPIRED } },\n { $set: { status: EnumAdStatus.EXPIRED } },\n );\n\n // active\n const activeResult = await AdModel.updateMany(\n {\n end: { $gt: now },\n start: { $lte: now },\n status: { $ne: EnumAdStatus.ACTIVE },\n },\n { $set: { status: EnumAdStatus.ACTIVE } },\n );\n\n // paused\n const pausedResult = await AdModel.updateMany(\n { start: { $gt: now }, status: { $ne: EnumAdStatus.PAUSED } },\n { $set: { status: EnumAdStatus.PAUSED } },\n );\n\n console.log(\n `✅ Ad statuses updated: invalid=${invalidResult.modifiedCount}, expired=${expiredResult.modifiedCount}, active=${activeResult.modifiedCount}, paused=${pausedResult.modifiedCount}`,\n );\n}\n","import { EnumChatType, EnumResourceType } from \"@timardex/cluemart-shared\";\nimport mongoose from \"mongoose\";\n\nimport { ChatModel, UserModel } from \"src/mongoose\";\nimport { ObjectId } from \"src/types\";\n\ninterface RemoveAssociateFromResourceParams {\n resourceId: string | ObjectId;\n resourceOwnerId: string | ObjectId;\n resourceType: EnumResourceType;\n}\n\n/**\n * Removes all associates linked to a resource\n * and deactivates related chat participants.\n */\nexport async function removeAssociateFromResource({\n resourceId,\n resourceOwnerId,\n resourceType,\n}: RemoveAssociateFromResourceParams): Promise<void> {\n try {\n const normalizedResourceId = resourceId.toString();\n\n const normalizedOwnerId =\n typeof resourceOwnerId === \"string\"\n ? new mongoose.Types.ObjectId(resourceOwnerId)\n : resourceOwnerId;\n\n /**\n * STEP 1:\n * Fetch matching associate emails BEFORE removal\n */\n const usersWithAssociates = await UserModel.find(\n {\n associates: {\n $elemMatch: {\n resourceId: normalizedResourceId,\n resourceType,\n },\n },\n },\n {\n associates: 1,\n },\n ).lean();\n\n /**\n * Extract unique associate emails\n */\n const associateEmails = [\n ...new Set(\n usersWithAssociates.flatMap((user) =>\n (user.associates ?? [])\n .filter(\n (associate) =>\n associate.resourceId === normalizedResourceId &&\n associate.resourceType === resourceType,\n )\n .map((associate) => associate.email),\n ),\n ),\n ];\n\n /**\n * Nothing to remove\n */\n if (associateEmails.length === 0) {\n return;\n }\n\n /**\n * STEP 2:\n * Remove associates from users\n */\n await UserModel.updateMany(\n {\n associates: {\n $elemMatch: {\n resourceId: normalizedResourceId,\n resourceType,\n },\n },\n },\n {\n $pull: {\n associates: {\n resourceId: normalizedResourceId,\n resourceType,\n },\n },\n },\n );\n\n /**\n * STEP 3:\n * Deactivate associate participants in chats\n */\n await ChatModel.updateMany(\n {\n active: true,\n chatType: EnumChatType.RELATION,\n deletedAt: null,\n participants: {\n $elemMatch: {\n userId: normalizedOwnerId,\n },\n },\n },\n {\n $set: {\n \"participants.$[associate].active\": false,\n },\n },\n {\n arrayFilters: [\n {\n \"associate.isAssociate\": true,\n \"associate.userEmail\": {\n $in: associateEmails,\n },\n },\n ],\n },\n );\n } catch (error) {\n console.error(\n `[removeAssociateFromResource] Failed for resourceId=${resourceId}, resourceType=${resourceType}`,\n error,\n );\n }\n}\n","import { EnumResourceType, EnumUserLicence } from \"@timardex/cluemart-shared\";\n\nimport { UserModel, VendorModel, SchemaVendorType } from \"src/mongoose\";\nimport { ObjectId } from \"src/types\";\n\nimport { removeAssociateFromResource } from \"./associate\";\n\nexport async function updateVendorBasedOnUserLicense(\n userId: ObjectId,\n licenceType: EnumUserLicence,\n): Promise<void> {\n try {\n /**\n * Fetch user vendor reference\n */\n const user = await UserModel.findById(userId).select(\"vendor\").lean();\n\n if (!user?.vendor) {\n console.warn(`[updateVendor] No vendor found for userId=${userId}`);\n return;\n }\n\n /**\n * Fetch vendor\n */\n const vendor = await VendorModel.findById(user.vendor).lean();\n\n if (!vendor) {\n console.warn(`[updateVendor] Vendor not found for id=${user.vendor}`);\n return;\n }\n\n /**\n * Build vendor update payload\n */\n const updateData: Partial<SchemaVendorType> = {};\n\n const isStandardVendor = licenceType === EnumUserLicence.STANDARD_VENDOR;\n\n if (isStandardVendor) {\n updateData.associates = [];\n\n updateData.availability = {\n corporate: false,\n private: false,\n school: false,\n };\n\n updateData.products = {\n active: false,\n productsList: vendor.products?.productsList ?? [],\n };\n\n updateData.calendar = {\n active: false,\n calendarData: vendor.calendar?.calendarData ?? [],\n };\n }\n\n /**\n * Image rules\n * STANDARD_VENDOR => only first 6 active\n * PRO_VENDOR => all active\n */\n updateData.images = (vendor.images ?? []).map((image, index) => ({\n ...image,\n active: isStandardVendor ? index < 6 : true,\n }));\n\n /**\n * Persist vendor updates\n */\n await VendorModel.updateOne({ _id: vendor._id }, { $set: updateData });\n\n /**\n * Cleanup associates for STANDARD licence\n */\n if (isStandardVendor) {\n await removeAssociateFromResource({\n resourceId: vendor._id,\n resourceOwnerId: vendor.owner.userId,\n resourceType: EnumResourceType.VENDOR,\n });\n }\n } catch (error) {\n console.error(\"[updateVendorBasedOnUserLicense] Failed:\", error);\n }\n}\n","import mongoose from \"mongoose\";\n\n/**\n * Recursively converts all ObjectId fields to strings in an object\n * This is needed because GraphQL expects string IDs, not ObjectIds\n */\nexport function convertObjectIdsToStrings(obj: any): any {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (obj instanceof mongoose.Types.ObjectId) {\n return obj.toString();\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertObjectIdsToStrings);\n }\n\n if (typeof obj === \"object\") {\n const converted: any = {};\n for (const [key, value] of Object.entries(obj)) {\n converted[key] = convertObjectIdsToStrings(value);\n }\n return converted;\n }\n\n return obj;\n}\n","import { EventModel, GoogleImportedMarketModel } from \"src/mongoose\";\nimport { ObjectId } from \"src/types\";\n\nimport { convertObjectIdsToStrings } from \"./objectIdToString\";\n\ntype EventOrMarket = { _id: ObjectId | string; name: string } | null;\n\n/**\n * This function attempts to find an Event or a Google Imported Market by the given resource ID.\n * It first normalizes the resource ID to a string format, then performs parallel queries to both collections.\n * If an Event is found, it returns that; otherwise, it checks for a Google Imported Market and returns it if found.\n * If neither is found, it returns null.\n * @param resourceId - The ID of the resource to find, which can be an ObjectId, string, null, or undefined.\n * @returns A promise that resolves to either an Event or a Google Imported Market object containing _id and name, or null if not found.\n */\n\nexport async function findEventOrImportedMarketById(\n resourceId: ObjectId | string | null | undefined,\n): Promise<EventOrMarket> {\n if (!resourceId) {\n return null;\n }\n\n const normalizedId = convertObjectIdsToStrings(resourceId) as string;\n\n const [eventDoc, googleImportedDoc] = await Promise.all([\n EventModel.findById(normalizedId).select(\"_id name\").lean().exec(),\n GoogleImportedMarketModel.findById(normalizedId)\n .select(\"_id name\")\n .lean()\n .exec(),\n ]);\n\n return eventDoc ?? googleImportedDoc;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA,OAAO,cAAc;AAMd,IAAM,oBAAoB,OAAO;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAMM;AACJ,MAAI;AAEF,UAAM,WAAW,aACb;AAAA;AAAA,MAEA,iBAAiB,MAAM,IAAI,UAAU,IAAI,MAAM,qDAAqD,OAAO;AAAA;AAE/G,UAAM,SAAS,QAAQ,QAAQ;AAE/B,UAAM,iBAAiB,aAAa,kBAAkB;AACtD,YAAQ;AAAA,MACN,GAAG,cAAc;AAAA,IACnB;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,MAAM,gCAAgC,GAAG;AACjD,UAAM;AAAA,EACR;AACF;;;AC1BA,eAAsB,sBACpB,SACqB;AACrB,QAAM,EAAE,MAAM,SAAS,OAAO,MAAM,QAAQ,IAAI;AAChD,MAAI;AACF,UAAM,gBAAgB,QAAQ,IAAI,CAAC,YAAY;AAAA,MAC7C;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE;AAGF,UAAM,kBAAkB,WAAW,aAAa;AAChD,YAAQ;AAAA,MACN,WAAW,cAAc,MAAM,sBAAsB,QAAQ,MAAM;AAAA,IACrE;AAEA,WAAO,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC;AAAA,EAC7B,SAAS,OAAO;AACd,YAAQ,MAAM,mCAAmC,KAAK;AACtD,WAAO,CAAC;AAAA,EAEV;AACF;;;ACnCA,SAAS,YAA6C;AAKtD,IAAM,OAAO,IAAI,KAAK;AAKtB,SAAS,yBAAyB,SAAoC;AACpE,SAAO,MAAM,QAAQ,QAAQ,EAAE,IAAI,QAAQ,KAAK,CAAC,QAAQ,EAAE;AAC7D;AAYA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAGE;AACA,QAAM,WAA8B,CAAC;AACrC,QAAM,gBAA0B,CAAC;AAEjC,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,KAAK,gBAAgB,KAAK,GAAG;AAChC,oBAAc,KAAK,KAAK;AACxB;AAAA,IACF;AAEA,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM,EAAE,GAAG,KAAK;AAAA,MAChB,OAAO;AAAA,MACP;AAAA,MACA,IAAI;AAAA,IACN,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,eAAe,SAAS;AACnC;AAKA,SAAS,oBACP,SACA,OACkD;AAClD,MAAI,eAAe;AACnB,QAAM,eAAyB,CAAC;AAEhC,aAAW,CAAC,aAAa,MAAM,KAAK,QAAQ,QAAQ,GAAG;AACrD,QAAI,OAAO,WAAW,SAAS;AAC7B,YAAM,UAAU,MAAM,WAAW;AACjC,UAAI,SAAS;AACX,cAAM,SAAS,yBAAyB,OAAO;AAC/C,YAAI,OAAO,SAAS,UAAU,uBAAuB;AACnD,uBAAa,KAAK,GAAG,MAAM;AAAA,QAC7B;AACA,gBAAQ,IAAI,2BAA2B;AAAA,UACrC,OAAO,OAAO,SAAS;AAAA,UACvB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,cAAc,aAAa;AACtC;AAKA,eAAe,UACb,OACA,YAC2D;AAC3D,MAAI;AACF,UAAM,UAAU,MAAM,KAAK,2BAA2B,KAAK;AAC3D,UAAM,EAAE,cAAc,aAAa,IAAI,oBAAoB,SAAS,KAAK;AAEzE,YAAQ;AAAA,MACN,SAAS,aAAa,CAAC,UAAU,YAAY,IAAI,MAAM,MAAM;AAAA,IAC/D;AAEA,WAAO,EAAE,cAAc,aAAa;AAAA,EACtC,SAAS,OAAO;AACd,YAAQ,IAAI,8CAA8C;AAAA,MACxD;AAAA,MACA,WAAW,MAAM;AAAA,MACjB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAC;AACD,WAAO,EAAE,cAAc,CAAC,GAAG,cAAc,EAAE;AAAA,EAC7C;AACF;AAEA,eAAsB,sBAAsB;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsC;AACpC,QAAM,aAAa,MAAM,eAAe,KAAK,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAC;AACzE,QAAM,aAAa,WAAW,IAAI,CAAC,UAAU,MAAM,KAAK;AAExD,MAAI,CAAC,KAAM;AAEX,QAAM,EAAE,UAAU,cAAc,IAAI,mBAAmB;AAAA,IACrD;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV,CAAC;AAGD,MAAI,cAAc,SAAS,GAAG;AAC5B,YAAQ,IAAI,SAAS,cAAc,MAAM,sBAAsB;AAAA,EACjE;AAEA,MAAI,SAAS,WAAW,GAAG;AACzB,YAAQ,IAAI,kDAAkD;AAC9D;AAAA,EACF;AAGA,QAAM,SAAS,KAAK,uBAAuB,QAAQ;AACnD,MAAI,oBAAoB;AACxB,QAAM,kBAA4B,CAAC;AAEnC,aAAW,CAAC,YAAY,KAAK,KAAK,OAAO,QAAQ,GAAG;AAClD,UAAM,EAAE,cAAc,aAAa,IAAI,MAAM;AAAA,MAC3C;AAAA,MACA,aAAa;AAAA,IACf;AACA,yBAAqB;AACrB,oBAAgB,KAAK,GAAG,YAAY;AAAA,EACtC;AAGA,UAAQ;AAAA,IACN,6BAA6B,iBAAiB,IAAI,SAAS,MAAM,kBAAkB,OAAO,MAAM;AAAA,EAClG;AAEA,MAAI,gBAAgB,SAAS,GAAG;AAC9B,YAAQ,IAAI,SAAS,gBAAgB,MAAM,qBAAqB;AAAA,EAClE;AACF;;;AC3JA,eAAsB,mBAAkC;AACtD,QAAM,MAAM,oBAAI,KAAK;AAGrB,QAAM,gBAAgB,MAAM,QAAQ;AAAA,IAClC;AAAA,MACE,KAAK;AAAA,QACH,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE;AAAA,QAC5B,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE;AAAA,QAC1B,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,MAAM,EAAE,EAAE;AAAA,MACvC;AAAA,MACA,QAAQ,EAAE,KAAK,aAAa,OAAO;AAAA,IACrC;AAAA,IACA,EAAE,MAAM,EAAE,QAAQ,aAAa,OAAO,EAAE;AAAA,EAC1C;AAGA,QAAM,gBAAgB,MAAM,QAAQ;AAAA,IAClC,EAAE,KAAK,EAAE,MAAM,IAAI,GAAG,QAAQ,EAAE,KAAK,aAAa,QAAQ,EAAE;AAAA,IAC5D,EAAE,MAAM,EAAE,QAAQ,aAAa,QAAQ,EAAE;AAAA,EAC3C;AAGA,QAAM,eAAe,MAAM,QAAQ;AAAA,IACjC;AAAA,MACE,KAAK,EAAE,KAAK,IAAI;AAAA,MAChB,OAAO,EAAE,MAAM,IAAI;AAAA,MACnB,QAAQ,EAAE,KAAK,aAAa,OAAO;AAAA,IACrC;AAAA,IACA,EAAE,MAAM,EAAE,QAAQ,aAAa,OAAO,EAAE;AAAA,EAC1C;AAGA,QAAM,eAAe,MAAM,QAAQ;AAAA,IACjC,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,QAAQ,EAAE,KAAK,aAAa,OAAO,EAAE;AAAA,IAC5D,EAAE,MAAM,EAAE,QAAQ,aAAa,OAAO,EAAE;AAAA,EAC1C;AAEA,UAAQ;AAAA,IACN,uCAAkC,cAAc,aAAa,aAAa,cAAc,aAAa,YAAY,aAAa,aAAa,YAAY,aAAa,aAAa;AAAA,EACnL;AACF;;;AC/CA,OAAOA,eAAc;AAerB,eAAsB,4BAA4B;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AACF,GAAqD;AACnD,MAAI;AACF,UAAM,uBAAuB,WAAW,SAAS;AAEjD,UAAM,oBACJ,OAAO,oBAAoB,WACvB,IAAIC,UAAS,MAAM,SAAS,eAAe,IAC3C;AAMN,UAAM,sBAAsB,MAAM,UAAU;AAAA,MAC1C;AAAA,QACE,YAAY;AAAA,UACV,YAAY;AAAA,YACV,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,YAAY;AAAA,MACd;AAAA,IACF,EAAE,KAAK;AAKP,UAAM,kBAAkB;AAAA,MACtB,GAAG,IAAI;AAAA,QACL,oBAAoB;AAAA,UAAQ,CAAC,UAC1B,KAAK,cAAc,CAAC,GAClB;AAAA,YACC,CAAC,cACC,UAAU,eAAe,wBACzB,UAAU,iBAAiB;AAAA,UAC/B,EACC,IAAI,CAAC,cAAc,UAAU,KAAK;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAKA,QAAI,gBAAgB,WAAW,GAAG;AAChC;AAAA,IACF;AAMA,UAAM,UAAU;AAAA,MACd;AAAA,QACE,YAAY;AAAA,UACV,YAAY;AAAA,YACV,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,OAAO;AAAA,UACL,YAAY;AAAA,YACV,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAMA,UAAM,UAAU;AAAA,MACd;AAAA,QACE,QAAQ;AAAA,QACR,UAAU,aAAa;AAAA,QACvB,WAAW;AAAA,QACX,cAAc;AAAA,UACZ,YAAY;AAAA,YACV,QAAQ;AAAA,UACV;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,UACJ,oCAAoC;AAAA,QACtC;AAAA,MACF;AAAA,MACA;AAAA,QACE,cAAc;AAAA,UACZ;AAAA,YACE,yBAAyB;AAAA,YACzB,uBAAuB;AAAA,cACrB,KAAK;AAAA,YACP;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ;AAAA,MACN,uDAAuD,UAAU,kBAAkB,YAAY;AAAA,MAC/F;AAAA,IACF;AAAA,EACF;AACF;;;AC5HA,eAAsB,+BACpB,QACA,aACe;AACf,MAAI;AAIF,UAAM,OAAO,MAAM,UAAU,SAAS,MAAM,EAAE,OAAO,QAAQ,EAAE,KAAK;AAEpE,QAAI,CAAC,MAAM,QAAQ;AACjB,cAAQ,KAAK,6CAA6C,MAAM,EAAE;AAClE;AAAA,IACF;AAKA,UAAM,SAAS,MAAM,YAAY,SAAS,KAAK,MAAM,EAAE,KAAK;AAE5D,QAAI,CAAC,QAAQ;AACX,cAAQ,KAAK,0CAA0C,KAAK,MAAM,EAAE;AACpE;AAAA,IACF;AAKA,UAAM,aAAwC,CAAC;AAE/C,UAAM,mBAAmB,gBAAgB,gBAAgB;AAEzD,QAAI,kBAAkB;AACpB,iBAAW,aAAa,CAAC;AAEzB,iBAAW,eAAe;AAAA,QACxB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,QAAQ;AAAA,MACV;AAEA,iBAAW,WAAW;AAAA,QACpB,QAAQ;AAAA,QACR,cAAc,OAAO,UAAU,gBAAgB,CAAC;AAAA,MAClD;AAEA,iBAAW,WAAW;AAAA,QACpB,QAAQ;AAAA,QACR,cAAc,OAAO,UAAU,gBAAgB,CAAC;AAAA,MAClD;AAAA,IACF;AAOA,eAAW,UAAU,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,OAAO,WAAW;AAAA,MAC/D,GAAG;AAAA,MACH,QAAQ,mBAAmB,QAAQ,IAAI;AAAA,IACzC,EAAE;AAKF,UAAM,YAAY,UAAU,EAAE,KAAK,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAKrE,QAAI,kBAAkB;AACpB,YAAM,4BAA4B;AAAA,QAChC,YAAY,OAAO;AAAA,QACnB,iBAAiB,OAAO,MAAM;AAAA,QAC9B,cAAc,iBAAiB;AAAA,MACjC,CAAC;AAAA,IACH;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,4CAA4C,KAAK;AAAA,EACjE;AACF;;;ACvFA,OAAOC,eAAc;AAMd,SAAS,0BAA0B,KAAe;AACvD,MAAI,QAAQ,QAAQ,QAAQ,QAAW;AACrC,WAAO;AAAA,EACT;AAEA,MAAI,eAAeA,UAAS,MAAM,UAAU;AAC1C,WAAO,IAAI,SAAS;AAAA,EACtB;AAEA,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAO,IAAI,IAAI,yBAAyB;AAAA,EAC1C;AAEA,MAAI,OAAO,QAAQ,UAAU;AAC3B,UAAM,YAAiB,CAAC;AACxB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,gBAAU,GAAG,IAAI,0BAA0B,KAAK;AAAA,IAClD;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;ACZA,eAAsB,8BACpB,YACwB;AACxB,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,0BAA0B,UAAU;AAEzD,QAAM,CAAC,UAAU,iBAAiB,IAAI,MAAM,QAAQ,IAAI;AAAA,IACtD,WAAW,SAAS,YAAY,EAAE,OAAO,UAAU,EAAE,KAAK,EAAE,KAAK;AAAA,IACjE,0BAA0B,SAAS,YAAY,EAC5C,OAAO,UAAU,EACjB,KAAK,EACL,KAAK;AAAA,EACV,CAAC;AAED,SAAO,YAAY;AACrB;","names":["mongoose","mongoose","mongoose"]}
|
|
1
|
+
{"version":3,"sources":["../../src/service/database.ts","../../src/service/saveNotificationsInDb.ts","../../src/service/sendPushNotifications.ts","../../src/service/updateAdStatus.ts","../../src/service/associate.ts","../../src/service/vendor.ts","../../src/service/objectIdToString.ts","../../src/service/event.ts","../../src/service/relations.ts"],"sourcesContent":["import mongoose from \"mongoose\";\n\n/**\n * Connect to MongoDB using Mongoose.\n * Supports both local MongoDB (via MONGODB_URI) and MongoDB Atlas (via individual env vars).\n */\nexport const connectToDatabase = async ({\n appName,\n dbName,\n dbPassword,\n dbUser,\n mongodbUri,\n}: {\n appName: string;\n dbName: string;\n dbPassword: string;\n dbUser: string;\n mongodbUri: string;\n}) => {\n try {\n // Check if MONGODB_URI is provided (for local Docker MongoDB)\n const mongoUri = mongodbUri\n ? mongodbUri\n : // Fallback to MongoDB Atlas connection string\n `mongodb+srv://${dbUser}:${dbPassword}@${dbName}.mongodb.net/?retryWrites=true&w=majority&appName=${appName}`;\n\n await mongoose.connect(mongoUri);\n\n const connectionType = mongodbUri ? \"Local MongoDB\" : \"MongoDB Atlas\";\n console.log(\n `${connectionType} connected from server/src/service/database.ts`,\n );\n } catch (err) {\n console.error(\"Error connecting to MongoDB:\", err);\n throw err; // You can throw the error if you want to stop the server in case of connection failure\n }\n};\n","import {\n SchemaCreateBulkNotificationInput,\n NotificationModel,\n} from \"src/mongoose/Notification\";\nimport { ObjectId } from \"src/types\";\n\n/**\n * Create notifications in the database for multiple users\n * This is typically called when sending push notifications\n */\nexport async function saveNotificationsInDb(\n payload: SchemaCreateBulkNotificationInput,\n): Promise<ObjectId[]> {\n const { data, message, title, type, userIds } = payload;\n try {\n const notifications = userIds.map((userId) => ({\n data,\n isRead: false,\n message,\n title,\n type,\n userId,\n }));\n\n // Save notifications to database\n await NotificationModel.insertMany(notifications);\n console.log(\n `Created ${notifications.length} notifications for ${userIds.length} users`,\n );\n\n return [...new Set(userIds)];\n } catch (error) {\n console.error(\"Failed to create notifications:\", error);\n return [];\n //throw new Error(`Failed to create notifications: ${error}`);\n }\n}\n","import { NotificationDataType } from \"@timardex/cluemart-shared\";\nimport { Expo, ExpoPushMessage, ExpoPushTicket } from \"expo-server-sdk\";\n\nimport { SchemaCreateBulkNotificationInput } from \"src/mongoose/Notification\";\nimport { PushTokenModel } from \"src/mongoose/PushToken\";\n\nconst expo = new Expo();\n\n/**\n * Safely extract tokens from ExpoPushMessage handling both string and array cases\n */\nfunction extractTokensFromMessage(message: ExpoPushMessage): string[] {\n return Array.isArray(message.to) ? message.to : [message.to];\n}\n\ninterface CreatePushMessagesOptions {\n tokens: string[];\n message: string;\n title: string;\n data: NotificationDataType;\n}\n\n/**\n * Create push messages from valid tokens\n */\nfunction createPushMessages({\n tokens,\n message,\n title,\n data,\n}: CreatePushMessagesOptions): {\n messages: ExpoPushMessage[];\n invalidTokens: string[];\n} {\n const messages: ExpoPushMessage[] = [];\n const invalidTokens: string[] = [];\n\n for (const token of tokens) {\n if (!Expo.isExpoPushToken(token)) {\n invalidTokens.push(token);\n continue;\n }\n\n messages.push({\n body: message,\n data: { ...data },\n sound: \"default\",\n title,\n to: token,\n });\n }\n\n return { invalidTokens, messages };\n}\n\n/**\n * Process chunk results and extract failed tokens\n */\nfunction processChunkResults(\n tickets: ExpoPushTicket[],\n chunk: ExpoPushMessage[],\n): { successCount: number; failedTokens: string[] } {\n let successCount = 0;\n const failedTokens: string[] = [];\n\n for (const [ticketIndex, ticket] of tickets.entries()) {\n if (ticket.status === \"error\") {\n const message = chunk[ticketIndex];\n if (message) {\n const tokens = extractTokensFromMessage(message);\n if (ticket.details?.error === \"DeviceNotRegistered\") {\n failedTokens.push(...tokens);\n }\n console.log(\"Push notification error\", {\n error: ticket.details?.error,\n tokens,\n });\n }\n } else {\n successCount++;\n }\n }\n\n return { failedTokens, successCount };\n}\n\n/**\n * Send a single chunk of push notifications\n */\nasync function sendChunk(\n chunk: ExpoPushMessage[],\n chunkIndex: number,\n): Promise<{ successCount: number; failedTokens: string[] }> {\n try {\n const tickets = await expo.sendPushNotificationsAsync(chunk);\n const { successCount, failedTokens } = processChunkResults(tickets, chunk);\n\n console.log(\n `Chunk ${chunkIndex + 1}: Sent ${successCount}/${chunk.length} notifications successfully`,\n );\n\n return { failedTokens, successCount };\n } catch (error) {\n console.log(\"Error sending Expo push notification chunk\", {\n chunkIndex,\n chunkSize: chunk.length,\n error: error instanceof Error ? error.message : String(error),\n });\n return { failedTokens: [], successCount: 0 };\n }\n}\n\nexport async function sendPushNotifications({\n data,\n message,\n title,\n userIds,\n}: SchemaCreateBulkNotificationInput) {\n const pushTokens = await PushTokenModel.find({ userId: { $in: userIds } });\n const expoTokens = pushTokens.map((token) => token.token);\n\n if (!data) return;\n\n const { messages, invalidTokens } = createPushMessages({\n data,\n message,\n title,\n tokens: expoTokens,\n });\n\n // Log invalid tokens\n if (invalidTokens.length > 0) {\n console.log(`Found ${invalidTokens.length} invalid push tokens`);\n }\n\n if (messages.length === 0) {\n console.log(\"No valid messages to send after filtering tokens\");\n return;\n }\n\n // Send notifications in chunks\n const chunks = expo.chunkPushNotifications(messages);\n let totalSuccessCount = 0;\n const allFailedTokens: string[] = [];\n\n for (const [chunkIndex, chunk] of chunks.entries()) {\n const { successCount, failedTokens } = await sendChunk(\n chunk,\n chunkIndex + 1,\n );\n totalSuccessCount += successCount;\n allFailedTokens.push(...failedTokens);\n }\n\n // Log final results\n console.log(\n `Sent push notification to ${totalSuccessCount}/${messages.length} tokens across ${chunks.length} chunks`,\n );\n\n if (allFailedTokens.length > 0) {\n console.log(`Found ${allFailedTokens.length} failed push tokens`);\n }\n}\n","import { EnumAdStatus } from \"@timardex/cluemart-shared\";\n\nimport { AdModel } from \"src/mongoose\";\n\n/**\n * Updates ad statuses based on start/end dates and validity\n */\nexport async function updateAdStatuses(): Promise<void> {\n const now = new Date();\n\n // invalid\n const invalidResult = await AdModel.updateMany(\n {\n $or: [\n { start: { $exists: false } },\n { end: { $exists: false } },\n { $expr: { $gt: [\"$start\", \"$end\"] } },\n ],\n status: { $ne: EnumAdStatus.PAUSED },\n },\n { $set: { status: EnumAdStatus.PAUSED } },\n );\n\n // expired\n const expiredResult = await AdModel.updateMany(\n { end: { $lte: now }, status: { $ne: EnumAdStatus.EXPIRED } },\n { $set: { status: EnumAdStatus.EXPIRED } },\n );\n\n // active\n const activeResult = await AdModel.updateMany(\n {\n end: { $gt: now },\n start: { $lte: now },\n status: { $ne: EnumAdStatus.ACTIVE },\n },\n { $set: { status: EnumAdStatus.ACTIVE } },\n );\n\n // paused\n const pausedResult = await AdModel.updateMany(\n { start: { $gt: now }, status: { $ne: EnumAdStatus.PAUSED } },\n { $set: { status: EnumAdStatus.PAUSED } },\n );\n\n console.log(\n `✅ Ad statuses updated: invalid=${invalidResult.modifiedCount}, expired=${expiredResult.modifiedCount}, active=${activeResult.modifiedCount}, paused=${pausedResult.modifiedCount}`,\n );\n}\n","import { EnumChatType, EnumResourceType } from \"@timardex/cluemart-shared\";\nimport mongoose from \"mongoose\";\n\nimport { ChatModel, UserModel } from \"src/mongoose\";\nimport { ObjectId } from \"src/types\";\n\ninterface RemoveAssociateFromResourceParams {\n resourceId: string | ObjectId;\n resourceOwnerId: string | ObjectId;\n resourceType: EnumResourceType;\n}\n\n/**\n * Removes all associates linked to a resource\n * and deactivates related chat participants.\n */\nexport async function removeAssociateFromResource({\n resourceId,\n resourceOwnerId,\n resourceType,\n}: RemoveAssociateFromResourceParams): Promise<void> {\n try {\n const normalizedResourceId = resourceId.toString();\n\n const normalizedOwnerId =\n typeof resourceOwnerId === \"string\"\n ? new mongoose.Types.ObjectId(resourceOwnerId)\n : resourceOwnerId;\n\n /**\n * STEP 1:\n * Fetch matching associate emails BEFORE removal\n */\n const usersWithAssociates = await UserModel.find(\n {\n associates: {\n $elemMatch: {\n resourceId: normalizedResourceId,\n resourceType,\n },\n },\n },\n {\n associates: 1,\n },\n ).lean();\n\n /**\n * Extract unique associate emails\n */\n const associateEmails = [\n ...new Set(\n usersWithAssociates.flatMap((user) =>\n (user.associates ?? [])\n .filter(\n (associate) =>\n associate.resourceId === normalizedResourceId &&\n associate.resourceType === resourceType,\n )\n .map((associate) => associate.email),\n ),\n ),\n ];\n\n /**\n * Nothing to remove\n */\n if (associateEmails.length === 0) {\n return;\n }\n\n /**\n * STEP 2:\n * Remove associates from users\n */\n await UserModel.updateMany(\n {\n associates: {\n $elemMatch: {\n resourceId: normalizedResourceId,\n resourceType,\n },\n },\n },\n {\n $pull: {\n associates: {\n resourceId: normalizedResourceId,\n resourceType,\n },\n },\n },\n );\n\n /**\n * STEP 3:\n * Deactivate associate participants in chats\n */\n await ChatModel.updateMany(\n {\n active: true,\n chatType: EnumChatType.RELATION,\n deletedAt: null,\n participants: {\n $elemMatch: {\n userId: normalizedOwnerId,\n },\n },\n },\n {\n $set: {\n \"participants.$[associate].active\": false,\n },\n },\n {\n arrayFilters: [\n {\n \"associate.isAssociate\": true,\n \"associate.userEmail\": {\n $in: associateEmails,\n },\n },\n ],\n },\n );\n } catch (error) {\n console.error(\n `[removeAssociateFromResource] Failed for resourceId=${resourceId}, resourceType=${resourceType}`,\n error,\n );\n }\n}\n","import { EnumResourceType, EnumUserLicence } from \"@timardex/cluemart-shared\";\n\nimport { UserModel, VendorModel, SchemaVendorType } from \"src/mongoose\";\nimport { ObjectId } from \"src/types\";\n\nimport { removeAssociateFromResource } from \"./associate\";\n\nexport async function updateVendorBasedOnUserLicense(\n userId: ObjectId,\n licenceType: EnumUserLicence,\n): Promise<void> {\n try {\n /**\n * Fetch user vendor reference\n */\n const user = await UserModel.findById(userId).select(\"vendor\").lean();\n\n if (!user?.vendor) {\n console.warn(`[updateVendor] No vendor found for userId=${userId}`);\n return;\n }\n\n /**\n * Fetch vendor\n */\n const vendor = await VendorModel.findById(user.vendor).lean();\n\n if (!vendor) {\n console.warn(`[updateVendor] Vendor not found for id=${user.vendor}`);\n return;\n }\n\n /**\n * Build vendor update payload\n */\n const updateData: Partial<SchemaVendorType> = {};\n\n const isStandardVendor = licenceType === EnumUserLicence.STANDARD_VENDOR;\n\n if (isStandardVendor) {\n updateData.associates = [];\n\n updateData.availability = {\n corporate: false,\n private: false,\n school: false,\n };\n\n updateData.products = {\n active: false,\n productsList: vendor.products?.productsList ?? [],\n };\n\n updateData.calendar = {\n active: false,\n calendarData: vendor.calendar?.calendarData ?? [],\n };\n }\n\n /**\n * Image rules\n * STANDARD_VENDOR => only first 6 active\n * PRO_VENDOR => all active\n */\n updateData.images = (vendor.images ?? []).map((image, index) => ({\n ...image,\n active: isStandardVendor ? index < 6 : true,\n }));\n\n /**\n * Persist vendor updates\n */\n await VendorModel.updateOne({ _id: vendor._id }, { $set: updateData });\n\n /**\n * Cleanup associates for STANDARD licence\n */\n if (isStandardVendor) {\n await removeAssociateFromResource({\n resourceId: vendor._id,\n resourceOwnerId: vendor.owner.userId,\n resourceType: EnumResourceType.VENDOR,\n });\n }\n } catch (error) {\n console.error(\"[updateVendorBasedOnUserLicense] Failed:\", error);\n }\n}\n","import mongoose from \"mongoose\";\n\n/**\n * Recursively converts all ObjectId fields to strings in an object\n * This is needed because GraphQL expects string IDs, not ObjectIds\n */\nexport function convertObjectIdsToStrings(obj: any): any {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (obj instanceof mongoose.Types.ObjectId) {\n return obj.toString();\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertObjectIdsToStrings);\n }\n\n if (typeof obj === \"object\") {\n const converted: any = {};\n for (const [key, value] of Object.entries(obj)) {\n converted[key] = convertObjectIdsToStrings(value);\n }\n return converted;\n }\n\n return obj;\n}\n","import { EventModel, GoogleImportedMarketModel } from \"src/mongoose\";\nimport { ObjectId } from \"src/types\";\n\nimport { convertObjectIdsToStrings } from \"./objectIdToString\";\n\ntype EventOrMarket = { _id: ObjectId | string; name: string } | null;\n\n/**\n * This function attempts to find an Event or a Google Imported Market by the given resource ID.\n * It first normalizes the resource ID to a string format, then performs parallel queries to both collections.\n * If an Event is found, it returns that; otherwise, it checks for a Google Imported Market and returns it if found.\n * If neither is found, it returns null.\n * @param resourceId - The ID of the resource to find, which can be an ObjectId, string, null, or undefined.\n * @returns A promise that resolves to either an Event or a Google Imported Market object containing _id and name, or null if not found.\n */\n\nexport async function findEventOrImportedMarketById(\n resourceId: ObjectId | string | null | undefined,\n): Promise<EventOrMarket> {\n if (!resourceId) {\n return null;\n }\n\n const normalizedId = convertObjectIdsToStrings(resourceId) as string;\n\n const [eventDoc, googleImportedDoc] = await Promise.all([\n EventModel.findById(normalizedId).select(\"_id name\").lean().exec(),\n GoogleImportedMarketModel.findById(normalizedId)\n .select(\"_id name\")\n .lean()\n .exec(),\n ]);\n\n return eventDoc ?? googleImportedDoc;\n}\n","import {\n DateTimeWithPriceType,\n EnumInviteStatus,\n} from \"@timardex/cluemart-shared\";\n\nimport { SchemaRelationType } from \"src/mongoose/Relation\";\n\n/**\n * Helper: Update relationDates based on event's dateTime\n * Marks dates as UNAVAILABLE if they no longer exist in the event's dateTime.\n */\nexport function updateRelationDatesToUnavailable(\n relationDates: SchemaRelationType[\"relationDates\"],\n eventDateTime: DateTimeWithPriceType[] | undefined,\n): SchemaRelationType[\"relationDates\"] {\n return relationDates.map((relationDate) => {\n // Check if this relationDate exists in the event's dateTime\n const existsInEvent =\n eventDateTime?.some(\n (dt) =>\n dt.startDate === relationDate.dateTime.startDate &&\n dt.startTime === relationDate.dateTime.startTime,\n ) ?? false;\n\n return {\n ...relationDate,\n status: existsInEvent\n ? relationDate.status\n : EnumInviteStatus.UNAVAILABLE,\n };\n });\n}\n"],"mappings":"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","names":["mongoose","mongoose","mongoose"]}
|