@marteye/studiojs 1.1.23 → 1.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4558,7 +4558,12 @@ z.object({
4558
4558
  suffix: z.string().min(1, { message: "Suffix Type is required" }),
4559
4559
  });
4560
4560
  // Adding Sizes here will make more end points in the mainConfig object
4561
- const IMAGE_SIZES_VALUES$1 = ["small", "medium", "large"];
4561
+ const IMAGE_SIZES_VALUES$1 = [
4562
+ "thumbnail",
4563
+ "small",
4564
+ "medium",
4565
+ "large",
4566
+ ];
4562
4567
  const VIDEO_TASKS_VALUES$1 = ["compressed", "thumbnail"];
4563
4568
  z.enum(VIDEO_TASKS_VALUES$1);
4564
4569
  z.enum(IMAGE_SIZES_VALUES$1);
@@ -4568,12 +4573,29 @@ const UPLOAD_PATHS = {
4568
4573
  FINISH_UPLOAD: "finishMultipartUpload",
4569
4574
  CANCEL_UPLOAD: "cancelUpload",
4570
4575
  DELETE_UPLOAD: "deleteUpload",
4576
+ UPLOAD_SINGLE_FILE: "upload",
4571
4577
  };
4572
4578
  /**
4573
4579
  |--------------------------------------------------
4574
4580
  | Helper Functions
4575
4581
  |--------------------------------------------------
4576
4582
  */
