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