@lyxa.ai/core 1.1.43 → 1.1.45

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.
@@ -4,10 +4,12 @@ import { PunchMarketing } from './providers/punch-marketing.model';
4
4
  import { Shop } from './shop.model';
5
5
  import { User } from './user.model';
6
6
  import { PunchMarketingStatus, ValueType } from '../../../utilities/enum';
7
+ import { Order } from './order.model';
7
8
  export declare class PunchMarketingHistory extends TimeStamps {
8
9
  user: Ref<User>;
9
10
  marketing: Ref<PunchMarketing>;
10
11
  shop: Ref<Shop>;
12
+ order?: Ref<Order>;
11
13
  targetOrder: number;
12
14
  minimumOrderValue: number;
13
15
  completedOrder: number;
@@ -16,10 +16,12 @@ const punch_marketing_model_1 = require("./providers/punch-marketing.model");
16
16
  const shop_model_1 = require("./shop.model");
17
17
  const user_model_1 = require("./user.model");
18
18
  const enum_1 = require("../../../utilities/enum");
19
+ const order_model_1 = require("./order.model");
19
20
  let PunchMarketingHistory = class PunchMarketingHistory extends defaultClasses_1.TimeStamps {
20
21
  user;
21
22
  marketing;
22
23
  shop;
24
+ order;
23
25
  targetOrder;
24
26
  minimumOrderValue;
25
27
  completedOrder;
@@ -45,6 +47,10 @@ __decorate([
45
47
  (0, typegoose_1.prop)({ required: true, ref: () => shop_model_1.Shop }),
46
48
  __metadata("design:type", Object)
47
49
  ], PunchMarketingHistory.prototype, "shop", void 0);
50
+ __decorate([
51
+ (0, typegoose_1.prop)({ ref: () => order_model_1.Order, default: null }),
52
+ __metadata("design:type", Object)
53
+ ], PunchMarketingHistory.prototype, "order", void 0);
48
54
  __decorate([
49
55
  (0, typegoose_1.prop)({ required: true, type: Number }),
50
56
  __metadata("design:type", Number)
@@ -1 +1 @@
1
- {"version":3,"file":"punch-marketing-history.model.js","sourceRoot":"/","sources":["libraries/mongo/models/punch-marketing-history.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA+D;AAC/D,4EAAqE;AACrE,6EAAmE;AACnE,6CAAoC;AACpC,6CAAoC;AAEpC,kDAA0E;AAGnE,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,2BAAU;IAE7C,IAAI,CAAa;IAGjB,SAAS,CAAuB;IAGhC,IAAI,CAAa;IAGjB,WAAW,CAAU;IAGrB,iBAAiB,CAAU;IAG3B,cAAc,CAAS;IAGvB,SAAS,CAAO;IAGhB,UAAU,CAAQ;IAGlB,WAAW,CAAQ;IAGnB,MAAM,CAAuB;IAG7B,eAAe,CAAa;IAG5B,WAAW,CAAU;IAGrB,oBAAoB,CAAU;IAG9B,gBAAgB,CAAO;CAC9B,CAAA;AA1CY,sDAAqB;AAE1B;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;mDAClB;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,sCAAc,EAAE,CAAC;;wDACb;AAGhC;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;mDAClB;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;0DACX;AAGrB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;gEACL;AAG3B;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;6DACL;AAGvB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;8BACxB,IAAI;wDAAC;AAGhB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;8BAChB,IAAI;yDAAC;AAGlB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;8BACf,IAAI;0DAAC;AAGnB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,2BAAoB,EAAE,OAAO,EAAE,2BAAoB,CAAC,MAAM,EAAE,CAAC;;qDACrD;AAG7B;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAS,EAAE,CAAC;;8DACrB;AAG5B;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;0DACX;AAGrB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;mEACF;AAG9B;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;8BACX,IAAI;+DAAC;gCAzClB,qBAAqB;IADjC,IAAA,wBAAY,EAAC,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,yBAAyB,EAAE,EAAE,CAAC;GAC9D,qBAAqB,CA0CjC","sourcesContent":["import { modelOptions, prop, Ref } from '@typegoose/typegoose';\nimport { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';\nimport { PunchMarketing } from './providers/punch-marketing.model';\nimport { Shop } from './shop.model';\nimport { User } from './user.model';\nimport { Coupon } from './coupon.model';\nimport { PunchMarketingStatus, ValueType } from '../../../utilities/enum';\n\n@modelOptions({ schemaOptions: { collection: 'punchMarketingHistories' } })\nexport class PunchMarketingHistory extends TimeStamps {\n\t@prop({ required: true, ref: () => User })\n\tpublic user!: Ref<User>;\n\n\t@prop({ required: true, ref: () => PunchMarketing })\n\tpublic marketing!: Ref<PunchMarketing>;\n\n\t@prop({ required: true, ref: () => Shop })\n\tpublic shop!: Ref<Shop>;\n\n\t@prop({ required: true, type: Number })\n\tpublic targetOrder!: number;\n\n\t@prop({ required: true, type: Number })\n\tpublic minimumOrderValue!: number;\n\n\t@prop({ type: Number, default: 1 })\n\tpublic completedOrder: number;\n\n\t@prop({ type: Date, default: new Date() })\n\tpublic startDate: Date;\n\n\t@prop({ type: Date, default: null })\n\tpublic expiryDate!: Date;\n\n\t@prop({ type: Date, default: null })\n\tpublic completedAt?: Date;\n\n\t@prop({ type: String, enum: PunchMarketingStatus, default: PunchMarketingStatus.ACTIVE })\n\tpublic status: PunchMarketingStatus;\n\n\t@prop({ required: true, type: String, enum: ValueType })\n\tpublic couponValueType!: ValueType;\n\n\t@prop({ required: true, type: Number })\n\tpublic couponValue!: number;\n\n\t@prop({ required: true, type: Number })\n\tpublic couponDurationInDays!: number;\n\n\t@prop({ type: Date, default: null })\n\tpublic couponExpiryDate: Date;\n}\n"]}
1
+ {"version":3,"file":"punch-marketing-history.model.js","sourceRoot":"/","sources":["libraries/mongo/models/punch-marketing-history.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA+D;AAC/D,4EAAqE;AACrE,6EAAmE;AACnE,6CAAoC;AACpC,6CAAoC;AAEpC,kDAA0E;AAC1E,+CAAsC;AAG/B,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,2BAAU;IAE7C,IAAI,CAAa;IAGjB,SAAS,CAAuB;IAGhC,IAAI,CAAa;IAGjB,KAAK,CAAc;IAGnB,WAAW,CAAU;IAGrB,iBAAiB,CAAU;IAG3B,cAAc,CAAS;IAGvB,SAAS,CAAO;IAGhB,UAAU,CAAQ;IAGlB,WAAW,CAAQ;IAGnB,MAAM,CAAuB;IAG7B,eAAe,CAAa;IAG5B,WAAW,CAAU;IAGrB,oBAAoB,CAAU;IAG9B,gBAAgB,CAAO;CAC9B,CAAA;AA7CY,sDAAqB;AAE1B;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;mDAClB;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,sCAAc,EAAE,CAAC;;wDACb;AAGhC;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;mDAClB;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,mBAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;oDAChB;AAGnB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;0DACX;AAGrB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;gEACL;AAG3B;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;6DACL;AAGvB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;8BACxB,IAAI;wDAAC;AAGhB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;8BAChB,IAAI;yDAAC;AAGlB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;8BACf,IAAI;0DAAC;AAGnB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,2BAAoB,EAAE,OAAO,EAAE,2BAAoB,CAAC,MAAM,EAAE,CAAC;;qDACrD;AAG7B;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAS,EAAE,CAAC;;8DACrB;AAG5B;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;0DACX;AAGrB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;mEACF;AAG9B;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;8BACX,IAAI;+DAAC;gCA5ClB,qBAAqB;IADjC,IAAA,wBAAY,EAAC,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,yBAAyB,EAAE,EAAE,CAAC;GAC9D,qBAAqB,CA6CjC","sourcesContent":["import { modelOptions, prop, Ref } from '@typegoose/typegoose';\nimport { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';\nimport { PunchMarketing } from './providers/punch-marketing.model';\nimport { Shop } from './shop.model';\nimport { User } from './user.model';\nimport { Coupon } from './coupon.model';\nimport { PunchMarketingStatus, ValueType } from '../../../utilities/enum';\nimport { Order } from './order.model';\n\n@modelOptions({ schemaOptions: { collection: 'punchMarketingHistories' } })\nexport class PunchMarketingHistory extends TimeStamps {\n\t@prop({ required: true, ref: () => User })\n\tpublic user!: Ref<User>;\n\n\t@prop({ required: true, ref: () => PunchMarketing })\n\tpublic marketing!: Ref<PunchMarketing>;\n\n\t@prop({ required: true, ref: () => Shop })\n\tpublic shop!: Ref<Shop>;\n\n\t@prop({ ref: () => Order, default: null })\n\tpublic order?: Ref<Order>;\n\n\t@prop({ required: true, type: Number })\n\tpublic targetOrder!: number;\n\n\t@prop({ required: true, type: Number })\n\tpublic minimumOrderValue!: number;\n\n\t@prop({ type: Number, default: 1 })\n\tpublic completedOrder: number;\n\n\t@prop({ type: Date, default: new Date() })\n\tpublic startDate: Date;\n\n\t@prop({ type: Date, default: null })\n\tpublic expiryDate!: Date;\n\n\t@prop({ type: Date, default: null })\n\tpublic completedAt?: Date;\n\n\t@prop({ type: String, enum: PunchMarketingStatus, default: PunchMarketingStatus.ACTIVE })\n\tpublic status: PunchMarketingStatus;\n\n\t@prop({ required: true, type: String, enum: ValueType })\n\tpublic couponValueType!: ValueType;\n\n\t@prop({ required: true, type: Number })\n\tpublic couponValue!: number;\n\n\t@prop({ required: true, type: Number })\n\tpublic couponDurationInDays!: number;\n\n\t@prop({ type: Date, default: null })\n\tpublic couponExpiryDate: Date;\n}\n"]}
@@ -136,7 +136,7 @@ class UploadService {
136
136
  }
137
137
  return {
138
138
  status: true,
139
- url: `https://storage.googleapis.com/${this.bucket.name}/${filename}`
139
+ url: `https://storage.googleapis.com/${this.bucket.name}/${filename}`,
140
140
  };
141
141
  }
142
142
  extractFilenameFromUrl(url) {
@@ -159,8 +159,33 @@ class UploadService {
159
159
  await file.delete();
160
160
  }
161
161
  async downloadImage(url) {
162
- const response = await axios_1.default.get(url, { responseType: 'arraybuffer' });
163
- return Buffer.from(response.data, 'binary');
162
+ try {
163
+ const response = await axios_1.default.get(url, { responseType: 'arraybuffer' });
164
+ return Buffer.from(response.data, 'binary');
165
+ }
166
+ catch (error) {
167
+ if (axios_1.default.isAxiosError(error)) {
168
+ const status = error.response?.status;
169
+ let reason = 'Image download failed';
170
+ if (status === 403) {
171
+ reason = 'Image URL is not valid or access forbidden (403)';
172
+ }
173
+ else if (status === 404) {
174
+ reason = 'Image not found (404)';
175
+ }
176
+ else if (status === 429) {
177
+ reason = 'Too many requests (429) — rate limited by server';
178
+ }
179
+ else if (status) {
180
+ reason = `Image download failed with status ${status}`;
181
+ }
182
+ else {
183
+ reason = `Network or unknown error: ${error.message}`;
184
+ }
185
+ throw new Error(reason);
186
+ }
187
+ throw new Error(`Unexpected error downloading image: ${error.message}`);
188
+ }
164
189
  }
165
190
  async uploadToGCS(buffer, filename, contentType) {
166
191
  const file = this.bucket.file(filename);
@@ -219,7 +244,9 @@ class UploadService {
219
244
  });
220
245
  }
221
246
  async uploadFile(buffer, originalFilename, options) {
222
- const newFilename = options?.withOriginalFilename ? originalFilename : this.generateFilename(originalFilename);
247
+ const newFilename = options?.withOriginalFilename
248
+ ? originalFilename
249
+ : this.generateFilename(originalFilename);
223
250
  const extension = path_1.default.extname(newFilename).toLowerCase();
224
251
  const contentType = mime_types_1.default.lookup(extension) || 'application/octet-stream';
225
252
  if (contentType.startsWith('image/')) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"/","sources":["libraries/upload/index.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios';\nimport sharp from 'sharp';\nimport moment from 'moment';\nimport path from 'path';\nimport { getLibraries } from '../../index';\nimport mime from 'mime-types';\n\nfunction makeSlug(input: string): string {\n\treturn input\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, '-')\n\t\t.replace(/(^-|-$)/g, '');\n}\n\nexport class UploadService {\n\tprivate bucket;\n\tprivate readonly websiteName;\n\n\tconstructor(bucketName?: string) {\n\t\tif (!bucketName) {\n\t\t\tbucketName = 'lyxa-global';\n\t\t}\n\n\t\tthis.bucket = getLibraries().getFirebaseService().superApp.storage().bucket(bucketName);\n\t\tthis.websiteName = 'lyxa-' + getLibraries().getConfigurationService().options.tenet;\n\t}\n\n\t/**\n\t * Generates a unique filename using the original filename.\n\t */\n\tprivate generateFilename(originalFilename: string, extension?: string): string {\n\t\tconst nameWithoutExt = path.parse(originalFilename).name;\n\t\tconst newExtension = extension || path.extname(originalFilename);\n\t\tconst timestamp = moment().format('DDMMYYHmmss');\n\t\tconst randomId = Math.floor(Math.random() * 100);\n\t\tconst baseName = `${makeSlug(nameWithoutExt)}-${this.websiteName}-${timestamp}-${randomId}`;\n\t\treturn baseName + newExtension;\n\t}\n\n\t/**\n\t * Uploads an image buffer after processing it with Sharp.\n\t * An optional destinationPath can be provided (e.g., 'images/product.jpg').\n\t */\n\tasync uploadImage(buffer: Buffer, originalFilename: string): Promise<{ filename: string; url: string }> {\n\t\tconst newFilename = this.generateFilename(originalFilename);\n\t\tconst extension = path.extname(newFilename).toLowerCase();\n\t\tlet processedImage: sharp.Sharp;\n\t\tlet contentType: string;\n\t\tif (extension === '.png') {\n\t\t\tprocessedImage = sharp(buffer).png({ quality: 80 });\n\t\t\tcontentType = 'image/png';\n\t\t} else if (extension === '.webp') {\n\t\t\tprocessedImage = sharp(buffer).webp({ quality: 80 });\n\t\t\tcontentType = 'image/webp';\n\t\t} else {\n\t\t\tprocessedImage = sharp(buffer).jpeg({ quality: 80 });\n\t\t\tcontentType = 'image/jpeg';\n\t\t}\n\n\t\tconst file = this.bucket.file(newFilename);\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst blobStream = file.createWriteStream({\n\t\t\t\tresumable: false,\n\t\t\t\tcontentType,\n\t\t\t});\n\n\t\t\tblobStream.on('error', (err: Error) => {\n\t\t\t\treject(err);\n\t\t\t});\n\n\t\t\tblobStream.on('finish', async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait file.makePublic();\n\t\t\t\t\tconst publicUrl = `https://storage.googleapis.com/${this.bucket.name}/${file.name}`;\n\t\t\t\t\tresolve({ filename: file.name, url: publicUrl });\n\t\t\t\t} catch (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tprocessedImage.pipe(blobStream);\n\t\t});\n\t}\n\n\t/**\n\t * Transcodes (resizes) an image buffer into multiple resolutions.\n\t * An optional destinationPrefix can be provided to force a specific path or filename base.\n\t *\n\t * For example, if destinationPrefix is 'images/product', then the original might be\n\t * uploaded as 'images/product.jpg' and the resized versions as 'images/product-480.jpg', etc.\n\t */\n\tasync transcodeImage(\n\t\tbuffer: Buffer,\n\t\toriginalFilename: string,\n\t\tresolutions: number[]\n\t): Promise<{\n\t\toriginalUrl: string;\n\t\tresizedResults: Array<{ resolution: number; url: string }>;\n\t}> {\n\t\tconst extension = path.extname(originalFilename);\n\t\tconst contentType = `image/${extension.replace('.', '') || 'jpeg'}`;\n\t\tconst timestamp = moment().format('DDMMYYHmmss');\n\t\tconst randomId = Math.floor(Math.random() * 100);\n\n\t\tconst baseFilename = `${makeSlug(path.parse(originalFilename).name)}-${this.websiteName}-${timestamp}-${randomId}`;\n\n\t\tconst originalFileName = `${baseFilename}${extension}`;\n\t\tconst originalUrl = await this.uploadBuffer(buffer, originalFileName, contentType);\n\n\t\tconst metadata = await sharp(buffer).metadata();\n\t\tconst isLandscape = metadata.width && metadata.height ? metadata.width > metadata.height : true;\n\n\t\tconst resizedResults = await Promise.all(\n\t\t\tresolutions.map(async resolution => {\n\t\t\t\tconst resizeOptions = isLandscape ? { width: resolution } : { height: resolution };\n\t\t\t\tconst formatKey = (extension.replace('.', '') || 'jpeg') as keyof sharp.FormatEnum;\n\t\t\t\tconst resizedBuffer = await sharp(buffer)\n\t\t\t\t\t.resize({\n\t\t\t\t\t\t...resizeOptions,\n\t\t\t\t\t\twithoutEnlargement: true,\n\t\t\t\t\t})\n\t\t\t\t\t.toFormat(formatKey, { quality: 80 })\n\t\t\t\t\t.toBuffer();\n\t\t\t\tconst resizedFilename = `${baseFilename}-${resolution}${extension}`;\n\t\t\t\tconst resizedUrl = await this.uploadBuffer(resizedBuffer, resizedFilename, contentType);\n\t\t\t\treturn { resolution, url: resizedUrl };\n\t\t\t})\n\t\t);\n\n\t\treturn { originalUrl, resizedResults };\n\t}\n\n\t/**\n\t * Helper function to upload a buffer to a specified filename.\n\t */\n\tprivate async uploadBuffer(buffer: Buffer, filename: string, contentType: string): Promise<string> {\n\t\tconst file = this.bucket.file(filename);\n\t\tawait file.save(buffer, {\n\t\t\tresumable: false,\n\t\t\tcontentType,\n\t\t});\n\t\tawait file.makePublic();\n\t\treturn `https://storage.googleapis.com/${this.bucket.name}/${file.name}`;\n\t}\n\n\tasync getListFiles(): Promise<Array<{ name: string; url: string }>> {\n\t\tconst [files] = await this.bucket.getFiles();\n\t\treturn files.map(file => ({\n\t\t\tname: file.name!,\n\t\t\turl: file.metadata.mediaLink!,\n\t\t}));\n\t}\n\n\tasync downloadFile(filename: string): Promise<Buffer> {\n\t\tconst file = this.bucket.file(filename);\n\t\tconst [buffer] = await file.download();\n\t\treturn buffer;\n\t}\n\n\tasync deleteFile(filename: string): Promise<void> {\n\t\tconst file = this.bucket.file(filename);\n\t\tconst [exists] = await file.exists();\n\t\tif (!exists) {\n\t\t\tthrow new Error('File does not exist.');\n\t\t}\n\t\tawait file.delete();\n\t}\n\n\tasync getPublicUrlFromFilename(filename: string): Promise<{status: boolean, url: string}> {\n\t\tconst file = this.bucket.file(filename);\n\t\tconst [exists] = await file.exists();\n\n\t\tif (!exists) {\n\t\t\treturn {status: false, url: ''};\n\t\t}\n\n\t\treturn {\n\t\t\tstatus: true,\n\t\t\turl: `https://storage.googleapis.com/${this.bucket.name}/${filename}`\n\t\t};\n\t}\n\n\tpublic extractFilenameFromUrl(url: string): string {\n\t\ttry {\n\t\t\tconst urlObj = new URL(url);\n\t\t\tconst pathParts = urlObj.pathname.split('/');\n\t\t\treturn decodeURIComponent(pathParts[pathParts.length - 1]);\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Invalid URL: ${url}`);\n\t\t}\n\t}\n\n\tasync deleteFileByUrl(url: string): Promise<void> {\n\t\tconst filename = this.extractFilenameFromUrl(url);\n\t\tconst file = this.bucket.file(filename);\n\t\tconst [exists] = await file.exists();\n\t\tif (!exists) {\n\t\t\tthrow new Error('File does not exist.');\n\t\t}\n\t\tawait file.delete();\n\t}\n\n\tasync downloadImage(url: string): Promise<Buffer> {\n\t\tconst response = await axios.get(url, { responseType: 'arraybuffer' });\n\t\treturn Buffer.from(response.data, 'binary');\n\t}\n\n\t/**\n\t * Uploads a buffer to Google Cloud Storage and makes it public\n\t */\n\tprivate async uploadToGCS(\n\t\tbuffer: Buffer,\n\t\tfilename: string,\n\t\tcontentType: string\n\t): Promise<{ filename: string; url: string }> {\n\t\tconst file = this.bucket.file(filename);\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// Create a write stream to upload the file\n\t\t\tconst blobStream = file.createWriteStream({\n\t\t\t\tresumable: false,\n\t\t\t\tcontentType,\n\t\t\t});\n\n\t\t\tblobStream.on('error', reject);\n\n\t\t\tblobStream.on('finish', async () => {\n\t\t\t\ttry {\n\t\t\t\t\t// Make the file publicly accessible\n\t\t\t\t\tawait file.makePublic();\n\t\t\t\t\tconst publicUrl = `https://storage.googleapis.com/${this.bucket.name}/${file.name}`;\n\t\t\t\t\tresolve({ filename: file.name, url: publicUrl });\n\t\t\t\t} catch (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Start uploading the buffer\n\t\t\tblobStream.end(buffer);\n\t\t});\n\t}\n\n\t/**\n\t * Uploads and converts an image to WebP format, resizes if needed, and uploads to GCS\n\t */\n\tasync uploadProcessedImageToWebp(\n\t\tbuffer: Buffer,\n\t\toriginalFilename: string,\n\t\toptions?: { quality?: number; width?: number; height?: number }\n\t): Promise<{ filename: string; url: string }> {\n\t\tconst newFilename = this.generateFilename(originalFilename, '.webp');\n\n\t\tlet width = options?.width;\n\t\tlet height = options?.height;\n\t\tconst quality = options?.quality ?? 80;\n\n\t\t// Get original image dimensions if width or height is missing\n\t\tif (!width || !height) {\n\t\t\tconst imageMetadata = await sharp(buffer).metadata();\n\t\t\twidth = width || imageMetadata.width;\n\t\t\theight = height || imageMetadata.height;\n\t\t}\n\n\t\t// Convert to WebP and resize\n\t\tconst processedImage: sharp.Sharp = sharp(buffer)\n\t\t\t.resize(width, height, { fit: 'inside' })\n\t\t\t.webp({ quality });\n\n\t\tconst file = this.bucket.file(newFilename);\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst blobStream = file.createWriteStream({\n\t\t\t\tresumable: false,\n\t\t\t\tcontentType: 'image/webp',\n\t\t\t});\n\n\t\t\tblobStream.on('error', (err: Error) => {\n\t\t\t\treject(err);\n\t\t\t});\n\n\t\t\tblobStream.on('finish', async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait file.makePublic();\n\t\t\t\t\tconst publicUrl = `https://storage.googleapis.com/${this.bucket.name}/${file.name}`;\n\t\t\t\t\tresolve({ filename: file.name, url: publicUrl });\n\t\t\t\t} catch (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tprocessedImage.pipe(blobStream);\n\t\t});\n\t}\n\n\t/**\n\t * Uploads any supported file type to GCS and returns its public URL\n\t */\n\tasync uploadFile(\n\t\tbuffer: Buffer,\n\t\toriginalFilename: string,\n\t\toptions?: { quality?: number; width?: number; height?: number; withExtension?: boolean, withOriginalFilename?: boolean }\n\t): Promise<{ filename: string; url: string }> {\n\t\tconst newFilename = options?.withOriginalFilename ? originalFilename : this.generateFilename(originalFilename);\n\t\tconst extension = path.extname(newFilename).toLowerCase();\n\n\t\t// Guess the MIME type using the mime-types library\n\t\tconst contentType = mime.lookup(extension) || 'application/octet-stream';\n\n\t\t// Special image handling (compression)\n\t\tif (contentType.startsWith('image/')) {\n\t\t\tif (options?.withExtension) {\n\t\t\t\treturn this.uploadImage(buffer, originalFilename);\n\t\t\t} else {\n\t\t\t\treturn this.uploadProcessedImageToWebp(buffer, originalFilename, options);\n\t\t\t}\n\t\t}\n\n\t\treturn this.uploadToGCS(buffer, newFilename, contentType);\n\t}\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"/","sources":["libraries/upload/index.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios';\nimport sharp from 'sharp';\nimport moment from 'moment';\nimport path from 'path';\nimport { getLibraries } from '../../index';\nimport mime from 'mime-types';\n\nfunction makeSlug(input: string): string {\n\treturn input\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, '-')\n\t\t.replace(/(^-|-$)/g, '');\n}\n\nexport class UploadService {\n\tprivate bucket;\n\tprivate readonly websiteName;\n\n\tconstructor(bucketName?: string) {\n\t\tif (!bucketName) {\n\t\t\tbucketName = 'lyxa-global';\n\t\t}\n\n\t\tthis.bucket = getLibraries().getFirebaseService().superApp.storage().bucket(bucketName);\n\t\tthis.websiteName = 'lyxa-' + getLibraries().getConfigurationService().options.tenet;\n\t}\n\n\t/**\n\t * Generates a unique filename using the original filename.\n\t */\n\tprivate generateFilename(originalFilename: string, extension?: string): string {\n\t\tconst nameWithoutExt = path.parse(originalFilename).name;\n\t\tconst newExtension = extension || path.extname(originalFilename);\n\t\tconst timestamp = moment().format('DDMMYYHmmss');\n\t\tconst randomId = Math.floor(Math.random() * 100);\n\t\tconst baseName = `${makeSlug(nameWithoutExt)}-${this.websiteName}-${timestamp}-${randomId}`;\n\t\treturn baseName + newExtension;\n\t}\n\n\t/**\n\t * Uploads an image buffer after processing it with Sharp.\n\t * An optional destinationPath can be provided (e.g., 'images/product.jpg').\n\t */\n\tasync uploadImage(buffer: Buffer, originalFilename: string): Promise<{ filename: string; url: string }> {\n\t\tconst newFilename = this.generateFilename(originalFilename);\n\t\tconst extension = path.extname(newFilename).toLowerCase();\n\t\tlet processedImage: sharp.Sharp;\n\t\tlet contentType: string;\n\t\tif (extension === '.png') {\n\t\t\tprocessedImage = sharp(buffer).png({ quality: 80 });\n\t\t\tcontentType = 'image/png';\n\t\t} else if (extension === '.webp') {\n\t\t\tprocessedImage = sharp(buffer).webp({ quality: 80 });\n\t\t\tcontentType = 'image/webp';\n\t\t} else {\n\t\t\tprocessedImage = sharp(buffer).jpeg({ quality: 80 });\n\t\t\tcontentType = 'image/jpeg';\n\t\t}\n\n\t\tconst file = this.bucket.file(newFilename);\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst blobStream = file.createWriteStream({\n\t\t\t\tresumable: false,\n\t\t\t\tcontentType,\n\t\t\t});\n\n\t\t\tblobStream.on('error', (err: Error) => {\n\t\t\t\treject(err);\n\t\t\t});\n\n\t\t\tblobStream.on('finish', async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait file.makePublic();\n\t\t\t\t\tconst publicUrl = `https://storage.googleapis.com/${this.bucket.name}/${file.name}`;\n\t\t\t\t\tresolve({ filename: file.name, url: publicUrl });\n\t\t\t\t} catch (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tprocessedImage.pipe(blobStream);\n\t\t});\n\t}\n\n\t/**\n\t * Transcodes (resizes) an image buffer into multiple resolutions.\n\t * An optional destinationPrefix can be provided to force a specific path or filename base.\n\t *\n\t * For example, if destinationPrefix is 'images/product', then the original might be\n\t * uploaded as 'images/product.jpg' and the resized versions as 'images/product-480.jpg', etc.\n\t */\n\tasync transcodeImage(\n\t\tbuffer: Buffer,\n\t\toriginalFilename: string,\n\t\tresolutions: number[]\n\t): Promise<{\n\t\toriginalUrl: string;\n\t\tresizedResults: Array<{ resolution: number; url: string }>;\n\t}> {\n\t\tconst extension = path.extname(originalFilename);\n\t\tconst contentType = `image/${extension.replace('.', '') || 'jpeg'}`;\n\t\tconst timestamp = moment().format('DDMMYYHmmss');\n\t\tconst randomId = Math.floor(Math.random() * 100);\n\n\t\tconst baseFilename = `${makeSlug(path.parse(originalFilename).name)}-${this.websiteName}-${timestamp}-${randomId}`;\n\n\t\tconst originalFileName = `${baseFilename}${extension}`;\n\t\tconst originalUrl = await this.uploadBuffer(buffer, originalFileName, contentType);\n\n\t\tconst metadata = await sharp(buffer).metadata();\n\t\tconst isLandscape = metadata.width && metadata.height ? metadata.width > metadata.height : true;\n\n\t\tconst resizedResults = await Promise.all(\n\t\t\tresolutions.map(async resolution => {\n\t\t\t\tconst resizeOptions = isLandscape ? { width: resolution } : { height: resolution };\n\t\t\t\tconst formatKey = (extension.replace('.', '') || 'jpeg') as keyof sharp.FormatEnum;\n\t\t\t\tconst resizedBuffer = await sharp(buffer)\n\t\t\t\t\t.resize({\n\t\t\t\t\t\t...resizeOptions,\n\t\t\t\t\t\twithoutEnlargement: true,\n\t\t\t\t\t})\n\t\t\t\t\t.toFormat(formatKey, { quality: 80 })\n\t\t\t\t\t.toBuffer();\n\t\t\t\tconst resizedFilename = `${baseFilename}-${resolution}${extension}`;\n\t\t\t\tconst resizedUrl = await this.uploadBuffer(resizedBuffer, resizedFilename, contentType);\n\t\t\t\treturn { resolution, url: resizedUrl };\n\t\t\t})\n\t\t);\n\n\t\treturn { originalUrl, resizedResults };\n\t}\n\n\t/**\n\t * Helper function to upload a buffer to a specified filename.\n\t */\n\tprivate async uploadBuffer(buffer: Buffer, filename: string, contentType: string): Promise<string> {\n\t\tconst file = this.bucket.file(filename);\n\t\tawait file.save(buffer, {\n\t\t\tresumable: false,\n\t\t\tcontentType,\n\t\t});\n\t\tawait file.makePublic();\n\t\treturn `https://storage.googleapis.com/${this.bucket.name}/${file.name}`;\n\t}\n\n\tasync getListFiles(): Promise<Array<{ name: string; url: string }>> {\n\t\tconst [files] = await this.bucket.getFiles();\n\t\treturn files.map(file => ({\n\t\t\tname: file.name!,\n\t\t\turl: file.metadata.mediaLink!,\n\t\t}));\n\t}\n\n\tasync downloadFile(filename: string): Promise<Buffer> {\n\t\tconst file = this.bucket.file(filename);\n\t\tconst [buffer] = await file.download();\n\t\treturn buffer;\n\t}\n\n\tasync deleteFile(filename: string): Promise<void> {\n\t\tconst file = this.bucket.file(filename);\n\t\tconst [exists] = await file.exists();\n\t\tif (!exists) {\n\t\t\tthrow new Error('File does not exist.');\n\t\t}\n\t\tawait file.delete();\n\t}\n\n\tasync getPublicUrlFromFilename(filename: string): Promise<{ status: boolean; url: string }> {\n\t\tconst file = this.bucket.file(filename);\n\t\tconst [exists] = await file.exists();\n\n\t\tif (!exists) {\n\t\t\treturn { status: false, url: '' };\n\t\t}\n\n\t\treturn {\n\t\t\tstatus: true,\n\t\t\turl: `https://storage.googleapis.com/${this.bucket.name}/${filename}`,\n\t\t};\n\t}\n\n\tpublic extractFilenameFromUrl(url: string): string {\n\t\ttry {\n\t\t\tconst urlObj = new URL(url);\n\t\t\tconst pathParts = urlObj.pathname.split('/');\n\t\t\treturn decodeURIComponent(pathParts[pathParts.length - 1]);\n\t\t} catch (err) {\n\t\t\tthrow new Error(`Invalid URL: ${url}`);\n\t\t}\n\t}\n\n\tasync deleteFileByUrl(url: string): Promise<void> {\n\t\tconst filename = this.extractFilenameFromUrl(url);\n\t\tconst file = this.bucket.file(filename);\n\t\tconst [exists] = await file.exists();\n\t\tif (!exists) {\n\t\t\tthrow new Error('File does not exist.');\n\t\t}\n\t\tawait file.delete();\n\t}\n\n\tasync downloadImage(url: string): Promise<Buffer> {\n\t\ttry {\n\t\t\tconst response = await axios.get(url, { responseType: 'arraybuffer' });\n\t\t\treturn Buffer.from(response.data, 'binary');\n\t\t} catch (error: any) {\n\t\t\tif (axios.isAxiosError(error)) {\n\t\t\t\tconst status = error.response?.status;\n\t\t\t\tlet reason = 'Image download failed';\n\n\t\t\t\tif (status === 403) {\n\t\t\t\t\treason = 'Image URL is not valid or access forbidden (403)';\n\t\t\t\t} else if (status === 404) {\n\t\t\t\t\treason = 'Image not found (404)';\n\t\t\t\t} else if (status === 429) {\n\t\t\t\t\treason = 'Too many requests (429) — rate limited by server';\n\t\t\t\t} else if (status) {\n\t\t\t\t\treason = `Image download failed with status ${status}`;\n\t\t\t\t} else {\n\t\t\t\t\treason = `Network or unknown error: ${error.message}`;\n\t\t\t\t}\n\n\t\t\t\tthrow new Error(reason);\n\t\t\t}\n\n\t\t\t// Non-Axios error (timeout, DNS, etc.)\n\t\t\tthrow new Error(`Unexpected error downloading image: ${error.message}`);\n\t\t}\n\t}\n\n\t/**\n\t * Uploads a buffer to Google Cloud Storage and makes it public\n\t */\n\tprivate async uploadToGCS(\n\t\tbuffer: Buffer,\n\t\tfilename: string,\n\t\tcontentType: string\n\t): Promise<{ filename: string; url: string }> {\n\t\tconst file = this.bucket.file(filename);\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// Create a write stream to upload the file\n\t\t\tconst blobStream = file.createWriteStream({\n\t\t\t\tresumable: false,\n\t\t\t\tcontentType,\n\t\t\t});\n\n\t\t\tblobStream.on('error', reject);\n\n\t\t\tblobStream.on('finish', async () => {\n\t\t\t\ttry {\n\t\t\t\t\t// Make the file publicly accessible\n\t\t\t\t\tawait file.makePublic();\n\t\t\t\t\tconst publicUrl = `https://storage.googleapis.com/${this.bucket.name}/${file.name}`;\n\t\t\t\t\tresolve({ filename: file.name, url: publicUrl });\n\t\t\t\t} catch (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Start uploading the buffer\n\t\t\tblobStream.end(buffer);\n\t\t});\n\t}\n\n\t/**\n\t * Uploads and converts an image to WebP format, resizes if needed, and uploads to GCS\n\t */\n\tasync uploadProcessedImageToWebp(\n\t\tbuffer: Buffer,\n\t\toriginalFilename: string,\n\t\toptions?: { quality?: number; width?: number; height?: number }\n\t): Promise<{ filename: string; url: string }> {\n\t\tconst newFilename = this.generateFilename(originalFilename, '.webp');\n\n\t\tlet width = options?.width;\n\t\tlet height = options?.height;\n\t\tconst quality = options?.quality ?? 80;\n\n\t\t// Get original image dimensions if width or height is missing\n\t\tif (!width || !height) {\n\t\t\tconst imageMetadata = await sharp(buffer).metadata();\n\t\t\twidth = width || imageMetadata.width;\n\t\t\theight = height || imageMetadata.height;\n\t\t}\n\n\t\t// Convert to WebP and resize\n\t\tconst processedImage: sharp.Sharp = sharp(buffer)\n\t\t\t.resize(width, height, { fit: 'inside' })\n\t\t\t.webp({ quality });\n\n\t\tconst file = this.bucket.file(newFilename);\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst blobStream = file.createWriteStream({\n\t\t\t\tresumable: false,\n\t\t\t\tcontentType: 'image/webp',\n\t\t\t});\n\n\t\t\tblobStream.on('error', (err: Error) => {\n\t\t\t\treject(err);\n\t\t\t});\n\n\t\t\tblobStream.on('finish', async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait file.makePublic();\n\t\t\t\t\tconst publicUrl = `https://storage.googleapis.com/${this.bucket.name}/${file.name}`;\n\t\t\t\t\tresolve({ filename: file.name, url: publicUrl });\n\t\t\t\t} catch (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tprocessedImage.pipe(blobStream);\n\t\t});\n\t}\n\n\t/**\n\t * Uploads any supported file type to GCS and returns its public URL\n\t */\n\tasync uploadFile(\n\t\tbuffer: Buffer,\n\t\toriginalFilename: string,\n\t\toptions?: {\n\t\t\tquality?: number;\n\t\t\twidth?: number;\n\t\t\theight?: number;\n\t\t\twithExtension?: boolean;\n\t\t\twithOriginalFilename?: boolean;\n\t\t}\n\t): Promise<{ filename: string; url: string }> {\n\t\tconst newFilename = options?.withOriginalFilename\n\t\t\t? originalFilename\n\t\t\t: this.generateFilename(originalFilename);\n\t\tconst extension = path.extname(newFilename).toLowerCase();\n\n\t\t// Guess the MIME type using the mime-types library\n\t\tconst contentType = mime.lookup(extension) || 'application/octet-stream';\n\n\t\t// Special image handling (compression)\n\t\tif (contentType.startsWith('image/')) {\n\t\t\tif (options?.withExtension) {\n\t\t\t\treturn this.uploadImage(buffer, originalFilename);\n\t\t\t} else {\n\t\t\t\treturn this.uploadProcessedImageToWebp(buffer, originalFilename, options);\n\t\t\t}\n\t\t}\n\n\t\treturn this.uploadToGCS(buffer, newFilename, contentType);\n\t}\n}\n"]}
@@ -22,7 +22,7 @@ Perfect for sharing types between frontend and backend applications.
22
22
 
23
23
  ## Version
24
24
 
25
- Version: 1.1.43
25
+ Version: 1.1.45
26
26
 
27
27
  ## Dependencies
28
28
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/types",
3
- "version": "1.1.43",
3
+ "version": "1.1.45",
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.1.43",
3
+ "version": "1.1.45",
4
4
  "description": "The Core system of the Lyxa services.",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",