@lyxa.ai/core 1.4.323 → 1.4.324

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.
@@ -35,13 +35,7 @@ let GoogleLocationService = class GoogleLocationService {
35
35
  this.logger.logger.info('Google Autocomplete skipped: empty input provided');
36
36
  return { predictions: [], status: 'OK' };
37
37
  }
38
- const queryParams = { input: searchText, ...otherParams };
39
- if (sessionToken)
40
- queryParams.sessiontoken = sessionToken;
41
- const querySummary = Object.entries(queryParams)
42
- .map(([k, v]) => `${k}:${v}`)
43
- .join('|');
44
- const cacheKey = `maps:autocomplete:${this.redisService.sanitizeKey(querySummary)}`;
38
+ const cacheKey = `maps:autocomplete:${this.redisService.sanitizeKey(searchText.trim().toLowerCase())}`;
45
39
  try {
46
40
  const cached = await this.redisService.getCachedObject(cacheKey);
47
41
  if (cached !== undefined) {
@@ -54,9 +48,12 @@ let GoogleLocationService = class GoogleLocationService {
54
48
  this.logger.logger.error('GOOGLE_MAPS_API_KEY is missing in SecretManager');
55
49
  throw new Error('GOOGLE_MAPS_API_KEY is not configured');
56
50
  }
51
+ const queryParams = { input: searchText, ...otherParams };
52
+ if (sessionToken)
53
+ queryParams.sessiontoken = sessionToken;
57
54
  const result = await this.client.callGoogleMapsAPI('place/autocomplete', apiKey, queryParams);
58
55
  if (result.status === 'OK') {
59
- await this.redisService.cacheObject(cacheKey, result, 86400);
56
+ await this.redisService.cacheObject(cacheKey, result, 604800);
60
57
  this.logger.logger.info('Google Autocomplete response cached successfully', {
61
58
  cacheKey,
62
59
  predictionCount: result.predictions?.length ?? 0,
@@ -128,6 +125,16 @@ let GoogleLocationService = class GoogleLocationService {
128
125
  const roundedLng = parseFloat(longitude).toFixed(4);
129
126
  const cacheKey = `maps:geocode:${roundedLat}:${roundedLng}`;
130
127
  try {
128
+ const cached = await this.redisService.getCachedObject(cacheKey);
129
+ if (cached !== undefined) {
130
+ this.logger.logger.info('Google Reverse Geocode Cache HIT', { cacheKey, roundedLat, roundedLng });
131
+ return cached;
132
+ }
133
+ this.logger.logger.info('Google Reverse Geocode Cache MISS - Calling API', {
134
+ cacheKey,
135
+ latitude,
136
+ longitude,
137
+ });
131
138
  const apiKey = await this.secretManager.getKey('GOOGLE_MAPS_API_KEY');
132
139
  if (!apiKey) {
133
140
  this.logger.logger.error('GOOGLE_MAPS_API_KEY is missing in SecretManager');
@@ -136,11 +143,6 @@ let GoogleLocationService = class GoogleLocationService {
136
143
  const params = { latlng: `${latitude},${longitude}` };
137
144
  const result = await this.client.callGoogleMapsAPI('geocode', apiKey, params);
138
145
  if (result.status === 'OK') {
139
- await this.redisService.cacheObject(cacheKey, result, 259200);
140
- this.logger.logger.info('Google Reverse Geocode cached successfully', {
141
- cacheKey,
142
- resultsCount: result.results?.length ?? 0,
143
- });
144
146
  }
145
147
  else {
146
148
  this.logger.logger.warn('Google Reverse Geocode returned non-OK status', {
@@ -1 +1 @@
1
- {"version":3,"file":"google-location.service.js","sourceRoot":"/","sources":["libraries/google-location/google-location.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,mCAAyC;AACzC,qEAAgE;AAChE,wCAAkD;AAClD,oCAAwC;AACxC,sCAAuC;AAWhC,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAEL;IACA;IACA;IACA;IAJ5B,YAC4B,MAA4B,EAC5B,aAAmC,EACnC,YAA0B,EAC1B,MAAkB;QAHlB,WAAM,GAAN,MAAM,CAAsB;QAC5B,kBAAa,GAAb,aAAa,CAAsB;QACnC,iBAAY,GAAZ,YAAY,CAAc;QAC1B,WAAM,GAAN,MAAM,CAAY;IAC3C,CAAC;IAEG,KAAK,CAAC,eAAe,CAAC,KAAiC;QAC7D,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,WAAW,EAAE,GAAG,KAAK,CAAC;QAE3D,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;YAC7E,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1C,CAAC;QAED,MAAM,WAAW,GAA2B,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,WAAW,EAAE,CAAC;QAClF,IAAI,YAAY;YAAE,WAAW,CAAC,YAAY,GAAG,YAAY,CAAC;QAE1D,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;aAC9C,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;aAC5B,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,MAAM,QAAQ,GAAG,qBAAqB,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC;QAEpF,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAA6B,QAAQ,CAAC,CAAC;YAC7F,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC9E,OAAO,MAAM,CAAC;YACf,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,8CAA8C,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YAE7F,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;YACtE,IAAI,CAAC,MAAM,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;gBAC5E,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC1D,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YAE9F,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBAC5B,MAAM,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;gBAC7D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,kDAAkD,EAAE;oBAC3E,QAAQ;oBACR,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC;iBAChD,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,4CAA4C,EAAE;oBACrE,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,YAAY,EAAE,MAAM,CAAC,aAAa;iBAClC,CAAC,CAAC;YACJ,CAAC;YAED,OAAO,MAAoC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACzE,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,KAAiC;QAC7D,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YACzE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACrC,CAAC;QAED,MAAM,QAAQ,GAAG,gBAAgB,OAAO,EAAE,CAAC;QAE3C,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAA6B,QAAQ,CAAC,CAAC;YAC7F,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;gBACjF,OAAO,MAAM,CAAC;YACf,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,+CAA+C,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YAEhG,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;YACtE,IAAI,CAAC,MAAM,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;gBAC5E,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC1D,CAAC;YAED,MAAM,MAAM,GAA2B;gBACtC,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,mDAAmD;aAC3D,CAAC;YACF,IAAI,YAAY;gBAAE,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;YAErD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAEpF,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBAC5B,MAAM,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC9D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,0CAA0C,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YAC5F,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,6CAA6C,EAAE;oBACtE,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,YAAY,EAAE,MAAM,CAAC,aAAa;iBAClC,CAAC,CAAC;YACJ,CAAC;YAED,OAAO,MAAoC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1E,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,KAAmC;QACjE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;QACtC,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,oDAAoD,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;YACxG,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,gBAAgB,UAAU,IAAI,UAAU,EAAE,CAAC;QAE5D,IAAI,CAAC;YAiBJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;YACtE,IAAI,CAAC,MAAM,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;gBAC5E,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC1D,CAAC;YAED,MAAM,MAAM,GAAG,EAAE,MAAM,EAAE,GAAG,QAAQ,IAAI,SAAS,EAAE,EAAE,CAAC;YAEtD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAE9E,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBAC5B,MAAM,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC9D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,4CAA4C,EAAE;oBACrE,QAAQ;oBACR,YAAY,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;iBACzC,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,+CAA+C,EAAE;oBACxE,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,YAAY,EAAE,MAAM,CAAC,aAAa;iBAClC,CAAC,CAAC;YACJ,CAAC;YAED,OAAO,MAAsC,CAAC;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5E,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;CACD,CAAA;AAvKY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,gBAAO,GAAE;IAGP,WAAA,IAAA,eAAM,GAAE,CAAA;IACR,WAAA,IAAA,eAAM,GAAE,CAAA;IACR,WAAA,IAAA,eAAM,GAAE,CAAA;IACR,WAAA,IAAA,eAAM,GAAE,CAAA;qCAH0B,6CAAoB;QACb,8BAAoB;QACrB,oBAAY;QAClB,mBAAU;GALlC,qBAAqB,CAuKjC","sourcesContent":["import { Inject, Service } from 'typedi';\nimport { GoogleLocationClient } from './google-location.client';\nimport { SecretManagerService } from '../secrets';\nimport { RedisService } from '../redis';\nimport { LyxaLogger } from '../logger';\nimport {\n\tGoogleAutocompleteInputDTO,\n\tGoogleAutocompleteResponse,\n\tGooglePlaceDetailsInputDTO,\n\tGooglePlaceDetailsResponse,\n\tGoogleReverseGeocodeInputDTO,\n\tGoogleReverseGeocodeResponse,\n} from './google-location.dto';\n\n@Service()\nexport class GoogleLocationService {\n\tconstructor(\n\t\t@Inject() private readonly client: GoogleLocationClient,\n\t\t@Inject() private readonly secretManager: SecretManagerService,\n\t\t@Inject() private readonly redisService: RedisService,\n\t\t@Inject() private readonly logger: LyxaLogger\n\t) {}\n\n\tpublic async getAutocomplete(input: GoogleAutocompleteInputDTO): Promise<GoogleAutocompleteResponse> {\n\t\tconst { searchText, sessionToken, ...otherParams } = input;\n\n\t\tif (!searchText?.trim()) {\n\t\t\tthis.logger.logger.info('Google Autocomplete skipped: empty input provided');\n\t\t\treturn { predictions: [], status: 'OK' };\n\t\t}\n\n\t\tconst queryParams: Record<string, string> = { input: searchText, ...otherParams };\n\t\tif (sessionToken) queryParams.sessiontoken = sessionToken;\n\n\t\tconst querySummary = Object.entries(queryParams)\n\t\t\t.map(([k, v]) => `${k}:${v}`)\n\t\t\t.join('|');\n\t\tconst cacheKey = `maps:autocomplete:${this.redisService.sanitizeKey(querySummary)}`;\n\n\t\ttry {\n\t\t\tconst cached = await this.redisService.getCachedObject<GoogleAutocompleteResponse>(cacheKey);\n\t\t\tif (cached !== undefined) {\n\t\t\t\tthis.logger.logger.info('Google Autocomplete Cache HIT', { cacheKey, input });\n\t\t\t\treturn cached;\n\t\t\t}\n\n\t\t\tthis.logger.logger.info('Google Autocomplete Cache MISS - Calling API', { cacheKey, input });\n\n\t\t\tconst apiKey = await this.secretManager.getKey('GOOGLE_MAPS_API_KEY');\n\t\t\tif (!apiKey) {\n\t\t\t\tthis.logger.logger.error('GOOGLE_MAPS_API_KEY is missing in SecretManager');\n\t\t\t\tthrow new Error('GOOGLE_MAPS_API_KEY is not configured');\n\t\t\t}\n\n\t\t\tconst result = await this.client.callGoogleMapsAPI('place/autocomplete', apiKey, queryParams);\n\n\t\t\tif (result.status === 'OK') {\n\t\t\t\tawait this.redisService.cacheObject(cacheKey, result, 86400);\n\t\t\t\tthis.logger.logger.info('Google Autocomplete response cached successfully', {\n\t\t\t\t\tcacheKey,\n\t\t\t\t\tpredictionCount: result.predictions?.length ?? 0,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.logger.logger.warn('Google Autocomplete returned non-OK status', {\n\t\t\t\t\tstatus: result.status,\n\t\t\t\t\terrorMessage: result.error_message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn result as GoogleAutocompleteResponse;\n\t\t} catch (error) {\n\t\t\tthis.logger.logger.error('Google Autocomplete failed', { input, error });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async getPlaceDetails(input: GooglePlaceDetailsInputDTO): Promise<GooglePlaceDetailsResponse> {\n\t\tconst { placeId, sessionToken } = input;\n\t\tif (!placeId) {\n\t\t\tthis.logger.logger.error('Google Place Details failed: missing placeId');\n\t\t\tthrow new Error('Missing place_id');\n\t\t}\n\n\t\tconst cacheKey = `maps:details:${placeId}`;\n\n\t\ttry {\n\t\t\tconst cached = await this.redisService.getCachedObject<GooglePlaceDetailsResponse>(cacheKey);\n\t\t\tif (cached !== undefined) {\n\t\t\t\tthis.logger.logger.info('Google Place Details Cache HIT', { cacheKey, placeId });\n\t\t\t\treturn cached;\n\t\t\t}\n\n\t\t\tthis.logger.logger.info('Google Place Details Cache MISS - Calling API', { cacheKey, placeId });\n\n\t\t\tconst apiKey = await this.secretManager.getKey('GOOGLE_MAPS_API_KEY');\n\t\t\tif (!apiKey) {\n\t\t\t\tthis.logger.logger.error('GOOGLE_MAPS_API_KEY is missing in SecretManager');\n\t\t\t\tthrow new Error('GOOGLE_MAPS_API_KEY is not configured');\n\t\t\t}\n\n\t\t\tconst params: Record<string, string> = {\n\t\t\t\tplace_id: placeId,\n\t\t\t\tfields: 'name,formatted_address,geometry,address_component',\n\t\t\t};\n\t\t\tif (sessionToken) params.sessiontoken = sessionToken;\n\n\t\t\tconst result = await this.client.callGoogleMapsAPI('place/details', apiKey, params);\n\n\t\t\tif (result.status === 'OK') {\n\t\t\t\tawait this.redisService.cacheObject(cacheKey, result, 604800);\n\t\t\t\tthis.logger.logger.info('Google Place Details cached successfully', { cacheKey, placeId });\n\t\t\t} else {\n\t\t\t\tthis.logger.logger.warn('Google Place Details returned non-OK status', {\n\t\t\t\t\tstatus: result.status,\n\t\t\t\t\terrorMessage: result.error_message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn result as GooglePlaceDetailsResponse;\n\t\t} catch (error) {\n\t\t\tthis.logger.logger.error('Google Place Details failed', { input, error });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async getReverseGeocode(input: GoogleReverseGeocodeInputDTO): Promise<GoogleReverseGeocodeResponse> {\n\t\tconst { latitude, longitude } = input;\n\t\tif (!latitude || !longitude) {\n\t\t\tthis.logger.logger.error('Google Reverse Geocode failed: missing coordinates', { latitude, longitude });\n\t\t\tthrow new Error('Missing latitude or longitude');\n\t\t}\n\n\t\tconst roundedLat = parseFloat(latitude).toFixed(4);\n\t\tconst roundedLng = parseFloat(longitude).toFixed(4);\n\t\tconst cacheKey = `maps:geocode:${roundedLat}:${roundedLng}`;\n\n\t\ttry {\n\t\t\t/*\n\t\t\tRedis Cache logic \n\t\t\t*/\n\n\t\t\t// const cached = await this.redisService.getCachedObject<GoogleReverseGeocodeResponse>(cacheKey);\n\t\t\t// if (cached !== undefined) {\n\t\t\t// \tthis.logger.logger.info('Google Reverse Geocode Cache HIT', { cacheKey, roundedLat, roundedLng });\n\t\t\t// \treturn cached;\n\t\t\t// }\n\n\t\t\t// this.logger.logger.info('Google Reverse Geocode Cache MISS - Calling API', {\n\t\t\t// \tcacheKey,\n\t\t\t// \tlatitude,\n\t\t\t// \tlongitude,\n\t\t\t// });\n\n\t\t\tconst apiKey = await this.secretManager.getKey('GOOGLE_MAPS_API_KEY');\n\t\t\tif (!apiKey) {\n\t\t\t\tthis.logger.logger.error('GOOGLE_MAPS_API_KEY is missing in SecretManager');\n\t\t\t\tthrow new Error('GOOGLE_MAPS_API_KEY is not configured');\n\t\t\t}\n\n\t\t\tconst params = { latlng: `${latitude},${longitude}` };\n\n\t\t\tconst result = await this.client.callGoogleMapsAPI('geocode', apiKey, params);\n\n\t\t\tif (result.status === 'OK') {\n\t\t\t\tawait this.redisService.cacheObject(cacheKey, result, 259200);\n\t\t\t\tthis.logger.logger.info('Google Reverse Geocode cached successfully', {\n\t\t\t\t\tcacheKey,\n\t\t\t\t\tresultsCount: result.results?.length ?? 0,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.logger.logger.warn('Google Reverse Geocode returned non-OK status', {\n\t\t\t\t\tstatus: result.status,\n\t\t\t\t\terrorMessage: result.error_message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn result as GoogleReverseGeocodeResponse;\n\t\t} catch (error) {\n\t\t\tthis.logger.logger.error('Google Reverse Geocode failed', { input, error });\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"google-location.service.js","sourceRoot":"/","sources":["libraries/google-location/google-location.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inject, Service } from 'typedi';\nimport { GoogleLocationClient } from './google-location.client';\nimport { SecretManagerService } from '../secrets';\nimport { RedisService } from '../redis';\nimport { LyxaLogger } from '../logger';\nimport {\n\tGoogleAutocompleteInputDTO,\n\tGoogleAutocompleteResponse,\n\tGooglePlaceDetailsInputDTO,\n\tGooglePlaceDetailsResponse,\n\tGoogleReverseGeocodeInputDTO,\n\tGoogleReverseGeocodeResponse,\n} from './google-location.dto';\n\n@Service()\nexport class GoogleLocationService {\n\tconstructor(\n\t\t@Inject() private readonly client: GoogleLocationClient,\n\t\t@Inject() private readonly secretManager: SecretManagerService,\n\t\t@Inject() private readonly redisService: RedisService,\n\t\t@Inject() private readonly logger: LyxaLogger\n\t) {}\n\n\tpublic async getAutocomplete(input: GoogleAutocompleteInputDTO): Promise<GoogleAutocompleteResponse> {\n\t\tconst { searchText, sessionToken, ...otherParams } = input;\n\n\t\tif (!searchText?.trim()) {\n\t\t\tthis.logger.logger.info('Google Autocomplete skipped: empty input provided');\n\t\t\treturn { predictions: [], status: 'OK' };\n\t\t}\n\n\t\tconst cacheKey = `maps:autocomplete:${this.redisService.sanitizeKey(searchText.trim().toLowerCase())}`;\n\n\t\ttry {\n\t\t\tconst cached = await this.redisService.getCachedObject<GoogleAutocompleteResponse>(cacheKey);\n\t\t\tif (cached !== undefined) {\n\t\t\t\tthis.logger.logger.info('Google Autocomplete Cache HIT', { cacheKey, input });\n\t\t\t\treturn cached;\n\t\t\t}\n\n\t\t\tthis.logger.logger.info('Google Autocomplete Cache MISS - Calling API', { cacheKey, input });\n\n\t\t\tconst apiKey = await this.secretManager.getKey('GOOGLE_MAPS_API_KEY');\n\t\t\tif (!apiKey) {\n\t\t\t\tthis.logger.logger.error('GOOGLE_MAPS_API_KEY is missing in SecretManager');\n\t\t\t\tthrow new Error('GOOGLE_MAPS_API_KEY is not configured');\n\t\t\t}\n\n\t\t\tconst queryParams: Record<string, string> = { input: searchText, ...otherParams };\n\t\t\tif (sessionToken) queryParams.sessiontoken = sessionToken;\n\n\t\t\tconst result = await this.client.callGoogleMapsAPI('place/autocomplete', apiKey, queryParams);\n\n\t\t\tif (result.status === 'OK') {\n\t\t\t\tawait this.redisService.cacheObject(cacheKey, result, 604800);\n\t\t\t\tthis.logger.logger.info('Google Autocomplete response cached successfully', {\n\t\t\t\t\tcacheKey,\n\t\t\t\t\tpredictionCount: result.predictions?.length ?? 0,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.logger.logger.warn('Google Autocomplete returned non-OK status', {\n\t\t\t\t\tstatus: result.status,\n\t\t\t\t\terrorMessage: result.error_message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn result as GoogleAutocompleteResponse;\n\t\t} catch (error) {\n\t\t\tthis.logger.logger.error('Google Autocomplete failed', { input, error });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async getPlaceDetails(input: GooglePlaceDetailsInputDTO): Promise<GooglePlaceDetailsResponse> {\n\t\tconst { placeId, sessionToken } = input;\n\t\tif (!placeId) {\n\t\t\tthis.logger.logger.error('Google Place Details failed: missing placeId');\n\t\t\tthrow new Error('Missing place_id');\n\t\t}\n\n\t\tconst cacheKey = `maps:details:${placeId}`;\n\n\t\ttry {\n\t\t\tconst cached = await this.redisService.getCachedObject<GooglePlaceDetailsResponse>(cacheKey);\n\t\t\tif (cached !== undefined) {\n\t\t\t\tthis.logger.logger.info('Google Place Details Cache HIT', { cacheKey, placeId });\n\t\t\t\treturn cached;\n\t\t\t}\n\n\t\t\tthis.logger.logger.info('Google Place Details Cache MISS - Calling API', { cacheKey, placeId });\n\n\t\t\tconst apiKey = await this.secretManager.getKey('GOOGLE_MAPS_API_KEY');\n\t\t\tif (!apiKey) {\n\t\t\t\tthis.logger.logger.error('GOOGLE_MAPS_API_KEY is missing in SecretManager');\n\t\t\t\tthrow new Error('GOOGLE_MAPS_API_KEY is not configured');\n\t\t\t}\n\n\t\t\tconst params: Record<string, string> = {\n\t\t\t\tplace_id: placeId,\n\t\t\t\tfields: 'name,formatted_address,geometry,address_component',\n\t\t\t};\n\t\t\tif (sessionToken) params.sessiontoken = sessionToken;\n\n\t\t\tconst result = await this.client.callGoogleMapsAPI('place/details', apiKey, params);\n\n\t\t\tif (result.status === 'OK') {\n\t\t\t\tawait this.redisService.cacheObject(cacheKey, result, 604800);\n\t\t\t\tthis.logger.logger.info('Google Place Details cached successfully', { cacheKey, placeId });\n\t\t\t} else {\n\t\t\t\tthis.logger.logger.warn('Google Place Details returned non-OK status', {\n\t\t\t\t\tstatus: result.status,\n\t\t\t\t\terrorMessage: result.error_message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn result as GooglePlaceDetailsResponse;\n\t\t} catch (error) {\n\t\t\tthis.logger.logger.error('Google Place Details failed', { input, error });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async getReverseGeocode(input: GoogleReverseGeocodeInputDTO): Promise<GoogleReverseGeocodeResponse> {\n\t\tconst { latitude, longitude } = input;\n\t\tif (!latitude || !longitude) {\n\t\t\tthis.logger.logger.error('Google Reverse Geocode failed: missing coordinates', { latitude, longitude });\n\t\t\tthrow new Error('Missing latitude or longitude');\n\t\t}\n\n\t\tconst roundedLat = parseFloat(latitude).toFixed(4);\n\t\tconst roundedLng = parseFloat(longitude).toFixed(4);\n\t\tconst cacheKey = `maps:geocode:${roundedLat}:${roundedLng}`;\n\n\t\ttry {\n\t\t\tconst cached = await this.redisService.getCachedObject<GoogleReverseGeocodeResponse>(cacheKey);\n\t\t\tif (cached !== undefined) {\n\t\t\t\tthis.logger.logger.info('Google Reverse Geocode Cache HIT', { cacheKey, roundedLat, roundedLng });\n\t\t\t\treturn cached;\n\t\t\t}\n\n\t\t\tthis.logger.logger.info('Google Reverse Geocode Cache MISS - Calling API', {\n\t\t\t\tcacheKey,\n\t\t\t\tlatitude,\n\t\t\t\tlongitude,\n\t\t\t});\n\n\t\t\tconst apiKey = await this.secretManager.getKey('GOOGLE_MAPS_API_KEY');\n\t\t\tif (!apiKey) {\n\t\t\t\tthis.logger.logger.error('GOOGLE_MAPS_API_KEY is missing in SecretManager');\n\t\t\t\tthrow new Error('GOOGLE_MAPS_API_KEY is not configured');\n\t\t\t}\n\n\t\t\tconst params = { latlng: `${latitude},${longitude}` };\n\n\t\t\tconst result = await this.client.callGoogleMapsAPI('geocode', apiKey, params);\n\n\t\t\tif (result.status === 'OK') {\n\t\t\t\t/* redis cache create\n\t\t\t\tawait this.redisService.cacheObject(cacheKey, result, 259200);\n\t\t\t\tthis.logger.logger.info('Google Reverse Geocode cached successfully', {\n\t\t\t\t\tcacheKey,\n\t\t\t\t\tresultsCount: result.results?.length ?? 0,\n\t\t\t\t});\n\t\t\t\t*/\n\t\t\t} else {\n\t\t\t\tthis.logger.logger.warn('Google Reverse Geocode returned non-OK status', {\n\t\t\t\t\tstatus: result.status,\n\t\t\t\t\terrorMessage: result.error_message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn result as GoogleReverseGeocodeResponse;\n\t\t} catch (error) {\n\t\t\tthis.logger.logger.error('Google Reverse Geocode failed', { input, error });\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"]}
@@ -48,9 +48,9 @@ class OpenAICompletionProvider {
48
48
  }
49
49
  async generateSearchVariantsChunksInBatch(items, model, instructions, options) {
50
50
  const finalModel = model ?? this.model;
51
- const chunkSize = options?.chunkSize ?? 200;
51
+ const chunkSize = options?.chunkSize ?? 25;
52
52
  const maxArabic = options?.maxArabic ?? 1;
53
- const maxArabizi = options?.maxArabizi ?? 2;
53
+ const maxArabizi = options?.maxArabizi ?? 1;
54
54
  const maxTransliteration = options?.maxTransliteration ?? 1;
55
55
  const itemsToSend = items.filter(i => !i.skipAutoTranslation);
56
56
  const skippedItems = items.filter(i => i.skipAutoTranslation);
@@ -109,6 +109,7 @@ class OpenAICompletionProvider {
109
109
  const outputByChunk = await this.readJsonlFile(batch.output_file_id);
110
110
  const errorsByChunk = await this.readJsonlFile(batch.error_file_id);
111
111
  const resultsById = new Map();
112
+ let chunkParseFailures = 0;
112
113
  for (const [chunkId, record] of outputByChunk.entries()) {
113
114
  const body = record?.response?.body;
114
115
  const outputText = body?.output_text ??
@@ -140,10 +141,19 @@ class OpenAICompletionProvider {
140
141
  });
141
142
  }
142
143
  }
143
- catch {
144
- console.error(`generateSearchVariantsChunksInBatch: failed to parse output for ${chunkId}`, outputText);
144
+ catch (parseErr) {
145
+ chunkParseFailures++;
146
+ console.error(`generateSearchVariantsChunksInBatch: failed to parse output for ${chunkId}`, {
147
+ error: parseErr,
148
+ outputTextLength: outputText.length,
149
+ outputTextPreview: outputText.slice(0, 2000),
150
+ outputTextTail: outputText.slice(-500),
151
+ });
145
152
  }
146
153
  }
154
+ if (chunkParseFailures) {
155
+ console.error(`generateSearchVariantsChunksInBatch: ${chunkParseFailures}/${chunks.length} chunks failed to parse entirely — every item in those chunks will show as missing from LLM output below.`);
156
+ }
147
157
  const missingIds = itemsToSend.filter(i => !resultsById.has(i.id)).map(i => i.id);
148
158
  if (missingIds.length) {
149
159
  console.error(`generateSearchVariantsChunksInBatch: ${missingIds.length}/${itemsToSend.length} items missing from LLM output`, missingIds);
@@ -152,7 +162,7 @@ class OpenAICompletionProvider {
152
162
  const r = resultsById.get(id);
153
163
  if (!r) {
154
164
  console.error(`generateSearchVariantsChunksInBatch: no result for itemId=${id}`);
155
- return { id, original: text, processingFailed: true, isEmpty: true };
165
+ return { id, original: text, isProcessingFailed: true, isEmpty: true };
156
166
  }
157
167
  return { id, original: text, ...r };
158
168
  });
@@ -1 +1 @@
1
- {"version":3,"file":"openai-provider.js","sourceRoot":"/","sources":["libraries/llm/providers/openai-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI, { toFile } from 'openai';\nimport { IAICompletionProvider, ItemTextInput, TextVariantResult } from '../interfaces/common-llm-interfaces';\n\nexport class OpenAICompletionProvider implements IAICompletionProvider {\n\tprivate readonly client: OpenAI;\n\tprivate readonly model: string;\n\tprivate readonly ARABIC_CHAR_REGEX = /[\\u0600-\\u06FF]/;\n\n\tconstructor(apiKey: string | undefined, model: string = 'gpt-5-nano') {\n\t\tif (!apiKey) {\n\t\t\tthrow new Error('OPENAI_API_KEY is required to construct OpenAICompletionProvider');\n\t\t}\n\t\tthis.client = new OpenAI({ apiKey });\n\t\tthis.model = model;\n\t}\n\n\t// ── Cost-optimized batch path ────────────────────────────────────\n\t// Implements everything discussed:\n\t// 1. Chunking — groups items (default 200/chunk) into one line per\n\t// chunk, so `instructions` is billed once per chunk instead of\n\t// once per item (biggest single cost lever).\n\t// 2. Short output keys — model emits {id, ar, az, tr} instead of\n\t// {id, arabic, arabizi, arabicTransliteration}; mapped back\n\t// to full field names locally, at zero token cost.\n\t// 3. Capped array lengths — schema enforces maxItems (not just a\n\t// prose suggestion), so the model can't drift to longer arrays.\n\t// 4. No echoed fields — model never re-emits id/original text;\n\t// both are re-attached locally from the input you already have.\n\tasync generateSearchVariantsChunksInBatch(\n\t\titems: ItemTextInput[],\n\t\tmodel?: string,\n\t\tinstructions?: string,\n\t\toptions?: {\n\t\t\tchunkSize?: number;\n\t\t\tmaxArabic?: number;\n\t\t\tmaxArabizi?: number;\n\t\t\tmaxTransliteration?: number;\n\t\t\tpollIntervalMs?: number;\n\t\t\tmaxWaitMs?: number;\n\t\t}\n\t): Promise<TextVariantResult[]> {\n\t\tconst finalModel = model ?? this.model;\n\t\tconst chunkSize = options?.chunkSize ?? 200;\n\t\tconst maxArabic = options?.maxArabic ?? 1;\n\t\tconst maxArabizi = options?.maxArabizi ?? 2;\n\t\tconst maxTransliteration = options?.maxTransliteration ?? 1;\n\n\t\t// Items explicitly opted out — never sent to the model, just passed through.\n\t\tconst itemsToSend = items.filter(i => !i.skipAutoTranslation);\n\t\tconst skippedItems = items.filter(i => i.skipAutoTranslation);\n\n\t\tif (skippedItems.length) {\n\t\t\tconsole.log(\n\t\t\t\t`generateSearchVariantsChunksInBatch: skipping ${skippedItems.length}/${items.length} items due to skipAutoTranslation=true`\n\t\t\t);\n\t\t}\n\n\t\t// Nothing left to actually send — short-circuit before touching the OpenAI API at all.\n\t\tif (!itemsToSend.length) {\n\t\t\t// return skippedItems.map(({ id, text }) => ({ id, original: text, skipped: true }));\n\t\t\treturn [];\n\t\t}\n\n\t\ttry {\n\t\t\tconst finalInstructions =\n\t\t\t\tinstructions ?? this.buildOptimizedInstructions({ maxArabic, maxArabizi, maxTransliteration });\n\n\t\t\tconst chunkSchema = this.buildOptimizedChunkSchema({ maxArabic, maxArabizi, maxTransliteration });\n\n\t\t\tconst chunks = this.chunkItems(itemsToSend, chunkSize);\n\n\t\t\tif (chunks.length > 50_000) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Too many chunks (${chunks.length}) for a single batch file — increase chunkSize or split into multiple batch submissions.`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconsole.log(\n\t\t\t\t`generateSearchVariantsChunksInBatch: model=${finalModel} items=${itemsToSend.length} (${skippedItems.length} skipped) chunkSize=${chunkSize} chunks=${chunks.length}`\n\t\t\t);\n\n\t\t\t// 1. Build JSONL — ONE line per chunk, not per item\n\t\t\tconst jsonl = chunks\n\t\t\t\t.map((chunkItems, i) =>\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tcustom_id: `chunk-${i}`,\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\turl: '/v1/responses',\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\tmodel: finalModel,\n\t\t\t\t\t\t\tinstructions: finalInstructions,\n\t\t\t\t\t\t\tinput: JSON.stringify(chunkItems.map(({ id, text }) => ({ id: id, text }))),\n\t\t\t\t\t\t\ttext: {\n\t\t\t\t\t\t\t\tformat: {\n\t\t\t\t\t\t\t\t\ttype: 'json_schema',\n\t\t\t\t\t\t\t\t\tname: 'text_variants_batch',\n\t\t\t\t\t\t\t\t\tschema: chunkSchema,\n\t\t\t\t\t\t\t\t\tstrict: true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t\t.join('\\n');\n\n\t\t\t// 2. Upload input file\n\t\t\tconst inputFile = await this.client.files.create({\n\t\t\t\tfile: await toFile(Buffer.from(jsonl, 'utf-8'), 'batch-input-optimized.jsonl'),\n\t\t\t\tpurpose: 'batch',\n\t\t\t});\n\n\t\t\t// 3. Create batch job\n\t\t\tlet batch = await this.client.batches.create({\n\t\t\t\tinput_file_id: inputFile.id,\n\t\t\t\tendpoint: '/v1/responses',\n\t\t\t\tcompletion_window: '24h',\n\t\t\t});\n\n\t\t\t// 4. Poll until done\n\t\t\tbatch = await this.pollBatch(batch.id, options?.pollIntervalMs, options?.maxWaitMs);\n\n\t\t\tconsole.log({\n\t\t\t\tstatus: batch.status,\n\t\t\t\trequest_counts: batch.request_counts,\n\t\t\t\terrors: batch.errors,\n\t\t\t});\n\n\t\t\tif (batch.status !== 'completed') {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Batch ${batch.id} ended with status \"${batch.status}\" (${batch.request_counts?.failed ?? 0} failed)`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// 5. Parse output\n\t\t\tconst outputByChunk = await this.readJsonlFile(batch.output_file_id);\n\t\t\tconst errorsByChunk = await this.readJsonlFile(batch.error_file_id);\n\n\t\t\t// 6. Flatten chunk results into a per-itemId map\n\t\t\tconst resultsById = new Map<string, Partial<TextVariantResult>>();\n\n\t\t\tfor (const [chunkId, record] of outputByChunk.entries()) {\n\t\t\t\tconst body = record?.response?.body;\n\t\t\t\tconst outputText =\n\t\t\t\t\tbody?.output_text ??\n\t\t\t\t\tbody?.output\n\t\t\t\t\t\t?.find((o: any) => o.type === 'message')\n\t\t\t\t\t\t?.content?.find((c: any) => c.type === 'output_text')?.text;\n\n\t\t\t\tif (!outputText) {\n\t\t\t\t\tconst err = errorsByChunk.get(chunkId);\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`generateSearchVariantsChunksInBatch: no output for ${chunkId}`,\n\t\t\t\t\t\terr ?? record?.error\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(outputText) as {\n\t\t\t\t\t\tresults: Array<{ id: string; ar: string[]; az: string[]; tr: string[] }>;\n\t\t\t\t\t};\n\t\t\t\t\tfor (const r of parsed.results) {\n\t\t\t\t\t\tconst ar = this.sanitizeArabicArray(r.ar);\n\t\t\t\t\t\tconst tr = this.sanitizeArabicArray(r.tr);\n\t\t\t\t\t\tconst az = this.sanitizeLatinArray(r.az);\n\n\t\t\t\t\t\tconst isEmpty = this.isEmptyValue(r.ar) || this.isEmptyValue(r.az) || this.isEmptyValue(r.tr);\n\t\t\t\t\t\tconst isProcessingFailed = (!ar.length && !tr.length) || !az.length;\n\n\t\t\t\t\t\tif (isProcessingFailed) {\n\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t`generateSearchVariantsChunksInBatch: marking id=${r.id} as processingFailed — ar=${JSON.stringify(r.ar)} az=${JSON.stringify(r.az)} tr=${JSON.stringify(r.tr)}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresultsById.set(r.id, {\n\t\t\t\t\t\t\tarabic: ar,\n\t\t\t\t\t\t\tarabizi: az,\n\t\t\t\t\t\t\tarabicTransliteration: tr,\n\t\t\t\t\t\t\tisProcessingFailed,\n\t\t\t\t\t\t\tisEmpty,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`generateSearchVariantsChunksInBatch: failed to parse output for ${chunkId}`,\n\t\t\t\t\t\toutputText\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 7. Surface items the model silently dropped (only checked against what we actually sent)\n\t\t\tconst missingIds = itemsToSend.filter(i => !resultsById.has(i.id)).map(i => i.id);\n\t\t\tif (missingIds.length) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`generateSearchVariantsChunksInBatch: ${missingIds.length}/${itemsToSend.length} items missing from LLM output`,\n\t\t\t\t\tmissingIds\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// 8. Merge back with the FULL original item list — skipped items pass through untouched,\n\t\t\t// everything else is looked up in resultsById.\n\t\t\treturn items.map(({ id, text }) => {\n\t\t\t\tconst r = resultsById.get(id);\n\t\t\t\tif (!r) {\n\t\t\t\t\tconsole.error(`generateSearchVariantsChunksInBatch: no result for itemId=${id}`);\n\t\t\t\t\treturn { id, original: text, processingFailed: true, isEmpty: true };\n\t\t\t\t}\n\t\t\t\treturn { id, original: text, ...r } as TextVariantResult;\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsole.error('generateSearchVariantsChunksInBatch failed', {\n\t\t\t\terror,\n\t\t\t\titemCount: itemsToSend.length,\n\t\t\t\tmodel: finalModel,\n\t\t\t});\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t// ── Helpers ──────────────────────────────────────────────────────\n\n\t// Keeps only entries that actually contain Arabic-script characters — used for `ar`/`tr`,\n\t// which must never contain the raw English/Latin text the model was given.\n\tprivate sanitizeArabicArray(values: string[] | undefined): string[] {\n\t\treturn (values ?? []).filter(v => typeof v === 'string' && v.trim() && this.ARABIC_CHAR_REGEX.test(v));\n\t}\n\n\t// Keeps only entries that do NOT contain Arabic-script characters — used for `az`\n\t// (Latin/Arabizi variants), which must never contain Arabic script.\n\tprivate sanitizeLatinArray(values: string[] | undefined): string[] {\n\t\treturn (values ?? []).filter(v => typeof v === 'string' && v.trim() && !this.ARABIC_CHAR_REGEX.test(v));\n\t}\n\n\t// Compact instructions for the optimized path: short-key output format,\n\t// explicit array caps stated in prose (schema also enforces them),\n\t// and an explicit \"no commentary inside values\" rule to stop the model\n\t// padding fields with parenthetical notes.\n\tprivate buildOptimizedInstructions(caps: {\n\t\tmaxArabic: number;\n\t\tmaxArabizi: number;\n\t\tmaxTransliteration: number;\n\t}): string {\n\t\treturn [\n\t\t\t'You generate search-name variants for a food delivery app product/shop name.',\n\t\t\t'You will receive a JSON array of items, each with \"id\" and \"text\".',\n\t\t\t'For EACH item, return an object with:',\n\t\t\t`- id: the exact id provided (unchanged)`,\n\t\t\t`- ar: Arabic translation(s) in Arabic script, max ${caps.maxArabic}.`,\n\t\t\t`- az: Arabizi spelling(s) (Latin script/numerals, e.g. \"zaytoon\"), max ${caps.maxArabizi}.`,\n\t\t\t`- tr: Arabic-script transliteration(s) of the original word (not translated), max ${caps.maxTransliteration}.`,\n\t\t\t'Return one result per input item, same order, no items skipped or merged.',\n\t\t\t'Values must contain only the term itself — no parenthetical notes, no commentary.',\n\t\t\t'Return strict JSON matching the schema. No extra commentary, no extra fields.',\n\t\t].join('\\n');\n\t}\n\n\t// Schema for the OPTIMIZED chunk path: wraps a `results` array (one\n\t// entry per item in the chunk), short keys, and hard maxItems caps.\n\tprivate buildOptimizedChunkSchema(caps: {\n\t\tmaxArabic: number;\n\t\tmaxArabizi: number;\n\t\tmaxTransliteration: number;\n\t}) {\n\t\treturn {\n\t\t\ttype: 'object',\n\t\t\tproperties: {\n\t\t\t\tresults: {\n\t\t\t\t\ttype: 'array',\n\t\t\t\t\titems: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tid: { type: 'string' },\n\t\t\t\t\t\t\tar: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: caps.maxArabic },\n\t\t\t\t\t\t\taz: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: caps.maxArabizi },\n\t\t\t\t\t\t\ttr: {\n\t\t\t\t\t\t\t\ttype: 'array',\n\t\t\t\t\t\t\t\titems: { type: 'string' },\n\t\t\t\t\t\t\t\tminItems: 1,\n\t\t\t\t\t\t\t\tmaxItems: caps.maxTransliteration,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: ['id', 'ar', 'az', 'tr'],\n\t\t\t\t\t\tadditionalProperties: false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\trequired: ['results'],\n\t\t\tadditionalProperties: false,\n\t\t};\n\t}\n\n\tprivate chunkItems<T>(items: T[], size: number): T[][] {\n\t\tconst out: T[][] = [];\n\t\tfor (let i = 0; i < items.length; i += size) {\n\t\t\tout.push(items.slice(i, i + size));\n\t\t}\n\t\treturn out;\n\t}\n\n\tprivate async pollBatch(\n\t\tbatchId: string,\n\t\tintervalMs = 5000,\n\t\tmaxWaitMs = 24 * 60 * 60 * 1000\n\t): Promise<OpenAI.Batches.Batch> {\n\t\tconst terminal = new Set(['completed', 'failed', 'expired', 'cancelled']);\n\t\tconst start = Date.now();\n\n\t\twhile (true) {\n\t\t\tconst batch = await this.client.batches.retrieve(batchId);\n\t\t\tconsole.log(\n\t\t\t\t`pollBatch: ${batchId} status=${batch.status} elapsed=${Math.round((Date.now() - start) / 1000)}s`\n\t\t\t);\n\t\t\tif (terminal.has(batch.status)) return batch;\n\n\t\t\tif (Date.now() - start > maxWaitMs) {\n\t\t\t\tthrow new Error(`Batch ${batchId} did not finish within ${maxWaitMs}ms (status: ${batch.status})`);\n\t\t\t}\n\n\t\t\tawait new Promise(resolve => setTimeout(resolve, intervalMs));\n\t\t}\n\t}\n\n\tprivate async readJsonlFile(fileId: string | null | undefined): Promise<Map<string, any>> {\n\t\tconst result = new Map<string, any>();\n\t\tif (!fileId) return result;\n\n\t\tconst fileResponse = await this.client.files.content(fileId);\n\t\tconst text = await fileResponse.text();\n\n\t\tfor (const line of text.split('\\n').filter(Boolean)) {\n\t\t\tconst record = JSON.parse(line);\n\t\t\tresult.set(record.custom_id, record);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// Checks whether ar/az/tr came back empty in any sense the model might produce:\n\t// missing entirely (null/undefined), an empty array, or an array whose entries\n\t// are just empty/whitespace strings.\n\tprivate isEmptyValue(values: string[] | null | undefined): boolean {\n\t\tif (!values || values.length === 0) return true;\n\t\treturn values.every(v => typeof v !== 'string' || !v.trim());\n\t}\n}\n"]}
1
+ {"version":3,"file":"openai-provider.js","sourceRoot":"/","sources":["libraries/llm/providers/openai-provider.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAAwC;AAGxC,MAAa,wBAAwB;IACnB,MAAM,CAAS;IACf,KAAK,CAAS;IACd,iBAAiB,GAAG,iBAAiB,CAAC;IAEvD,YAAY,MAA0B,EAAE,QAAgB,YAAY;QACnE,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACrF,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,gBAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;IAeD,KAAK,CAAC,mCAAmC,CACxC,KAAsB,EACtB,KAAc,EACd,YAAqB,EACrB,OAOC;QAED,MAAM,UAAU,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;QAGvC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,CAAC,CAAC;QAG1C,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,CAAC,CAAC;QAC5C,MAAM,kBAAkB,GAAG,OAAO,EAAE,kBAAkB,IAAI,CAAC,CAAC;QAG5D,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;QAC9D,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;QAE9D,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CACV,iDAAiD,YAAY,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,wCAAwC,CAC5H,CAAC;QACH,CAAC;QAGD,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;YACzB,OAAO,EAAE,CAAC;QACX,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,iBAAiB,GACtB,YAAY,IAAI,IAAI,CAAC,0BAA0B,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAEhG,MAAM,WAAW,GAAG,IAAI,CAAC,yBAAyB,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAElG,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YAEvD,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACd,oBAAoB,MAAM,CAAC,MAAM,0FAA0F,CAC3H,CAAC;YACH,CAAC;YAED,OAAO,CAAC,GAAG,CACV,8CAA8C,UAAU,UAAU,WAAW,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM,uBAAuB,SAAS,WAAW,MAAM,CAAC,MAAM,EAAE,CACtK,CAAC;YAGF,MAAM,KAAK,GAAG,MAAM;iBAClB,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CACtB,IAAI,CAAC,SAAS,CAAC;gBACd,SAAS,EAAE,SAAS,CAAC,EAAE;gBACvB,MAAM,EAAE,MAAM;gBACd,GAAG,EAAE,eAAe;gBACpB,IAAI,EAAE;oBACL,KAAK,EAAE,UAAU;oBACjB,YAAY,EAAE,iBAAiB;oBAC/B,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;oBAC3E,IAAI,EAAE;wBACL,MAAM,EAAE;4BACP,IAAI,EAAE,aAAa;4BACnB,IAAI,EAAE,qBAAqB;4BAC3B,MAAM,EAAE,WAAW;4BACnB,MAAM,EAAE,IAAI;yBACZ;qBACD;iBACD;aACD,CAAC,CACF;iBACA,IAAI,CAAC,IAAI,CAAC,CAAC;YAGb,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;gBAChD,IAAI,EAAE,MAAM,IAAA,eAAM,EAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,6BAA6B,CAAC;gBAC9E,OAAO,EAAE,OAAO;aAChB,CAAC,CAAC;YAGH,IAAI,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC5C,aAAa,EAAE,SAAS,CAAC,EAAE;gBAC3B,QAAQ,EAAE,eAAe;gBACzB,iBAAiB,EAAE,KAAK;aACxB,CAAC,CAAC;YAGH,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YAEpF,OAAO,CAAC,GAAG,CAAC;gBACX,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,MAAM,EAAE,KAAK,CAAC,MAAM;aACpB,CAAC,CAAC;YAEH,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CACd,SAAS,KAAK,CAAC,EAAE,uBAAuB,KAAK,CAAC,MAAM,MAAM,KAAK,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC,UAAU,CACrG,CAAC;YACH,CAAC;YAGD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACrE,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YAGpE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAsC,CAAC;YAClE,IAAI,kBAAkB,GAAG,CAAC,CAAC;YAE3B,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC;gBACzD,MAAM,IAAI,GAAG,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC;gBACpC,MAAM,UAAU,GACf,IAAI,EAAE,WAAW;oBACjB,IAAI,EAAE,MAAM;wBACX,EAAE,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;wBACxC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,EAAE,IAAI,CAAC;gBAE9D,IAAI,CAAC,UAAU,EAAE,CAAC;oBACjB,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACvC,OAAO,CAAC,KAAK,CACZ,sDAAsD,OAAO,EAAE,EAC/D,GAAG,IAAI,MAAM,EAAE,KAAK,CACpB,CAAC;oBACF,SAAS;gBACV,CAAC;gBAED,IAAI,CAAC;oBACJ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAEnC,CAAC;oBACF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;wBAChC,MAAM,EAAE,GAAG,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;wBAC1C,MAAM,EAAE,GAAG,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;wBAC1C,MAAM,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;wBAEzC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;wBAC9F,MAAM,kBAAkB,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;wBAEpE,IAAI,kBAAkB,EAAE,CAAC;4BACxB,OAAO,CAAC,IAAI,CACX,mDAAmD,CAAC,CAAC,EAAE,6BAA6B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAChK,CAAC;wBACH,CAAC;wBAED,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;4BACrB,MAAM,EAAE,EAAE;4BACV,OAAO,EAAE,EAAE;4BACX,qBAAqB,EAAE,EAAE;4BACzB,kBAAkB;4BAClB,OAAO;yBACP,CAAC,CAAC;oBACJ,CAAC;gBACF,CAAC;gBAAC,OAAO,QAAQ,EAAE,CAAC;oBACnB,kBAAkB,EAAE,CAAC;oBAGrB,OAAO,CAAC,KAAK,CAAC,mEAAmE,OAAO,EAAE,EAAE;wBAC3F,KAAK,EAAE,QAAQ;wBACf,gBAAgB,EAAE,UAAU,CAAC,MAAM;wBACnC,iBAAiB,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;wBAC5C,cAAc,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC;qBACtC,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;YAED,IAAI,kBAAkB,EAAE,CAAC;gBACxB,OAAO,CAAC,KAAK,CACZ,wCAAwC,kBAAkB,IAAI,MAAM,CAAC,MAAM,2GAA2G,CACtL,CAAC;YACH,CAAC;YAGD,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAClF,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;gBACvB,OAAO,CAAC,KAAK,CACZ,wCAAwC,UAAU,CAAC,MAAM,IAAI,WAAW,CAAC,MAAM,gCAAgC,EAC/G,UAAU,CACV,CAAC;YACH,CAAC;YAID,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;gBACjC,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;oBACR,OAAO,CAAC,KAAK,CAAC,6DAA6D,EAAE,EAAE,CAAC,CAAC;oBAKjF,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBACxE,CAAC;gBACD,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,EAAuB,CAAC;YAC1D,CAAC,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE;gBAC3D,KAAK;gBACL,SAAS,EAAE,WAAW,CAAC,MAAM;gBAC7B,KAAK,EAAE,UAAU;aACjB,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAMO,mBAAmB,CAAC,MAA4B;QACvD,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACxG,CAAC;IAIO,kBAAkB,CAAC,MAA4B;QACtD,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACzG,CAAC;IAMO,0BAA0B,CAAC,IAIlC;QACA,OAAO;YACN,8EAA8E;YAC9E,oEAAoE;YACpE,uCAAuC;YACvC,yCAAyC;YACzC,qDAAqD,IAAI,CAAC,SAAS,GAAG;YACtE,0EAA0E,IAAI,CAAC,UAAU,GAAG;YAC5F,qFAAqF,IAAI,CAAC,kBAAkB,GAAG;YAC/G,2EAA2E;YAC3E,mFAAmF;YACnF,+EAA+E;SAC/E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,CAAC;IAIO,yBAAyB,CAAC,IAIjC;QACA,OAAO;YACN,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACX,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;4BACtB,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE;4BACvF,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE;4BACxF,EAAE,EAAE;gCACH,IAAI,EAAE,OAAO;gCACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gCACzB,QAAQ,EAAE,CAAC;gCACX,QAAQ,EAAE,IAAI,CAAC,kBAAkB;6BACjC;yBACD;wBACD,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;wBAClC,oBAAoB,EAAE,KAAK;qBAC3B;iBACD;aACD;YACD,QAAQ,EAAE,CAAC,SAAS,CAAC;YACrB,oBAAoB,EAAE,KAAK;SAC3B,CAAC;IACH,CAAC;IAEO,UAAU,CAAI,KAAU,EAAE,IAAY;QAC7C,MAAM,GAAG,GAAU,EAAE,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;YAC7C,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAEO,KAAK,CAAC,SAAS,CACtB,OAAe,EACf,UAAU,GAAG,IAAI,EACjB,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;QAE/B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;QAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEzB,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CACV,cAAc,OAAO,WAAW,KAAK,CAAC,MAAM,YAAY,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAClG,CAAC;YACF,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;gBAAE,OAAO,KAAK,CAAC;YAE7C,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,SAAS,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,0BAA0B,SAAS,eAAe,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;YACpG,CAAC;YAED,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;QAC/D,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,MAAiC;QAC5D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAe,CAAC;QACtC,IAAI,CAAC,MAAM;YAAE,OAAO,MAAM,CAAC;QAE3B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC;QAEvC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;IAKO,YAAY,CAAC,MAAmC;QACvD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAChD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;CACD;AA1WD,4DA0WC","sourcesContent":["import OpenAI, { toFile } from 'openai';\nimport { IAICompletionProvider, ItemTextInput, TextVariantResult } from '../interfaces/common-llm-interfaces';\n\nexport class OpenAICompletionProvider implements IAICompletionProvider {\n\tprivate readonly client: OpenAI;\n\tprivate readonly model: string;\n\tprivate readonly ARABIC_CHAR_REGEX = /[\\u0600-\\u06FF]/;\n\n\tconstructor(apiKey: string | undefined, model: string = 'gpt-5-nano') {\n\t\tif (!apiKey) {\n\t\t\tthrow new Error('OPENAI_API_KEY is required to construct OpenAICompletionProvider');\n\t\t}\n\t\tthis.client = new OpenAI({ apiKey });\n\t\tthis.model = model;\n\t}\n\n\t// ── Cost-optimized batch path ────────────────────────────────────\n\t// Implements everything discussed:\n\t// 1. Chunking — groups items (default 25/chunk — kept small so a single\n\t// malformed/truncated model response only takes out a small slice of\n\t// items instead of ~100+ at once) into one line per chunk, so\n\t// `instructions` is billed once per chunk instead of once per item.\n\t// 2. Short output keys — model emits {id, ar, az, tr} instead of\n\t// {id, arabic, arabizi, arabicTransliteration}; mapped back\n\t// to full field names locally, at zero token cost.\n\t// 3. Capped array lengths — schema enforces maxItems (not just a\n\t// prose suggestion), so the model can't drift to longer arrays.\n\t// 4. No echoed fields — model never re-emits id/original text;\n\t// both are re-attached locally from the input you already have.\n\tasync generateSearchVariantsChunksInBatch(\n\t\titems: ItemTextInput[],\n\t\tmodel?: string,\n\t\tinstructions?: string,\n\t\toptions?: {\n\t\t\tchunkSize?: number;\n\t\t\tmaxArabic?: number;\n\t\t\tmaxArabizi?: number;\n\t\t\tmaxTransliteration?: number;\n\t\t\tpollIntervalMs?: number;\n\t\t\tmaxWaitMs?: number;\n\t\t}\n\t): Promise<TextVariantResult[]> {\n\t\tconst finalModel = model ?? this.model;\n\t\t// Kept intentionally small — large chunks (100+) risk the model truncating or\n\t\t// malforming output for the WHOLE chunk, which drops every item in it at once.\n\t\tconst chunkSize = options?.chunkSize ?? 25;\n\t\tconst maxArabic = options?.maxArabic ?? 1;\n\t\t// Reduced from 2 → 1 by default: fewer required strings per item means less total\n\t\t// output per chunk, which lowers the chance of hitting a truncation/formatting issue.\n\t\tconst maxArabizi = options?.maxArabizi ?? 1;\n\t\tconst maxTransliteration = options?.maxTransliteration ?? 1;\n\n\t\t// Items explicitly opted out — never sent to the model, just passed through.\n\t\tconst itemsToSend = items.filter(i => !i.skipAutoTranslation);\n\t\tconst skippedItems = items.filter(i => i.skipAutoTranslation);\n\n\t\tif (skippedItems.length) {\n\t\t\tconsole.log(\n\t\t\t\t`generateSearchVariantsChunksInBatch: skipping ${skippedItems.length}/${items.length} items due to skipAutoTranslation=true`\n\t\t\t);\n\t\t}\n\n\t\t// Nothing left to actually send — short-circuit before touching the OpenAI API at all.\n\t\tif (!itemsToSend.length) {\n\t\t\treturn [];\n\t\t}\n\n\t\ttry {\n\t\t\tconst finalInstructions =\n\t\t\t\tinstructions ?? this.buildOptimizedInstructions({ maxArabic, maxArabizi, maxTransliteration });\n\n\t\t\tconst chunkSchema = this.buildOptimizedChunkSchema({ maxArabic, maxArabizi, maxTransliteration });\n\n\t\t\tconst chunks = this.chunkItems(itemsToSend, chunkSize);\n\n\t\t\tif (chunks.length > 50_000) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Too many chunks (${chunks.length}) for a single batch file — increase chunkSize or split into multiple batch submissions.`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconsole.log(\n\t\t\t\t`generateSearchVariantsChunksInBatch: model=${finalModel} items=${itemsToSend.length} (${skippedItems.length} skipped) chunkSize=${chunkSize} chunks=${chunks.length}`\n\t\t\t);\n\n\t\t\t// 1. Build JSONL — ONE line per chunk, not per item\n\t\t\tconst jsonl = chunks\n\t\t\t\t.map((chunkItems, i) =>\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\tcustom_id: `chunk-${i}`,\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\turl: '/v1/responses',\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\tmodel: finalModel,\n\t\t\t\t\t\t\tinstructions: finalInstructions,\n\t\t\t\t\t\t\tinput: JSON.stringify(chunkItems.map(({ id, text }) => ({ id: id, text }))),\n\t\t\t\t\t\t\ttext: {\n\t\t\t\t\t\t\t\tformat: {\n\t\t\t\t\t\t\t\t\ttype: 'json_schema',\n\t\t\t\t\t\t\t\t\tname: 'text_variants_batch',\n\t\t\t\t\t\t\t\t\tschema: chunkSchema,\n\t\t\t\t\t\t\t\t\tstrict: true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t\t.join('\\n');\n\n\t\t\t// 2. Upload input file\n\t\t\tconst inputFile = await this.client.files.create({\n\t\t\t\tfile: await toFile(Buffer.from(jsonl, 'utf-8'), 'batch-input-optimized.jsonl'),\n\t\t\t\tpurpose: 'batch',\n\t\t\t});\n\n\t\t\t// 3. Create batch job\n\t\t\tlet batch = await this.client.batches.create({\n\t\t\t\tinput_file_id: inputFile.id,\n\t\t\t\tendpoint: '/v1/responses',\n\t\t\t\tcompletion_window: '24h',\n\t\t\t});\n\n\t\t\t// 4. Poll until done\n\t\t\tbatch = await this.pollBatch(batch.id, options?.pollIntervalMs, options?.maxWaitMs);\n\n\t\t\tconsole.log({\n\t\t\t\tstatus: batch.status,\n\t\t\t\trequest_counts: batch.request_counts,\n\t\t\t\terrors: batch.errors,\n\t\t\t});\n\n\t\t\tif (batch.status !== 'completed') {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Batch ${batch.id} ended with status \"${batch.status}\" (${batch.request_counts?.failed ?? 0} failed)`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// 5. Parse output\n\t\t\tconst outputByChunk = await this.readJsonlFile(batch.output_file_id);\n\t\t\tconst errorsByChunk = await this.readJsonlFile(batch.error_file_id);\n\n\t\t\t// 6. Flatten chunk results into a per-itemId map\n\t\t\tconst resultsById = new Map<string, Partial<TextVariantResult>>();\n\t\t\tlet chunkParseFailures = 0;\n\n\t\t\tfor (const [chunkId, record] of outputByChunk.entries()) {\n\t\t\t\tconst body = record?.response?.body;\n\t\t\t\tconst outputText =\n\t\t\t\t\tbody?.output_text ??\n\t\t\t\t\tbody?.output\n\t\t\t\t\t\t?.find((o: any) => o.type === 'message')\n\t\t\t\t\t\t?.content?.find((c: any) => c.type === 'output_text')?.text;\n\n\t\t\t\tif (!outputText) {\n\t\t\t\t\tconst err = errorsByChunk.get(chunkId);\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`generateSearchVariantsChunksInBatch: no output for ${chunkId}`,\n\t\t\t\t\t\terr ?? record?.error\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(outputText) as {\n\t\t\t\t\t\tresults: Array<{ id: string; ar: string[]; az: string[]; tr: string[] }>;\n\t\t\t\t\t};\n\t\t\t\t\tfor (const r of parsed.results) {\n\t\t\t\t\t\tconst ar = this.sanitizeArabicArray(r.ar);\n\t\t\t\t\t\tconst tr = this.sanitizeArabicArray(r.tr);\n\t\t\t\t\t\tconst az = this.sanitizeLatinArray(r.az);\n\n\t\t\t\t\t\tconst isEmpty = this.isEmptyValue(r.ar) || this.isEmptyValue(r.az) || this.isEmptyValue(r.tr);\n\t\t\t\t\t\tconst isProcessingFailed = (!ar.length && !tr.length) || !az.length;\n\n\t\t\t\t\t\tif (isProcessingFailed) {\n\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t`generateSearchVariantsChunksInBatch: marking id=${r.id} as processingFailed — ar=${JSON.stringify(r.ar)} az=${JSON.stringify(r.az)} tr=${JSON.stringify(r.tr)}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresultsById.set(r.id, {\n\t\t\t\t\t\t\tarabic: ar,\n\t\t\t\t\t\t\tarabizi: az,\n\t\t\t\t\t\t\tarabicTransliteration: tr,\n\t\t\t\t\t\t\tisProcessingFailed,\n\t\t\t\t\t\t\tisEmpty,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (parseErr) {\n\t\t\t\t\tchunkParseFailures++;\n\t\t\t\t\t// Log a preview + length of the raw output so you can tell WHY it failed —\n\t\t\t\t\t// truncated mid-JSON (hit output length) vs. malformed/extra text vs. something else.\n\t\t\t\t\tconsole.error(`generateSearchVariantsChunksInBatch: failed to parse output for ${chunkId}`, {\n\t\t\t\t\t\terror: parseErr,\n\t\t\t\t\t\toutputTextLength: outputText.length,\n\t\t\t\t\t\toutputTextPreview: outputText.slice(0, 2000),\n\t\t\t\t\t\toutputTextTail: outputText.slice(-500),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (chunkParseFailures) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`generateSearchVariantsChunksInBatch: ${chunkParseFailures}/${chunks.length} chunks failed to parse entirely — every item in those chunks will show as missing from LLM output below.`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// 7. Surface items the model silently dropped (only checked against what we actually sent)\n\t\t\tconst missingIds = itemsToSend.filter(i => !resultsById.has(i.id)).map(i => i.id);\n\t\t\tif (missingIds.length) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`generateSearchVariantsChunksInBatch: ${missingIds.length}/${itemsToSend.length} items missing from LLM output`,\n\t\t\t\t\tmissingIds\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// 8. Merge back with the FULL original item list — skipped items pass through untouched,\n\t\t\t// everything else is looked up in resultsById.\n\t\t\treturn items.map(({ id, text }) => {\n\t\t\t\tconst r = resultsById.get(id);\n\t\t\t\tif (!r) {\n\t\t\t\t\tconsole.error(`generateSearchVariantsChunksInBatch: no result for itemId=${id}`);\n\t\t\t\t\t// NOTE: key must be isProcessingFailed (matches the shape set above and what\n\t\t\t\t\t// hasAnyFailedField/isFieldUsable check downstream) — a prior version of this\n\t\t\t\t\t// fallback used `processingFailed` (wrong key), which meant callers saw\n\t\t\t\t\t// isProcessingFailed=undefined for every dropped item instead of true.\n\t\t\t\t\treturn { id, original: text, isProcessingFailed: true, isEmpty: true };\n\t\t\t\t}\n\t\t\t\treturn { id, original: text, ...r } as TextVariantResult;\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsole.error('generateSearchVariantsChunksInBatch failed', {\n\t\t\t\terror,\n\t\t\t\titemCount: itemsToSend.length,\n\t\t\t\tmodel: finalModel,\n\t\t\t});\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t// ── Helpers ──────────────────────────────────────────────────────\n\n\t// Keeps only entries that actually contain Arabic-script characters — used for `ar`/`tr`,\n\t// which must never contain the raw English/Latin text the model was given.\n\tprivate sanitizeArabicArray(values: string[] | undefined): string[] {\n\t\treturn (values ?? []).filter(v => typeof v === 'string' && v.trim() && this.ARABIC_CHAR_REGEX.test(v));\n\t}\n\n\t// Keeps only entries that do NOT contain Arabic-script characters — used for `az`\n\t// (Latin/Arabizi variants), which must never contain Arabic script.\n\tprivate sanitizeLatinArray(values: string[] | undefined): string[] {\n\t\treturn (values ?? []).filter(v => typeof v === 'string' && v.trim() && !this.ARABIC_CHAR_REGEX.test(v));\n\t}\n\n\t// Compact instructions for the optimized path: short-key output format,\n\t// explicit array caps stated in prose (schema also enforces them),\n\t// and an explicit \"no commentary inside values\" rule to stop the model\n\t// padding fields with parenthetical notes.\n\tprivate buildOptimizedInstructions(caps: {\n\t\tmaxArabic: number;\n\t\tmaxArabizi: number;\n\t\tmaxTransliteration: number;\n\t}): string {\n\t\treturn [\n\t\t\t'You generate search-name variants for a food delivery app product/shop name.',\n\t\t\t'You will receive a JSON array of items, each with \"id\" and \"text\".',\n\t\t\t'For EACH item, return an object with:',\n\t\t\t`- id: the exact id provided (unchanged)`,\n\t\t\t`- ar: Arabic translation(s) in Arabic script, max ${caps.maxArabic}.`,\n\t\t\t`- az: Arabizi spelling(s) (Latin script/numerals, e.g. \"zaytoon\"), max ${caps.maxArabizi}.`,\n\t\t\t`- tr: Arabic-script transliteration(s) of the original word (not translated), max ${caps.maxTransliteration}.`,\n\t\t\t'Return one result per input item, same order, no items skipped or merged.',\n\t\t\t'Values must contain only the term itself — no parenthetical notes, no commentary.',\n\t\t\t'Return strict JSON matching the schema. No extra commentary, no extra fields.',\n\t\t].join('\\n');\n\t}\n\n\t// Schema for the OPTIMIZED chunk path: wraps a `results` array (one\n\t// entry per item in the chunk), short keys, and hard maxItems caps.\n\tprivate buildOptimizedChunkSchema(caps: {\n\t\tmaxArabic: number;\n\t\tmaxArabizi: number;\n\t\tmaxTransliteration: number;\n\t}) {\n\t\treturn {\n\t\t\ttype: 'object',\n\t\t\tproperties: {\n\t\t\t\tresults: {\n\t\t\t\t\ttype: 'array',\n\t\t\t\t\titems: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tid: { type: 'string' },\n\t\t\t\t\t\t\tar: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: caps.maxArabic },\n\t\t\t\t\t\t\taz: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: caps.maxArabizi },\n\t\t\t\t\t\t\ttr: {\n\t\t\t\t\t\t\t\ttype: 'array',\n\t\t\t\t\t\t\t\titems: { type: 'string' },\n\t\t\t\t\t\t\t\tminItems: 1,\n\t\t\t\t\t\t\t\tmaxItems: caps.maxTransliteration,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequired: ['id', 'ar', 'az', 'tr'],\n\t\t\t\t\t\tadditionalProperties: false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\trequired: ['results'],\n\t\t\tadditionalProperties: false,\n\t\t};\n\t}\n\n\tprivate chunkItems<T>(items: T[], size: number): T[][] {\n\t\tconst out: T[][] = [];\n\t\tfor (let i = 0; i < items.length; i += size) {\n\t\t\tout.push(items.slice(i, i + size));\n\t\t}\n\t\treturn out;\n\t}\n\n\tprivate async pollBatch(\n\t\tbatchId: string,\n\t\tintervalMs = 5000,\n\t\tmaxWaitMs = 24 * 60 * 60 * 1000\n\t): Promise<OpenAI.Batches.Batch> {\n\t\tconst terminal = new Set(['completed', 'failed', 'expired', 'cancelled']);\n\t\tconst start = Date.now();\n\n\t\twhile (true) {\n\t\t\tconst batch = await this.client.batches.retrieve(batchId);\n\t\t\tconsole.log(\n\t\t\t\t`pollBatch: ${batchId} status=${batch.status} elapsed=${Math.round((Date.now() - start) / 1000)}s`\n\t\t\t);\n\t\t\tif (terminal.has(batch.status)) return batch;\n\n\t\t\tif (Date.now() - start > maxWaitMs) {\n\t\t\t\tthrow new Error(`Batch ${batchId} did not finish within ${maxWaitMs}ms (status: ${batch.status})`);\n\t\t\t}\n\n\t\t\tawait new Promise(resolve => setTimeout(resolve, intervalMs));\n\t\t}\n\t}\n\n\tprivate async readJsonlFile(fileId: string | null | undefined): Promise<Map<string, any>> {\n\t\tconst result = new Map<string, any>();\n\t\tif (!fileId) return result;\n\n\t\tconst fileResponse = await this.client.files.content(fileId);\n\t\tconst text = await fileResponse.text();\n\n\t\tfor (const line of text.split('\\n').filter(Boolean)) {\n\t\t\tconst record = JSON.parse(line);\n\t\t\tresult.set(record.custom_id, record);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t// Checks whether ar/az/tr came back empty in any sense the model might produce:\n\t// missing entirely (null/undefined), an empty array, or an array whose entries\n\t// are just empty/whitespace strings.\n\tprivate isEmptyValue(values: string[] | null | undefined): boolean {\n\t\tif (!values || values.length === 0) return true;\n\t\treturn values.every(v => typeof v !== 'string' || !v.trim());\n\t}\n}\n"]}
@@ -2,7 +2,12 @@ import { Ref } from '@typegoose/typegoose';
2
2
  import { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';
3
3
  import { User } from './user.model';
4
4
  import { Shop } from './shop.model';
5
+ export declare class ShopOrderCount {
6
+ shop: Ref<Shop>;
7
+ count: number;
8
+ lastOrderedAt: Date;
9
+ }
5
10
  export declare class UserShopHistory extends TimeStamps {
6
11
  user: Ref<User>;
7
- shops?: Ref<Shop>[];
12
+ shops: ShopOrderCount[];
8
13
  }
@@ -9,11 +9,29 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.UserShopHistory = void 0;
12
+ exports.UserShopHistory = exports.ShopOrderCount = void 0;
13
13
  const typegoose_1 = require("@typegoose/typegoose");
14
14
  const defaultClasses_1 = require("@typegoose/typegoose/lib/defaultClasses");
15
15
  const user_model_1 = require("./user.model");
16
16
  const shop_model_1 = require("./shop.model");
17
+ class ShopOrderCount {
18
+ shop;
19
+ count;
20
+ lastOrderedAt;
21
+ }
22
+ exports.ShopOrderCount = ShopOrderCount;
23
+ __decorate([
24
+ (0, typegoose_1.prop)({ required: true, ref: () => shop_model_1.Shop }),
25
+ __metadata("design:type", Object)
26
+ ], ShopOrderCount.prototype, "shop", void 0);
27
+ __decorate([
28
+ (0, typegoose_1.prop)({ required: true, type: Number, default: 1 }),
29
+ __metadata("design:type", Number)
30
+ ], ShopOrderCount.prototype, "count", void 0);
31
+ __decorate([
32
+ (0, typegoose_1.prop)({ required: true, type: Date, default: Date.now }),
33
+ __metadata("design:type", Date)
34
+ ], ShopOrderCount.prototype, "lastOrderedAt", void 0);
17
35
  let UserShopHistory = class UserShopHistory extends defaultClasses_1.TimeStamps {
18
36
  user;
19
37
  shops;
@@ -24,11 +42,12 @@ __decorate([
24
42
  __metadata("design:type", Object)
25
43
  ], UserShopHistory.prototype, "user", void 0);
26
44
  __decorate([
27
- (0, typegoose_1.prop)({ ref: () => shop_model_1.Shop }),
45
+ (0, typegoose_1.prop)({ type: () => [ShopOrderCount], default: [] }),
28
46
  __metadata("design:type", Array)
29
47
  ], UserShopHistory.prototype, "shops", void 0);
30
48
  exports.UserShopHistory = UserShopHistory = __decorate([
31
49
  (0, typegoose_1.modelOptions)({ schemaOptions: { collection: 'userShopHistories' } }),
32
- (0, typegoose_1.index)({ user: 1 }, { unique: true })
50
+ (0, typegoose_1.index)({ user: 1 }, { unique: true }),
51
+ (0, typegoose_1.index)({ 'shops.shop': 1 })
33
52
  ], UserShopHistory);
34
53
  //# sourceMappingURL=user-shop-history.model.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-shop-history.model.js","sourceRoot":"/","sources":["libraries/mongo/models/user-shop-history.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAAsE;AACtE,4EAAqE;AACrE,6CAAoC;AACpC,6CAAoC;AAO7B,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,2BAAU;IAEvC,IAAI,CAAa;IAGjB,KAAK,CAAe;CAC3B,CAAA;AANY,0CAAe;AAEpB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;6CAClB;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;8CACC;0BALf,eAAe;IAF3B,IAAA,wBAAY,EAAC,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,mBAAmB,EAAE,EAAE,CAAC;IACpE,IAAA,iBAAK,EAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;GACxB,eAAe,CAM3B","sourcesContent":["import { index, modelOptions, prop, Ref } from '@typegoose/typegoose';\nimport { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';\nimport { User } from './user.model';\nimport { Shop } from './shop.model';\n\n/**\n * UserShopHistory model - Tracks the shops a user is associated with (eligible/ordered-from shops)\n */\n@modelOptions({ schemaOptions: { collection: 'userShopHistories' } })\n@index({ user: 1 }, { unique: true })\nexport class UserShopHistory extends TimeStamps {\n\t@prop({ required: true, ref: () => User })\n\tpublic user!: Ref<User>;\n\n\t@prop({ ref: () => Shop })\n\tpublic shops?: Ref<Shop>[];\n}\n"]}
1
+ {"version":3,"file":"user-shop-history.model.js","sourceRoot":"/","sources":["libraries/mongo/models/user-shop-history.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAAsE;AACtE,4EAAqE;AACrE,6CAAoC;AACpC,6CAAoC;AAEpC,MAAa,cAAc;IAEnB,IAAI,CAAa;IAGjB,KAAK,CAAU;IAGf,aAAa,CAAQ;CAC5B;AATD,wCASC;AAPO;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;4CAClB;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;6CAC7B;AAGf;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;8BACjC,IAAI;qDAAC;AAStB,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,2BAAU;IAEvC,IAAI,CAAa;IAGjB,KAAK,CAAoB;CAChC,CAAA;AANY,0CAAe;AAEpB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;6CAClB;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;;8CACpB;0BALpB,eAAe;IAH3B,IAAA,wBAAY,EAAC,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,mBAAmB,EAAE,EAAE,CAAC;IACpE,IAAA,iBAAK,EAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACpC,IAAA,iBAAK,EAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;GACd,eAAe,CAM3B","sourcesContent":["import { index, modelOptions, prop, Ref } from '@typegoose/typegoose';\nimport { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';\nimport { User } from './user.model';\nimport { Shop } from './shop.model';\n\nexport class ShopOrderCount {\n\t@prop({ required: true, ref: () => Shop })\n\tpublic shop!: Ref<Shop>;\n\n\t@prop({ required: true, type: Number, default: 1 })\n\tpublic count!: number;\n\n\t@prop({ required: true, type: Date, default: Date.now })\n\tpublic lastOrderedAt!: Date;\n}\n\n/**\n * UserShopHistory model - Tracks the shops a user is associated with (eligible/ordered-from shops)\n */\n@modelOptions({ schemaOptions: { collection: 'userShopHistories' } })\n@index({ user: 1 }, { unique: true })\n@index({ 'shops.shop': 1 })\nexport class UserShopHistory extends TimeStamps {\n\t@prop({ required: true, ref: () => User })\n\tpublic user!: Ref<User>;\n\n\t@prop({ type: () => [ShopOrderCount], default: [] })\n\tpublic shops!: ShopOrderCount[];\n}\n"]}
@@ -20,13 +20,13 @@ export declare const ChatroomMessageSendOutputSchema: z.ZodObject<{
20
20
  name: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
21
21
  type: z.ZodNativeEnum<typeof UserRef>;
22
22
  }, "strip", z.ZodTypeAny, {
23
- type: UserRef;
24
23
  name: string;
25
24
  id: import("mongoose").Types.ObjectId;
26
- }, {
27
25
  type: UserRef;
26
+ }, {
28
27
  name: string;
29
28
  id: import("mongoose").Types.ObjectId;
29
+ type: UserRef;
30
30
  }>;
31
31
  content: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
32
32
  media: z.ZodArray<z.ZodObject<{
@@ -36,14 +36,14 @@ export declare const ChatroomMessageSendOutputSchema: z.ZodObject<{
36
36
  thumbnailUrl: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
37
37
  name: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
38
38
  }, "strip", z.ZodTypeAny, {
39
- mediaUrl: string;
40
39
  mediaType: MediaType;
40
+ mediaUrl: string;
41
41
  mimeType: string;
42
42
  name?: string | undefined;
43
43
  thumbnailUrl?: string | undefined;
44
44
  }, {
45
- mediaUrl: string;
46
45
  mediaType: MediaType;
46
+ mediaUrl: string;
47
47
  mimeType: string;
48
48
  name?: string | undefined;
49
49
  thumbnailUrl?: string | undefined;
@@ -63,17 +63,17 @@ export declare const ChatroomMessageSendOutputSchema: z.ZodObject<{
63
63
  orderId: z.ZodOptional<z.ZodEffects<z.ZodType<import("mongoose").Types.ObjectId, z.ZodTypeDef, import("mongoose").Types.ObjectId>, import("mongoose").Types.ObjectId, import("mongoose").Types.ObjectId>>;
64
64
  createdAt: z.ZodEffects<z.ZodEffects<z.ZodDate, Date, Date>, Date, Date>;
65
65
  }, "strip", z.ZodTypeAny, {
66
- _id: import("mongoose").Types.ObjectId;
67
66
  createdAt: Date;
67
+ _id: import("mongoose").Types.ObjectId;
68
68
  sender: {
69
- type: UserRef;
70
69
  name: string;
71
70
  id: import("mongoose").Types.ObjectId;
71
+ type: UserRef;
72
72
  };
73
73
  senderType: UserRef;
74
74
  media: {
75
- mediaUrl: string;
76
75
  mediaType: MediaType;
76
+ mediaUrl: string;
77
77
  mimeType: string;
78
78
  name?: string | undefined;
79
79
  thumbnailUrl?: string | undefined;
@@ -89,17 +89,17 @@ export declare const ChatroomMessageSendOutputSchema: z.ZodObject<{
89
89
  content?: string | undefined;
90
90
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
91
91
  }, {
92
- _id: import("mongoose").Types.ObjectId;
93
92
  createdAt: Date;
93
+ _id: import("mongoose").Types.ObjectId;
94
94
  sender: {
95
- type: UserRef;
96
95
  name: string;
97
96
  id: import("mongoose").Types.ObjectId;
97
+ type: UserRef;
98
98
  };
99
99
  senderType: UserRef;
100
100
  media: {
101
- mediaUrl: string;
102
101
  mediaType: MediaType;
102
+ mediaUrl: string;
103
103
  mimeType: string;
104
104
  name?: string | undefined;
105
105
  thumbnailUrl?: string | undefined;
@@ -124,14 +124,14 @@ export declare const ChatroomMessageSendPushOutputSchema: z.ZodObject<{
124
124
  }, "strip", z.ZodTypeAny, {
125
125
  type: ChatroomType;
126
126
  orderId?: import("mongoose").Types.ObjectId | undefined;
127
- ticketId?: import("mongoose").Types.ObjectId | undefined;
128
127
  lastMessage?: string | undefined;
128
+ ticketId?: import("mongoose").Types.ObjectId | undefined;
129
129
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
130
130
  }, {
131
131
  type: ChatroomType;
132
132
  orderId?: import("mongoose").Types.ObjectId | undefined;
133
- ticketId?: import("mongoose").Types.ObjectId | undefined;
134
133
  lastMessage?: string | undefined;
134
+ ticketId?: import("mongoose").Types.ObjectId | undefined;
135
135
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
136
136
  }>;
137
137
  export type ChatlistMessageSendPushOutputDTO = DTO<typeof ChatroomMessageSendPushOutputSchema>;
@@ -156,13 +156,13 @@ export declare class ChatroomMessageSendSocketEvent extends BaseSocketEvent<type
156
156
  name: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
157
157
  type: z.ZodNativeEnum<typeof UserRef>;
158
158
  }, "strip", z.ZodTypeAny, {
159
- type: UserRef;
160
159
  name: string;
161
160
  id: import("mongoose").Types.ObjectId;
162
- }, {
163
161
  type: UserRef;
162
+ }, {
164
163
  name: string;
165
164
  id: import("mongoose").Types.ObjectId;
165
+ type: UserRef;
166
166
  }>;
167
167
  content: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
168
168
  media: z.ZodArray<z.ZodObject<{
@@ -172,14 +172,14 @@ export declare class ChatroomMessageSendSocketEvent extends BaseSocketEvent<type
172
172
  thumbnailUrl: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
173
173
  name: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
174
174
  }, "strip", z.ZodTypeAny, {
175
- mediaUrl: string;
176
175
  mediaType: MediaType;
176
+ mediaUrl: string;
177
177
  mimeType: string;
178
178
  name?: string | undefined;
179
179
  thumbnailUrl?: string | undefined;
180
180
  }, {
181
- mediaUrl: string;
182
181
  mediaType: MediaType;
182
+ mediaUrl: string;
183
183
  mimeType: string;
184
184
  name?: string | undefined;
185
185
  thumbnailUrl?: string | undefined;
@@ -199,17 +199,17 @@ export declare class ChatroomMessageSendSocketEvent extends BaseSocketEvent<type
199
199
  orderId: z.ZodOptional<z.ZodEffects<z.ZodType<import("mongoose").Types.ObjectId, z.ZodTypeDef, import("mongoose").Types.ObjectId>, import("mongoose").Types.ObjectId, import("mongoose").Types.ObjectId>>;
200
200
  createdAt: z.ZodEffects<z.ZodEffects<z.ZodDate, Date, Date>, Date, Date>;
201
201
  }, "strip", z.ZodTypeAny, {
202
- _id: import("mongoose").Types.ObjectId;
203
202
  createdAt: Date;
203
+ _id: import("mongoose").Types.ObjectId;
204
204
  sender: {
205
- type: UserRef;
206
205
  name: string;
207
206
  id: import("mongoose").Types.ObjectId;
207
+ type: UserRef;
208
208
  };
209
209
  senderType: UserRef;
210
210
  media: {
211
- mediaUrl: string;
212
211
  mediaType: MediaType;
212
+ mediaUrl: string;
213
213
  mimeType: string;
214
214
  name?: string | undefined;
215
215
  thumbnailUrl?: string | undefined;
@@ -225,17 +225,17 @@ export declare class ChatroomMessageSendSocketEvent extends BaseSocketEvent<type
225
225
  content?: string | undefined;
226
226
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
227
227
  }, {
228
- _id: import("mongoose").Types.ObjectId;
229
228
  createdAt: Date;
229
+ _id: import("mongoose").Types.ObjectId;
230
230
  sender: {
231
- type: UserRef;
232
231
  name: string;
233
232
  id: import("mongoose").Types.ObjectId;
233
+ type: UserRef;
234
234
  };
235
235
  senderType: UserRef;
236
236
  media: {
237
- mediaUrl: string;
238
237
  mediaType: MediaType;
238
+ mediaUrl: string;
239
239
  mimeType: string;
240
240
  name?: string | undefined;
241
241
  thumbnailUrl?: string | undefined;
@@ -260,14 +260,14 @@ export declare class ChatroomMessageSendSocketEvent extends BaseSocketEvent<type
260
260
  }, "strip", z.ZodTypeAny, {
261
261
  type: ChatroomType;
262
262
  orderId?: import("mongoose").Types.ObjectId | undefined;
263
- ticketId?: import("mongoose").Types.ObjectId | undefined;
264
263
  lastMessage?: string | undefined;
264
+ ticketId?: import("mongoose").Types.ObjectId | undefined;
265
265
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
266
266
  }, {
267
267
  type: ChatroomType;
268
268
  orderId?: import("mongoose").Types.ObjectId | undefined;
269
- ticketId?: import("mongoose").Types.ObjectId | undefined;
270
269
  lastMessage?: string | undefined;
270
+ ticketId?: import("mongoose").Types.ObjectId | undefined;
271
271
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
272
272
  }>;
273
273
  };
@@ -278,8 +278,8 @@ export declare class ChatroomMessageSendSocketEvent extends BaseSocketEvent<type
278
278
  getPushNotificationPayload(): {
279
279
  type: ChatroomType;
280
280
  orderId?: import("mongoose").Types.ObjectId | undefined;
281
- ticketId?: import("mongoose").Types.ObjectId | undefined;
282
281
  lastMessage?: string | undefined;
282
+ ticketId?: import("mongoose").Types.ObjectId | undefined;
283
283
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
284
284
  } | undefined;
285
285
  protected getIdentifier(): string;
@@ -16,11 +16,11 @@ export declare const OrderActionsOutputSchema: z.ZodObject<{
16
16
  _id: z.ZodUnion<[z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, import("mongoose").Types.ObjectId, string>, z.ZodType<import("mongoose").Types.ObjectId, z.ZodTypeDef, import("mongoose").Types.ObjectId>]>;
17
17
  name: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
18
18
  }, "strip", z.ZodTypeAny, {
19
- _id: import("mongoose").Types.ObjectId;
20
19
  name: string;
20
+ _id: import("mongoose").Types.ObjectId;
21
21
  }, {
22
- _id: string | import("mongoose").Types.ObjectId;
23
22
  name: string;
23
+ _id: string | import("mongoose").Types.ObjectId;
24
24
  }>;
25
25
  orderStatus: z.ZodNativeEnum<typeof RegularOrderStatus>;
26
26
  orderAction: z.ZodNativeEnum<typeof OrderAction>;
@@ -39,20 +39,20 @@ export declare const OrderActionsOutputSchema: z.ZodObject<{
39
39
  riderTips: z.ZodNumber;
40
40
  secondaryRiderTips: z.ZodNumber;
41
41
  }, "strip", z.ZodTypeAny, {
42
- total: number;
43
42
  deliveryFee: number;
44
43
  secondaryDeliveryFee: number;
45
44
  riderTips: number;
46
45
  secondaryRiderTips: number;
46
+ total: number;
47
47
  secondaryTotal: number;
48
48
  paidAmount: number;
49
49
  secondaryPaidAmount: number;
50
50
  }, {
51
- total: number;
52
51
  deliveryFee: number;
53
52
  secondaryDeliveryFee: number;
54
53
  riderTips: number;
55
54
  secondaryRiderTips: number;
55
+ total: number;
56
56
  secondaryTotal: number;
57
57
  paidAmount: number;
58
58
  secondaryPaidAmount: number;
@@ -60,11 +60,11 @@ export declare const OrderActionsOutputSchema: z.ZodObject<{
60
60
  }, "strip", z.ZodTypeAny, {
61
61
  paymentMethod: PaymentMethod;
62
62
  pricing: {
63
- total: number;
64
63
  deliveryFee: number;
65
64
  secondaryDeliveryFee: number;
66
65
  riderTips: number;
67
66
  secondaryRiderTips: number;
67
+ total: number;
68
68
  secondaryTotal: number;
69
69
  paidAmount: number;
70
70
  secondaryPaidAmount: number;
@@ -73,11 +73,11 @@ export declare const OrderActionsOutputSchema: z.ZodObject<{
73
73
  }, {
74
74
  paymentMethod: PaymentMethod;
75
75
  pricing: {
76
- total: number;
77
76
  deliveryFee: number;
78
77
  secondaryDeliveryFee: number;
79
78
  riderTips: number;
80
79
  secondaryRiderTips: number;
80
+ total: number;
81
81
  secondaryTotal: number;
82
82
  paidAmount: number;
83
83
  secondaryPaidAmount: number;
@@ -88,59 +88,59 @@ export declare const OrderActionsOutputSchema: z.ZodObject<{
88
88
  triggerAt: z.ZodEffects<z.ZodEffects<z.ZodDate, Date, Date>, Date, Date>;
89
89
  orderActionType: z.ZodNativeEnum<typeof OrderAction>;
90
90
  }, "strip", z.ZodTypeAny, {
91
- _id: import("mongoose").Types.ObjectId;
92
91
  createdAt: Date;
92
+ _id: import("mongoose").Types.ObjectId;
93
+ shopId: import("mongoose").Types.ObjectId;
93
94
  user: {
94
- _id: import("mongoose").Types.ObjectId;
95
95
  name: string;
96
+ _id: import("mongoose").Types.ObjectId;
96
97
  };
97
98
  orderId: string;
98
- shopId: import("mongoose").Types.ObjectId;
99
- paymentMethod: PaymentMethod;
100
99
  triggerAt: Date;
101
100
  adjustedFinance: {
102
101
  paymentMethod: PaymentMethod;
103
102
  pricing: {
104
- total: number;
105
103
  deliveryFee: number;
106
104
  secondaryDeliveryFee: number;
107
105
  riderTips: number;
108
106
  secondaryRiderTips: number;
107
+ total: number;
109
108
  secondaryTotal: number;
110
109
  paidAmount: number;
111
110
  secondaryPaidAmount: number;
112
111
  };
113
112
  shopProfit: number;
114
113
  };
114
+ paymentMethod: PaymentMethod;
115
115
  orderActionType: OrderAction;
116
116
  orderStatus: RegularOrderStatus;
117
117
  orderAction: OrderAction;
118
118
  preparationTimeMinutes: number;
119
119
  }, {
120
- _id: string | import("mongoose").Types.ObjectId;
121
120
  createdAt: Date;
121
+ _id: string | import("mongoose").Types.ObjectId;
122
+ shopId: string | import("mongoose").Types.ObjectId;
122
123
  user: {
123
- _id: string | import("mongoose").Types.ObjectId;
124
124
  name: string;
125
+ _id: string | import("mongoose").Types.ObjectId;
125
126
  };
126
127
  orderId: string;
127
- shopId: string | import("mongoose").Types.ObjectId;
128
- paymentMethod: PaymentMethod;
129
128
  triggerAt: Date;
130
129
  adjustedFinance: {
131
130
  paymentMethod: PaymentMethod;
132
131
  pricing: {
133
- total: number;
134
132
  deliveryFee: number;
135
133
  secondaryDeliveryFee: number;
136
134
  riderTips: number;
137
135
  secondaryRiderTips: number;
136
+ total: number;
138
137
  secondaryTotal: number;
139
138
  paidAmount: number;
140
139
  secondaryPaidAmount: number;
141
140
  };
142
141
  shopProfit: number;
143
142
  };
143
+ paymentMethod: PaymentMethod;
144
144
  orderActionType: OrderAction;
145
145
  orderStatus: RegularOrderStatus;
146
146
  orderAction: OrderAction;
@@ -160,11 +160,11 @@ export declare class OrderActionsSocketEvent extends BaseSocketEvent<typeof Orde
160
160
  _id: z.ZodUnion<[z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, import("mongoose").Types.ObjectId, string>, z.ZodType<import("mongoose").Types.ObjectId, z.ZodTypeDef, import("mongoose").Types.ObjectId>]>;
161
161
  name: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
162
162
  }, "strip", z.ZodTypeAny, {
163
- _id: import("mongoose").Types.ObjectId;
164
163
  name: string;
164
+ _id: import("mongoose").Types.ObjectId;
165
165
  }, {
166
- _id: string | import("mongoose").Types.ObjectId;
167
166
  name: string;
167
+ _id: string | import("mongoose").Types.ObjectId;
168
168
  }>;
169
169
  orderStatus: z.ZodNativeEnum<typeof RegularOrderStatus>;
170
170
  orderAction: z.ZodNativeEnum<typeof OrderAction>;
@@ -183,20 +183,20 @@ export declare class OrderActionsSocketEvent extends BaseSocketEvent<typeof Orde
183
183
  riderTips: z.ZodNumber;
184
184
  secondaryRiderTips: z.ZodNumber;
185
185
  }, "strip", z.ZodTypeAny, {
186
- total: number;
187
186
  deliveryFee: number;
188
187
  secondaryDeliveryFee: number;
189
188
  riderTips: number;
190
189
  secondaryRiderTips: number;
190
+ total: number;
191
191
  secondaryTotal: number;
192
192
  paidAmount: number;
193
193
  secondaryPaidAmount: number;
194
194
  }, {
195
- total: number;
196
195
  deliveryFee: number;
197
196
  secondaryDeliveryFee: number;
198
197
  riderTips: number;
199
198
  secondaryRiderTips: number;
199
+ total: number;
200
200
  secondaryTotal: number;
201
201
  paidAmount: number;
202
202
  secondaryPaidAmount: number;
@@ -204,11 +204,11 @@ export declare class OrderActionsSocketEvent extends BaseSocketEvent<typeof Orde
204
204
  }, "strip", z.ZodTypeAny, {
205
205
  paymentMethod: PaymentMethod;
206
206
  pricing: {
207
- total: number;
208
207
  deliveryFee: number;
209
208
  secondaryDeliveryFee: number;
210
209
  riderTips: number;
211
210
  secondaryRiderTips: number;
211
+ total: number;
212
212
  secondaryTotal: number;
213
213
  paidAmount: number;
214
214
  secondaryPaidAmount: number;
@@ -217,11 +217,11 @@ export declare class OrderActionsSocketEvent extends BaseSocketEvent<typeof Orde
217
217
  }, {
218
218
  paymentMethod: PaymentMethod;
219
219
  pricing: {
220
- total: number;
221
220
  deliveryFee: number;
222
221
  secondaryDeliveryFee: number;
223
222
  riderTips: number;
224
223
  secondaryRiderTips: number;
224
+ total: number;
225
225
  secondaryTotal: number;
226
226
  paidAmount: number;
227
227
  secondaryPaidAmount: number;
@@ -232,59 +232,59 @@ export declare class OrderActionsSocketEvent extends BaseSocketEvent<typeof Orde
232
232
  triggerAt: z.ZodEffects<z.ZodEffects<z.ZodDate, Date, Date>, Date, Date>;
233
233
  orderActionType: z.ZodNativeEnum<typeof OrderAction>;
234
234
  }, "strip", z.ZodTypeAny, {
235
- _id: import("mongoose").Types.ObjectId;
236
235
  createdAt: Date;
236
+ _id: import("mongoose").Types.ObjectId;
237
+ shopId: import("mongoose").Types.ObjectId;
237
238
  user: {
238
- _id: import("mongoose").Types.ObjectId;
239
239
  name: string;
240
+ _id: import("mongoose").Types.ObjectId;
240
241
  };
241
242
  orderId: string;
242
- shopId: import("mongoose").Types.ObjectId;
243
- paymentMethod: PaymentMethod;
244
243
  triggerAt: Date;
245
244
  adjustedFinance: {
246
245
  paymentMethod: PaymentMethod;
247
246
  pricing: {
248
- total: number;
249
247
  deliveryFee: number;
250
248
  secondaryDeliveryFee: number;
251
249
  riderTips: number;
252
250
  secondaryRiderTips: number;
251
+ total: number;
253
252
  secondaryTotal: number;
254
253
  paidAmount: number;
255
254
  secondaryPaidAmount: number;
256
255
  };
257
256
  shopProfit: number;
258
257
  };
258
+ paymentMethod: PaymentMethod;
259
259
  orderActionType: OrderAction;
260
260
  orderStatus: RegularOrderStatus;
261
261
  orderAction: OrderAction;
262
262
  preparationTimeMinutes: number;
263
263
  }, {
264
- _id: string | import("mongoose").Types.ObjectId;
265
264
  createdAt: Date;
265
+ _id: string | import("mongoose").Types.ObjectId;
266
+ shopId: string | import("mongoose").Types.ObjectId;
266
267
  user: {
267
- _id: string | import("mongoose").Types.ObjectId;
268
268
  name: string;
269
+ _id: string | import("mongoose").Types.ObjectId;
269
270
  };
270
271
  orderId: string;
271
- shopId: string | import("mongoose").Types.ObjectId;
272
- paymentMethod: PaymentMethod;
273
272
  triggerAt: Date;
274
273
  adjustedFinance: {
275
274
  paymentMethod: PaymentMethod;
276
275
  pricing: {
277
- total: number;
278
276
  deliveryFee: number;
279
277
  secondaryDeliveryFee: number;
280
278
  riderTips: number;
281
279
  secondaryRiderTips: number;
280
+ total: number;
282
281
  secondaryTotal: number;
283
282
  paidAmount: number;
284
283
  secondaryPaidAmount: number;
285
284
  };
286
285
  shopProfit: number;
287
286
  };
287
+ paymentMethod: PaymentMethod;
288
288
  orderActionType: OrderAction;
289
289
  orderStatus: RegularOrderStatus;
290
290
  orderAction: OrderAction;
@@ -19,18 +19,18 @@ export declare const RiderLocationUpdateSocketOutputSchema: z.ZodObject<{
19
19
  bearing: z.ZodOptional<z.ZodNumber>;
20
20
  updatedAt: z.ZodEffects<z.ZodEffects<z.ZodUnion<[z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, Date, string>, z.ZodDate]>, Date, string | Date>, Date, string | Date>;
21
21
  }, "strip", z.ZodTypeAny, {
22
- _id: import("mongoose").Types.ObjectId;
23
22
  updatedAt: Date;
23
+ _id: import("mongoose").Types.ObjectId;
24
+ riderId: import("mongoose").Types.ObjectId;
24
25
  latitude: number;
25
26
  longitude: number;
26
- riderId: import("mongoose").Types.ObjectId;
27
27
  bearing?: number | undefined;
28
28
  }, {
29
- _id: string | import("mongoose").Types.ObjectId;
30
29
  updatedAt: string | Date;
30
+ _id: string | import("mongoose").Types.ObjectId;
31
+ riderId: string | import("mongoose").Types.ObjectId;
31
32
  latitude: number;
32
33
  longitude: number;
33
- riderId: string | import("mongoose").Types.ObjectId;
34
34
  bearing?: number | undefined;
35
35
  }>;
36
36
  export type RiderLocationUpdateSocketInputDTO = DTO<typeof RiderLocationUpdateSocketInputSchema>;
@@ -55,18 +55,18 @@ export declare class RiderLocationUpdateSocketEvent extends BaseSocketEvent<type
55
55
  bearing: z.ZodOptional<z.ZodNumber>;
56
56
  updatedAt: z.ZodEffects<z.ZodEffects<z.ZodUnion<[z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, Date, string>, z.ZodDate]>, Date, string | Date>, Date, string | Date>;
57
57
  }, "strip", z.ZodTypeAny, {
58
- _id: import("mongoose").Types.ObjectId;
59
58
  updatedAt: Date;
59
+ _id: import("mongoose").Types.ObjectId;
60
+ riderId: import("mongoose").Types.ObjectId;
60
61
  latitude: number;
61
62
  longitude: number;
62
- riderId: import("mongoose").Types.ObjectId;
63
63
  bearing?: number | undefined;
64
64
  }, {
65
- _id: string | import("mongoose").Types.ObjectId;
66
65
  updatedAt: string | Date;
66
+ _id: string | import("mongoose").Types.ObjectId;
67
+ riderId: string | import("mongoose").Types.ObjectId;
67
68
  latitude: number;
68
69
  longitude: number;
69
- riderId: string | import("mongoose").Types.ObjectId;
70
70
  bearing?: number | undefined;
71
71
  }>;
72
72
  };
@@ -13,18 +13,18 @@ export declare const TicketActionsSocketOutputSchema: z.ZodObject<{
13
13
  silent: z.ZodOptional<z.ZodBoolean>;
14
14
  }, "strip", z.ZodTypeAny, {
15
15
  status: TicketStatus;
16
- type: TicketType;
17
16
  _id: import("mongoose").Types.ObjectId;
18
- silent?: boolean | undefined;
17
+ type: TicketType;
19
18
  title?: string | undefined;
20
19
  content?: string | undefined;
20
+ silent?: boolean | undefined;
21
21
  }, {
22
22
  status: TicketStatus;
23
- type: TicketType;
24
23
  _id: import("mongoose").Types.ObjectId;
25
- silent?: boolean | undefined;
24
+ type: TicketType;
26
25
  title?: string | undefined;
27
26
  content?: string | undefined;
27
+ silent?: boolean | undefined;
28
28
  }>;
29
29
  export declare const TicketActionsPushOutputSchema: z.ZodObject<{
30
30
  ticketId: z.ZodEffects<z.ZodType<import("mongoose").Types.ObjectId, z.ZodTypeDef, import("mongoose").Types.ObjectId>, import("mongoose").Types.ObjectId, import("mongoose").Types.ObjectId>;
@@ -60,18 +60,18 @@ export declare class TicketActionsSocketEvent extends BaseSocketEvent<typeof Tic
60
60
  silent: z.ZodOptional<z.ZodBoolean>;
61
61
  }, "strip", z.ZodTypeAny, {
62
62
  status: TicketStatus;
63
- type: TicketType;
64
63
  _id: import("mongoose").Types.ObjectId;
65
- silent?: boolean | undefined;
64
+ type: TicketType;
66
65
  title?: string | undefined;
67
66
  content?: string | undefined;
67
+ silent?: boolean | undefined;
68
68
  }, {
69
69
  status: TicketStatus;
70
- type: TicketType;
71
70
  _id: import("mongoose").Types.ObjectId;
72
- silent?: boolean | undefined;
71
+ type: TicketType;
73
72
  title?: string | undefined;
74
73
  content?: string | undefined;
74
+ silent?: boolean | undefined;
75
75
  }>;
76
76
  pushNotificationOutput: z.ZodObject<{
77
77
  ticketId: z.ZodEffects<z.ZodType<import("mongoose").Types.ObjectId, z.ZodTypeDef, import("mongoose").Types.ObjectId>, import("mongoose").Types.ObjectId, import("mongoose").Types.ObjectId>;
@@ -13,14 +13,14 @@ export declare const TicketAssignSocketOutputSchema: z.ZodObject<{
13
13
  name: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
14
14
  profilePhoto: z.ZodNullable<z.ZodString> | z.ZodNullable<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
15
15
  }, "strip", z.ZodTypeAny, {
16
- type: UserRef;
17
- _id: import("mongoose").Types.ObjectId;
18
16
  name: string;
17
+ _id: import("mongoose").Types.ObjectId;
18
+ type: UserRef;
19
19
  profilePhoto: string | null;
20
20
  }, {
21
- type: UserRef;
22
- _id: string | import("mongoose").Types.ObjectId;
23
21
  name: string;
22
+ _id: string | import("mongoose").Types.ObjectId;
23
+ type: UserRef;
24
24
  profilePhoto: string | null;
25
25
  }>;
26
26
  createdAt: z.ZodEffects<z.ZodEffects<z.ZodUnion<[z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, Date, string>, z.ZodDate]>, Date, string | Date>, Date, string | Date>;
@@ -40,40 +40,40 @@ export declare const TicketAssignSocketOutputSchema: z.ZodObject<{
40
40
  unreadCount: z.ZodNumber;
41
41
  }, "strip", z.ZodTypeAny, {
42
42
  status: TicketStatus;
43
- type: TicketType;
44
- _id: import("mongoose").Types.ObjectId;
45
43
  createdAt: Date;
46
44
  updatedAt: Date;
45
+ _id: import("mongoose").Types.ObjectId;
46
+ type: TicketType;
47
47
  lastMessage: {
48
48
  createdAt: Date;
49
49
  content: string;
50
50
  };
51
- unreadCount: number;
52
51
  client: {
53
- type: UserRef;
54
- _id: import("mongoose").Types.ObjectId;
55
52
  name: string;
53
+ _id: import("mongoose").Types.ObjectId;
54
+ type: UserRef;
56
55
  profilePhoto: string | null;
57
56
  };
57
+ unreadCount: number;
58
58
  chatroomId: import("mongoose").Types.ObjectId;
59
59
  orderId?: import("mongoose").Types.ObjectId | undefined;
60
60
  }, {
61
61
  status: TicketStatus;
62
- type: TicketType;
63
- _id: string | import("mongoose").Types.ObjectId;
64
62
  createdAt: string | Date;
65
63
  updatedAt: string | Date;
64
+ _id: string | import("mongoose").Types.ObjectId;
65
+ type: TicketType;
66
66
  lastMessage: {
67
67
  createdAt: string | Date;
68
68
  content: string;
69
69
  };
70
- unreadCount: number;
71
70
  client: {
72
- type: UserRef;
73
- _id: string | import("mongoose").Types.ObjectId;
74
71
  name: string;
72
+ _id: string | import("mongoose").Types.ObjectId;
73
+ type: UserRef;
75
74
  profilePhoto: string | null;
76
75
  };
76
+ unreadCount: number;
77
77
  chatroomId: string | import("mongoose").Types.ObjectId;
78
78
  orderId?: string | import("mongoose").Types.ObjectId | undefined;
79
79
  }>;
@@ -91,14 +91,14 @@ export declare class TicketAssignEvent extends BaseSocketEvent<typeof TicketAssi
91
91
  name: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
92
92
  profilePhoto: z.ZodNullable<z.ZodString> | z.ZodNullable<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
93
93
  }, "strip", z.ZodTypeAny, {
94
- type: UserRef;
95
- _id: import("mongoose").Types.ObjectId;
96
94
  name: string;
95
+ _id: import("mongoose").Types.ObjectId;
96
+ type: UserRef;
97
97
  profilePhoto: string | null;
98
98
  }, {
99
- type: UserRef;
100
- _id: string | import("mongoose").Types.ObjectId;
101
99
  name: string;
100
+ _id: string | import("mongoose").Types.ObjectId;
101
+ type: UserRef;
102
102
  profilePhoto: string | null;
103
103
  }>;
104
104
  createdAt: z.ZodEffects<z.ZodEffects<z.ZodUnion<[z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, Date, string>, z.ZodDate]>, Date, string | Date>, Date, string | Date>;
@@ -118,40 +118,40 @@ export declare class TicketAssignEvent extends BaseSocketEvent<typeof TicketAssi
118
118
  unreadCount: z.ZodNumber;
119
119
  }, "strip", z.ZodTypeAny, {
120
120
  status: TicketStatus;
121
- type: TicketType;
122
- _id: import("mongoose").Types.ObjectId;
123
121
  createdAt: Date;
124
122
  updatedAt: Date;
123
+ _id: import("mongoose").Types.ObjectId;
124
+ type: TicketType;
125
125
  lastMessage: {
126
126
  createdAt: Date;
127
127
  content: string;
128
128
  };
129
- unreadCount: number;
130
129
  client: {
131
- type: UserRef;
132
- _id: import("mongoose").Types.ObjectId;
133
130
  name: string;
131
+ _id: import("mongoose").Types.ObjectId;
132
+ type: UserRef;
134
133
  profilePhoto: string | null;
135
134
  };
135
+ unreadCount: number;
136
136
  chatroomId: import("mongoose").Types.ObjectId;
137
137
  orderId?: import("mongoose").Types.ObjectId | undefined;
138
138
  }, {
139
139
  status: TicketStatus;
140
- type: TicketType;
141
- _id: string | import("mongoose").Types.ObjectId;
142
140
  createdAt: string | Date;
143
141
  updatedAt: string | Date;
142
+ _id: string | import("mongoose").Types.ObjectId;
143
+ type: TicketType;
144
144
  lastMessage: {
145
145
  createdAt: string | Date;
146
146
  content: string;
147
147
  };
148
- unreadCount: number;
149
148
  client: {
150
- type: UserRef;
151
- _id: string | import("mongoose").Types.ObjectId;
152
149
  name: string;
150
+ _id: string | import("mongoose").Types.ObjectId;
151
+ type: UserRef;
153
152
  profilePhoto: string | null;
154
153
  };
154
+ unreadCount: number;
155
155
  chatroomId: string | import("mongoose").Types.ObjectId;
156
156
  orderId?: string | import("mongoose").Types.ObjectId | undefined;
157
157
  }>;
@@ -22,7 +22,7 @@ Perfect for sharing types between frontend and backend applications.
22
22
 
23
23
  ## Version
24
24
 
25
- Version: 1.4.323
25
+ Version: 1.4.324
26
26
 
27
27
  ## Dependencies
28
28
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/types",
3
- "version": "1.4.323",
3
+ "version": "1.4.324",
4
4
  "description": "Lyxa type definitions and validation schemas for both frontend and backend",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/core",
3
- "version": "1.4.323",
3
+ "version": "1.4.324",
4
4
  "description": "The Core system of the Lyxa services.",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",