4583
+ const MIME_TYPE_MAP = {
4584
+ png: "image/png",
4585
+ jpg: "image/jpeg",
4586
+ jpeg: "image/jpeg",
4587
+ mp4: "video/mp4",
4588
+ mov: "video/quicktime",
4589
+ qt: "video/quicktime",
4590
+ };
4591
+ /**
4592
+ |--------------------------------------------------
4593
+ | Make a File Path
4594
+ |--------------------------------------------------
4595
+ */
4596
+ function createFilePath(marketId, saleId, lotId, attributeId, fileName) {
4597
+ return `/${marketId}/${saleId}/${lotId}/${attributeId}/${fileName}`;
4598
+ }
4577
4599
  const getHeaders = (mimeType, bucket = "raw", token) => {
4578
4600
  const headers = new Headers();
4579
4601
  headers.append("mbtype", bucket);
@@ -4595,7 +4617,7 @@ const startUpload = async ({ fileName, fileMimeType, fileExtension, token, optio
4595
4617
  var _a;
4596
4618
  const headers = getHeaders(fileMimeType, (_a = options.options) === null || _a === void 0 ? void 0 : _a.bucket, token);
4597
4619
  const formData = new FormData();
4598
- const filePath = `${options.marketId}/${options.saleId}/${options.lotId}/${options.attributeId}/${fileName}.${fileExtension}`;
4620
+ const filePath = createFilePath(options.marketId, options.saleId, options.lotId, options.attributeId, `${fileName}.${fileExtension}`);
4599
4621
  formData.append("filePath", filePath);
4600
4622
  headers.append("Authorization", `Bearer ${token}`);
4601
4623
  let uploadIdResponse = await fetch(new URL(`${BASE_CF_URL}/${UPLOAD_PATHS.START_UPLOAD}`), {
@@ -4762,7 +4784,7 @@ const deleteUpload = async (fileUrl, token) => {
4762
4784
  * @returns {Promise<MediaFinishUploadResponse>}
4763
4785
  * @throws {Error} When upload fails
4764
4786
  */
4765
- const uploadFile = async (input, token) => {
4787
+ const uploadMultipartFile = async (input, token) => {
4766
4788
  var _a, _b, _c, _d, _e;
4767
4789
  let uploadId = "";
4768
4790
  let filePath = "";
@@ -4866,12 +4888,61 @@ const uploadFile = async (input, token) => {
4866
4888
  throw new Error("Upload failed and canceled " + error);
4867
4889
  }
4868
4890
  };
4891
+ const uploadSingleFile = async (input, token) => {
4892
+ const { file, filePath, uploadConfig } = input;
4893
+ let fileMimeType = "";
4894
+ let destinationPath = "";
4895
+ let fileName = "";
4896
+ let fileExtension = "";
4897
+ if (!filePath && !file) {
4898
+ throw new Error("Either filePath or file must be provided");
4899
+ }
4900
+ if (filePath && file) {
4901
+ throw new Error("Only one of filePath or file can be provided");
4902
+ }
4903
+ // We perform a copy form one file to another
4904
+ if (filePath) {
4905
+ fileName = filePath.split("/").pop() || "";
4906
+ fileExtension = fileName.split(".").pop() || "";
4907
+ fileMimeType = MIME_TYPE_MAP[fileExtension] || "";
4908
+ destinationPath = createFilePath(uploadConfig.marketId, uploadConfig.saleId, uploadConfig.lotId, uploadConfig.attributeId, `${fileName}`);
4909
+ }
4910
+ // We upload a single File
4911
+ if (file) {
4912
+ fileName = file.name.replace(/\.[^/.]+$/, "");
4913
+ fileExtension = file.name.split(".").pop() || "";
4914
+ fileMimeType = file.type;
4915
+ destinationPath = createFilePath(uploadConfig.marketId, uploadConfig.saleId, uploadConfig.lotId, uploadConfig.attributeId, `${fileName}.${fileExtension}`);
4916
+ }
4917
+ // Construct the Fetch Request
4918
+ const uploadUrl = new URL(`${BASE_CF_URL}/${UPLOAD_PATHS.UPLOAD_SINGLE_FILE}`);
4919
+ const headers = new Headers();
4920
+ headers.append("mbtype", "raw");
4921
+ headers.append("Authorization", `Bearer ${token}`);
4922
+ headers.append("mmimetype", fileMimeType);
4923
+ const formData = new FormData();
4924
+ filePath && formData.append("existingFilePath", filePath);
4925
+ destinationPath && formData.append("filePath", destinationPath);
4926
+ file && formData.append("file", file);
4927
+ const uploadResponse = await fetch(uploadUrl, {
4928
+ headers: headers,
4929
+ method: "POST",
4930
+ body: formData,
4931
+ });
4932
+ if (!uploadResponse.ok) {
4933
+ throw new Error("Failed to upload single file");
4934
+ }
4935
+ return (await uploadResponse.json());
4936
+ };
4869
4937
 
4870
4938
  // Multipart Upload for Media to the MARTEYE Media Service
4871
4939
  function create$9() {
4872
4940
  const files = {
4873
- uploadFile: async (input, token) => {
4874
- return await uploadFile(input, token);
4941
+ uploadSingleFile: async (input, token) => {
4942
+ return await uploadSingleFile(input, token);
4943
+ },
4944
+ uploadMultipartFile: async (input, token) => {
4945
+ return await uploadMultipartFile(input, token);
4875
4946
  },
4876
4947
  deleteFile: async (fileUrl, token) => {
4877
4948
  return await deleteUpload(fileUrl, token);
@@ -5216,9 +5287,246 @@ function createAppManifest(appConfig) {
5216
5287
  };
5217
5288
  }
5218
5289
 
5290
+ class EarTag {
5291
+ static get countryCodesByNumber() {
5292
+ let reversed = {};
5293
+ for (const key of Object.keys(EarTag.countryCodes)) {
5294
+ reversed[EarTag.countryCodes[key]] = key;
5295
+ }
5296
+ return reversed;
5297
+ }
5298
+ normalisedCountryCode(countryCode) {
5299
+ if (!countryCode || typeof countryCode !== "string") {
5300
+ return null;
5301
+ }
5302
+ switch (countryCode) {
5303
+ case "GB-ENG":
5304
+ case "GB-SCT":
5305
+ case "GB-WLS":
5306
+ return "UK";
5307
+ case "GB-NIR":
5308
+ return "XI";
5309
+ default:
5310
+ return countryCode;
5311
+ }
5312
+ }
5313
+ get raw() {
5314
+ return this._raw;
5315
+ }
5316
+ isEartag() {
5317
+ return this._isEartag;
5318
+ }
5319
+ get isoCountryCode() {
5320
+ return this._isoCountryCode;
5321
+ }
5322
+ get nationalIdentifier() {
5323
+ return this._nationalIdentifier;
5324
+ }
5325
+ // private constructor
5326
+ constructor(input, fallbackCountryCode) {
5327
+ // readonly properties
5328
+ this._isEartag = false;
5329
+ fallbackCountryCode = this.normalisedCountryCode(fallbackCountryCode);
5330
+ let workingInput = input.replace(/\s/g, "").replace(/[^ -~]+/g, "");
5331
+ this._raw = workingInput; // Store the initial cleaned input. May get updated if prefix is added.
5332
+ // Part 1: Handle explicit country codes (alpha or numeric) in the input string
5333
+ let parsedCountryCode;
5334
+ let parsedNationalIdentifier;
5335
+ // 1a. Alpha prefix
5336
+ if (workingInput.length > 2 && /^[A-Z]{2}/.test(workingInput)) {
5337
+ const alphaCode = workingInput.slice(0, 2);
5338
+ const numericCode = EarTag.countryCodes[alphaCode];
5339
+ if (numericCode) {
5340
+ // Replace alpha with numeric for further parsing
5341
+ workingInput = numericCode + workingInput.slice(2);
5342
+ this._raw = workingInput; // Update _raw as it now contains numeric country code
5343
+ }
5344
+ // If unknown alpha, workingInput remains as is, will be handled by numeric check or fallback
5345
+ }
5346
+ // 1b. Numeric country code (already in workingInput, or converted from alpha)
5347
+ const countryPattern = "(372|826|899|528|250|276|056)";
5348
+ const regex12 = new RegExp(`^[0-9]{0,7}(${countryPattern})([0-9]{7})([0-9]{5})`);
5349
+ let match12 = regex12.exec(workingInput);
5350
+ if (match12) {
5351
+ parsedCountryCode = match12[1];
5352
+ parsedNationalIdentifier = `${match12[3]}${match12[4]}`;
5353
+ }
5354
+ else {
5355
+ const regex11 = new RegExp(`^[0-9]{0,7}(${countryPattern})([0-9]{6})([0-9]{5})`);
5356
+ let match11 = regex11.exec(workingInput);
5357
+ if (match11) {
5358
+ parsedCountryCode = match11[1];
5359
+ parsedNationalIdentifier = `${match11[3]}${match11[4]}`;
5360
+ }
5361
+ }
5362
+ // Part 2: If no country code parsed yet, try fallback
5363
+ if (!parsedCountryCode && fallbackCountryCode) {
5364
+ const numericFallback = EarTag.countryCodes[fallbackCountryCode];
5365
+ if (numericFallback) {
5366
+ // `workingInput` at this point is the original input (cleaned, no recognized country code)
5367
+ // Assume `workingInput` is the national identifier part (must be 11 or 12 digits)
5368
+ if (workingInput.length === 12 || workingInput.length === 11) {
5369
+ parsedCountryCode = numericFallback;
5370
+ parsedNationalIdentifier = workingInput;
5371
+ // Update _raw to reflect the tag as if it had the country code
5372
+ this._raw = numericFallback + workingInput;
5373
+ }
5374
+ }
5375
+ }
5376
+ // Part 3: Finalize and set properties
5377
+ if (parsedCountryCode && parsedNationalIdentifier) {
5378
+ this._isoCountryCode = parsedCountryCode;
5379
+ if (parsedNationalIdentifier.length === 11) {
5380
+ // Pad 11-digit national ID to 12-digits by prepending "0"
5381
+ this._nationalIdentifier = "0" + parsedNationalIdentifier;
5382
+ }
5383
+ else if (parsedNationalIdentifier.length === 12) {
5384
+ this._nationalIdentifier = parsedNationalIdentifier;
5385
+ }
5386
+ else {
5387
+ // This case should ideally not be reached if lengths are checked properly before.
5388
+ this._isEartag = false;
5389
+ return;
5390
+ }
5391
+ this._isEartag = true;
5392
+ }
5393
+ else {
5394
+ this._isEartag = false;
5395
+ }
5396
+ }
5397
+ static parse(str, fallbackCountryCode) {
5398
+ return new EarTag(str, fallbackCountryCode);
5399
+ }
5400
+ static format(str, marketCountry) {
5401
+ let t = EarTag.parse(str, marketCountry);
5402
+ if (t.isEartag()) {
5403
+ return t.toString();
5404
+ }
5405
+ return null;
5406
+ }
5407
+ toString() {
5408
+ if (!this._isEartag) {
5409
+ return "Invalid EarTag";
5410
+ }
5411
+ return `${EarTag.countryCodesByNumber[this.isoCountryCode]} ${this.nationalIdentifier.slice(0, 7)} ${this.nationalIdentifier.slice(7)}`;
5412
+ }
5413
+ isISO24631() {
5414
+ return EarTag.regexISO24631.test(this._raw);
5415
+ }
5416
+ toISO24631() {
5417
+ if (!this.isISO24631()) {
5418
+ return "Not a ISO24631 EarTag";
5419
+ }
5420
+ // ISO 24631 Formatting for movements
5421
+ const res = EarTag.regexISO24631.exec(this._raw);
5422
+ return `${res[1]} ${res[2]} ${res[3]} ${res[4]} ${res[5]} ${res[6]} ${res[7]} ${res[8]}`;
5423
+ }
5424
+ }
5425
+ EarTag.regexISO24631 = /^([0-9]{1})([0-9]{1})([0-9]{2})([0-9]{2})([0-9]{1})(372|826|899|528|250|276)([0-9]{7})([0-9]{5})/;
5426
+ EarTag.countryCodes = {
5427
+ IE: "372",
5428
+ UK: "826",
5429
+ XI: "899",
5430
+ NL: "528",
5431
+ FR: "250",
5432
+ DE: "276",
5433
+ BE: "056",
5434
+ };
5435
+
5436
+ function lotComparator(a, b) {
5437
+ const aMatch = a.lotNumber.match(/^(\d+)(\D*)$/);
5438
+ const bMatch = b.lotNumber.match(/^(\d+)(\D*)$/);
5439
+ // If neither matches the pattern, fall back to string comparison
5440
+ if (!aMatch && !bMatch) {
5441
+ return a.lotNumber.localeCompare(b.lotNumber);
5442
+ }
5443
+ // If only one matches, the one with numbers comes after
5444
+ if (!aMatch)
5445
+ return -1;
5446
+ if (!bMatch)
5447
+ return 1;
5448
+ // Handle cases with numbers
5449
+ const aNum = parseInt(aMatch[1], 10);
5450
+ const bNum = parseInt(bMatch[1], 10);
5451
+ // Compare numeric parts first
5452
+ if (aNum !== bNum)
5453
+ return aNum - bNum;
5454
+ // Get alphabetic suffixes (or empty string if none)
5455
+ const aAlpha = (aMatch === null || aMatch === void 0 ? void 0 : aMatch[2]) || "";
5456
+ const bAlpha = (bMatch === null || bMatch === void 0 ? void 0 : bMatch[2]) || "";
5457
+ // Compare by length first (shorter comes first)
5458
+ if (aAlpha.length !== bAlpha.length)
5459
+ return aAlpha.length - bAlpha.length;
5460
+ // Then compare alphabetically
5461
+ return aAlpha.localeCompare(bAlpha);
5462
+ }
5463
+ function sortByLotNumber(lots) {
5464
+ return [...lots].sort(lotComparator);
5465
+ }
5466
+ /***
5467
+ * Generate the next lot number in a sequence:
5468
+ */
5469
+ function nextLotNumber(previousLotNumber) {
5470
+ const match = previousLotNumber.match(/^(\d+)(\D*)$/);
5471
+ if (match) {
5472
+ // Has numeric part
5473
+ const numPart = parseInt(match[1], 10);
5474
+ const alphaPart = match[2];
5475
+ if (alphaPart === "") {
5476
+ // Just a number: 1 -> 2
5477
+ return (numPart + 1).toString();
5478
+ }
5479
+ else {
5480
+ // Alphanumeric: increment the alpha part
5481
+ const nextAlpha = incrementAlphaSequence(alphaPart);
5482
+ return numPart + nextAlpha;
5483
+ }
5484
+ }
5485
+ else {
5486
+ // Pure alphabetic: A -> B, Z -> AA, etc.
5487
+ return incrementAlphaSequence(previousLotNumber);
5488
+ }
5489
+ }
5490
+ function incrementAlphaSequence(alpha) {
5491
+ if (alpha === "") {
5492
+ return "A";
5493
+ }
5494
+ // Convert to uppercase for consistent handling
5495
+ alpha = alpha.toUpperCase();
5496
+ // Check if we're at the end of sequence (all Z's)
5497
+ if (alpha === "Z".repeat(alpha.length)) {
5498
+ // Z -> AA, ZZ -> AAA, etc.
5499
+ return "A".repeat(alpha.length + 1);
5500
+ }
5501
+ // Convert string to array for easier manipulation
5502
+ let chars = alpha.split("");
5503
+ let carry = true;
5504
+ // Start from the rightmost character and work backwards
5505
+ for (let i = chars.length - 1; i >= 0 && carry; i--) {
5506
+ if (chars[i] === "Z") {
5507
+ chars[i] = "A";
5508
+ // carry remains true
5509
+ }
5510
+ else {
5511
+ // Increment the character
5512
+ chars[i] = String.fromCharCode(chars[i].charCodeAt(0) + 1);
5513
+ carry = false;
5514
+ }
5515
+ }
5516
+ // If we still have carry, prepend an A
5517
+ if (carry) {
5518
+ chars.unshift("A");
5519
+ }
5520
+ return chars.join("");
5521
+ }
5522
+
5523
+ exports.EarTag = EarTag;
5219
5524
  exports.Studio = Studio;
5220
5525
  exports.StudioHeaders = StudioHeaders;
5221
5526
  exports.StudioTypes = types;
5222
5527
  exports.createAppManifest = createAppManifest;
5223
5528
  exports.default = Studio;
5529
+ exports.lotComparator = lotComparator;
5530
+ exports.nextLotNumber = nextLotNumber;
5531
+ exports.sortByLotNumber = sortByLotNumber;
5224
5532
  //# sourceMappingURL=index.js.map