@marteye/studiojs 1.1.24 → 1.1.26
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.d.ts +263 -109
- package/dist/index.esm.js +381 -10
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +384 -9
- package/dist/index.js.map +1 -1
- package/dist/resources/applications.d.ts +90 -0
- package/dist/resources/files.d.ts +6 -2
- package/dist/resources/lots.d.ts +1 -0
- package/dist/resources.d.ts +14 -1
- package/dist/studio.d.ts +14 -1
- package/dist/types.d.ts +40 -0
- package/dist/utils/eartag.d.ts +2 -2
- package/dist/utils/lots.d.ts +10 -0
- package/dist/utils/multipart-upload.d.ts +23 -3
- package/package.json +2 -1
package/dist/index.esm.js
CHANGED
|
@@ -67,7 +67,7 @@ function SimpleHttpClient(baseUrl, apiKey, fetch, defaultTimeout, debug = false)
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// Path: studiojs/src/resources/markets.ts
|
|
70
|
-
function create$
|
|
70
|
+
function create$d(_) {
|
|
71
71
|
const actions = {
|
|
72
72
|
/***
|
|
73
73
|
* This is used to construct the action from the request body
|
|
@@ -97,7 +97,7 @@ function create$c(_) {
|
|
|
97
97
|
return actions;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
function create$
|
|
100
|
+
function create$c(httpClient) {
|
|
101
101
|
return {
|
|
102
102
|
list: async (marketId) => {
|
|
103
103
|
return httpClient.get(`/${marketId}/adjustments`);
|
|
@@ -108,6 +108,72 @@ function create$b(httpClient) {
|
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
function create$b(httpClient) {
|
|
112
|
+
let applications = {
|
|
113
|
+
/**
|
|
114
|
+
* List applications for a market with optional filtering
|
|
115
|
+
* @param marketId - ID of the market
|
|
116
|
+
* @param options - Optional query parameters for filtering and pagination
|
|
117
|
+
* @returns Paginated list of applications
|
|
118
|
+
*/
|
|
119
|
+
list: async (marketId, options) => {
|
|
120
|
+
return httpClient.get(`/${marketId}/applications`, options);
|
|
121
|
+
},
|
|
122
|
+
/**
|
|
123
|
+
* Get a single application by ID
|
|
124
|
+
* @param marketId - ID of the market
|
|
125
|
+
* @param applicationId - ID of the application
|
|
126
|
+
* @returns The application details
|
|
127
|
+
*/
|
|
128
|
+
get: async (marketId, applicationId) => {
|
|
129
|
+
return httpClient.get(`/${marketId}/applications/${applicationId}`);
|
|
130
|
+
},
|
|
131
|
+
/**
|
|
132
|
+
* Create a new application
|
|
133
|
+
* @param marketId - ID of the market
|
|
134
|
+
* @param applicationData - The application data
|
|
135
|
+
* @returns The created application
|
|
136
|
+
*/
|
|
137
|
+
create: async (marketId, applicationData) => {
|
|
138
|
+
return httpClient.post(`/${marketId}/applications`, applicationData);
|
|
139
|
+
},
|
|
140
|
+
/**
|
|
141
|
+
* Update an existing application
|
|
142
|
+
* @param marketId - ID of the market
|
|
143
|
+
* @param applicationId - ID of the application to update
|
|
144
|
+
* @param updateData - The fields to update
|
|
145
|
+
* @returns The updated application
|
|
146
|
+
* @throws Error if the application is already approved or rejected
|
|
147
|
+
*/
|
|
148
|
+
update: async (marketId, applicationId, updateData) => {
|
|
149
|
+
return httpClient.post(`/${marketId}/applications/${applicationId}`, updateData);
|
|
150
|
+
},
|
|
151
|
+
/**
|
|
152
|
+
* Approve an application
|
|
153
|
+
* @param marketId - ID of the market
|
|
154
|
+
* @param applicationId - ID of the application to approve
|
|
155
|
+
* @param notes - Optional notes for the approval
|
|
156
|
+
* @returns The approved application
|
|
157
|
+
* @throws Error if the application is not in pending status
|
|
158
|
+
*/
|
|
159
|
+
approve: async (marketId, applicationId, notes) => {
|
|
160
|
+
return httpClient.post(`/${marketId}/applications/${applicationId}/approve`, { notes });
|
|
161
|
+
},
|
|
162
|
+
/**
|
|
163
|
+
* Reject an application
|
|
164
|
+
* @param marketId - ID of the market
|
|
165
|
+
* @param applicationId - ID of the application to reject
|
|
166
|
+
* @param notes - Optional notes for the rejection
|
|
167
|
+
* @returns The rejected application
|
|
168
|
+
* @throws Error if the application is not in pending status
|
|
169
|
+
*/
|
|
170
|
+
reject: async (marketId, applicationId, notes) => {
|
|
171
|
+
return httpClient.post(`/${marketId}/applications/${applicationId}/reject`, { notes });
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
return applications;
|
|
175
|
+
}
|
|
176
|
+
|
|
111
177
|
// Path: studiojs/src/resources/markets.ts
|
|
112
178
|
function create$a(httpClient) {
|
|
113
179
|
let customers = {
|
|
@@ -4554,7 +4620,12 @@ z.object({
|
|
|
4554
4620
|
suffix: z.string().min(1, { message: "Suffix Type is required" }),
|
|
4555
4621
|
});
|
|
4556
4622
|
// Adding Sizes here will make more end points in the mainConfig object
|
|
4557
|
-
const IMAGE_SIZES_VALUES$1 = [
|
|
4623
|
+
const IMAGE_SIZES_VALUES$1 = [
|
|
4624
|
+
"thumbnail",
|
|
4625
|
+
"small",
|
|
4626
|
+
"medium",
|
|
4627
|
+
"large",
|
|
4628
|
+
];
|
|
4558
4629
|
const VIDEO_TASKS_VALUES$1 = ["compressed", "thumbnail"];
|
|
4559
4630
|
z.enum(VIDEO_TASKS_VALUES$1);
|
|
4560
4631
|
z.enum(IMAGE_SIZES_VALUES$1);
|
|
@@ -4564,12 +4635,29 @@ const UPLOAD_PATHS = {
|
|
|
4564
4635
|
FINISH_UPLOAD: "finishMultipartUpload",
|
|
4565
4636
|
CANCEL_UPLOAD: "cancelUpload",
|
|
4566
4637
|
DELETE_UPLOAD: "deleteUpload",
|
|
4638
|
+
UPLOAD_SINGLE_FILE: "upload",
|
|
4567
4639
|
};
|
|
4568
4640
|
/**
|
|
4569
4641
|
|--------------------------------------------------
|
|
4570
4642
|
| Helper Functions
|
|
4571
4643
|
|--------------------------------------------------
|
|
4572
4644
|
*/
|
|
4645
|
+
const MIME_TYPE_MAP = {
|
|
4646
|
+
png: "image/png",
|
|
4647
|
+
jpg: "image/jpeg",
|
|
4648
|
+
jpeg: "image/jpeg",
|
|
4649
|
+
mp4: "video/mp4",
|
|
4650
|
+
mov: "video/quicktime",
|
|
4651
|
+
qt: "video/quicktime",
|
|
4652
|
+
};
|
|
4653
|
+
/**
|
|
4654
|
+
|--------------------------------------------------
|
|
4655
|
+
| Make a File Path
|
|
4656
|
+
|--------------------------------------------------
|
|
4657
|
+
*/
|
|
4658
|
+
function createFilePath(marketId, saleId, lotId, attributeId, fileName) {
|
|
4659
|
+
return `/${marketId}/${saleId}/${lotId}/${attributeId}/${fileName}`;
|
|
4660
|
+
}
|
|
4573
4661
|
const getHeaders = (mimeType, bucket = "raw", token) => {
|
|
4574
4662
|
const headers = new Headers();
|
|
4575
4663
|
headers.append("mbtype", bucket);
|
|
@@ -4591,7 +4679,7 @@ const startUpload = async ({ fileName, fileMimeType, fileExtension, token, optio
|
|
|
4591
4679
|
var _a;
|
|
4592
4680
|
const headers = getHeaders(fileMimeType, (_a = options.options) === null || _a === void 0 ? void 0 : _a.bucket, token);
|
|
4593
4681
|
const formData = new FormData();
|
|
4594
|
-
const filePath =
|
|
4682
|
+
const filePath = createFilePath(options.marketId, options.saleId, options.lotId, options.attributeId, `${fileName}.${fileExtension}`);
|
|
4595
4683
|
formData.append("filePath", filePath);
|
|
4596
4684
|
headers.append("Authorization", `Bearer ${token}`);
|
|
4597
4685
|
let uploadIdResponse = await fetch(new URL(`${BASE_CF_URL}/${UPLOAD_PATHS.START_UPLOAD}`), {
|
|
@@ -4758,7 +4846,7 @@ const deleteUpload = async (fileUrl, token) => {
|
|
|
4758
4846
|
* @returns {Promise<MediaFinishUploadResponse>}
|
|
4759
4847
|
* @throws {Error} When upload fails
|
|
4760
4848
|
*/
|
|
4761
|
-
const
|
|
4849
|
+
const uploadMultipartFile = async (input, token) => {
|
|
4762
4850
|
var _a, _b, _c, _d, _e;
|
|
4763
4851
|
let uploadId = "";
|
|
4764
4852
|
let filePath = "";
|
|
@@ -4862,12 +4950,61 @@ const uploadFile = async (input, token) => {
|
|
|
4862
4950
|
throw new Error("Upload failed and canceled " + error);
|
|
4863
4951
|
}
|
|
4864
4952
|
};
|
|
4953
|
+
const uploadSingleFile = async (input, token) => {
|
|
4954
|
+
const { file, filePath, uploadConfig } = input;
|
|
4955
|
+
let fileMimeType = "";
|
|
4956
|
+
let destinationPath = "";
|
|
4957
|
+
let fileName = "";
|
|
4958
|
+
let fileExtension = "";
|
|
4959
|
+
if (!filePath && !file) {
|
|
4960
|
+
throw new Error("Either filePath or file must be provided");
|
|
4961
|
+
}
|
|
4962
|
+
if (filePath && file) {
|
|
4963
|
+
throw new Error("Only one of filePath or file can be provided");
|
|
4964
|
+
}
|
|
4965
|
+
// We perform a copy form one file to another
|
|
4966
|
+
if (filePath) {
|
|
4967
|
+
fileName = filePath.split("/").pop() || "";
|
|
4968
|
+
fileExtension = fileName.split(".").pop() || "";
|
|
4969
|
+
fileMimeType = MIME_TYPE_MAP[fileExtension] || "";
|
|
4970
|
+
destinationPath = createFilePath(uploadConfig.marketId, uploadConfig.saleId, uploadConfig.lotId, uploadConfig.attributeId, `${fileName}`);
|
|
4971
|
+
}
|
|
4972
|
+
// We upload a single File
|
|
4973
|
+
if (file) {
|
|
4974
|
+
fileName = file.name.replace(/\.[^/.]+$/, "");
|
|
4975
|
+
fileExtension = file.name.split(".").pop() || "";
|
|
4976
|
+
fileMimeType = file.type;
|
|
4977
|
+
destinationPath = createFilePath(uploadConfig.marketId, uploadConfig.saleId, uploadConfig.lotId, uploadConfig.attributeId, `${fileName}.${fileExtension}`);
|
|
4978
|
+
}
|
|
4979
|
+
// Construct the Fetch Request
|
|
4980
|
+
const uploadUrl = new URL(`${BASE_CF_URL}/${UPLOAD_PATHS.UPLOAD_SINGLE_FILE}`);
|
|
4981
|
+
const headers = new Headers();
|
|
4982
|
+
headers.append("mbtype", "raw");
|
|
4983
|
+
headers.append("Authorization", `Bearer ${token}`);
|
|
4984
|
+
headers.append("mmimetype", fileMimeType);
|
|
4985
|
+
const formData = new FormData();
|
|
4986
|
+
filePath && formData.append("existingFilePath", filePath);
|
|
4987
|
+
destinationPath && formData.append("filePath", destinationPath);
|
|
4988
|
+
file && formData.append("file", file);
|
|
4989
|
+
const uploadResponse = await fetch(uploadUrl, {
|
|
4990
|
+
headers: headers,
|
|
4991
|
+
method: "POST",
|
|
4992
|
+
body: formData,
|
|
4993
|
+
});
|
|
4994
|
+
if (!uploadResponse.ok) {
|
|
4995
|
+
throw new Error("Failed to upload single file");
|
|
4996
|
+
}
|
|
4997
|
+
return (await uploadResponse.json());
|
|
4998
|
+
};
|
|
4865
4999
|
|
|
4866
5000
|
// Multipart Upload for Media to the MARTEYE Media Service
|
|
4867
5001
|
function create$9() {
|
|
4868
5002
|
const files = {
|
|
4869
|
-
|
|
4870
|
-
return await
|
|
5003
|
+
uploadSingleFile: async (input, token) => {
|
|
5004
|
+
return await uploadSingleFile(input, token);
|
|
5005
|
+
},
|
|
5006
|
+
uploadMultipartFile: async (input, token) => {
|
|
5007
|
+
return await uploadMultipartFile(input, token);
|
|
4871
5008
|
},
|
|
4872
5009
|
deleteFile: async (fileUrl, token) => {
|
|
4873
5010
|
return await deleteUpload(fileUrl, token);
|
|
@@ -5040,9 +5177,10 @@ function resources(httpClient) {
|
|
|
5040
5177
|
lots: create$7(httpClient),
|
|
5041
5178
|
lotitems: create$8(httpClient),
|
|
5042
5179
|
webhooks: create(),
|
|
5043
|
-
actions: create$
|
|
5180
|
+
actions: create$d(),
|
|
5181
|
+
applications: create$b(httpClient),
|
|
5044
5182
|
settings: create$2(httpClient),
|
|
5045
|
-
adjustments: create$
|
|
5183
|
+
adjustments: create$c(httpClient),
|
|
5046
5184
|
productCodes: create$5(httpClient),
|
|
5047
5185
|
taxRates: create$1(httpClient),
|
|
5048
5186
|
customers: create$a(httpClient),
|
|
@@ -5212,5 +5350,238 @@ function createAppManifest(appConfig) {
|
|
|
5212
5350
|
};
|
|
5213
5351
|
}
|
|
5214
5352
|
|
|
5215
|
-
|
|
5353
|
+
class EarTag {
|
|
5354
|
+
static get countryCodesByNumber() {
|
|
5355
|
+
let reversed = {};
|
|
5356
|
+
for (const key of Object.keys(EarTag.countryCodes)) {
|
|
5357
|
+
reversed[EarTag.countryCodes[key]] = key;
|
|
5358
|
+
}
|
|
5359
|
+
return reversed;
|
|
5360
|
+
}
|
|
5361
|
+
normalisedCountryCode(countryCode) {
|
|
5362
|
+
if (!countryCode || typeof countryCode !== "string") {
|
|
5363
|
+
return null;
|
|
5364
|
+
}
|
|
5365
|
+
switch (countryCode) {
|
|
5366
|
+
case "GB-ENG":
|
|
5367
|
+
case "GB-SCT":
|
|
5368
|
+
case "GB-WLS":
|
|
5369
|
+
return "UK";
|
|
5370
|
+
case "GB-NIR":
|
|
5371
|
+
return "XI";
|
|
5372
|
+
default:
|
|
5373
|
+
return countryCode;
|
|
5374
|
+
}
|
|
5375
|
+
}
|
|
5376
|
+
get raw() {
|
|
5377
|
+
return this._raw;
|
|
5378
|
+
}
|
|
5379
|
+
isEartag() {
|
|
5380
|
+
return this._isEartag;
|
|
5381
|
+
}
|
|
5382
|
+
get isoCountryCode() {
|
|
5383
|
+
return this._isoCountryCode;
|
|
5384
|
+
}
|
|
5385
|
+
get nationalIdentifier() {
|
|
5386
|
+
return this._nationalIdentifier;
|
|
5387
|
+
}
|
|
5388
|
+
// private constructor
|
|
5389
|
+
constructor(input, fallbackCountryCode) {
|
|
5390
|
+
// readonly properties
|
|
5391
|
+
this._isEartag = false;
|
|
5392
|
+
fallbackCountryCode = this.normalisedCountryCode(fallbackCountryCode);
|
|
5393
|
+
let workingInput = input.replace(/\s/g, "").replace(/[^ -~]+/g, "");
|
|
5394
|
+
this._raw = workingInput; // Store the initial cleaned input. May get updated if prefix is added.
|
|
5395
|
+
// Part 1: Handle explicit country codes (alpha or numeric) in the input string
|
|
5396
|
+
let parsedCountryCode;
|
|
5397
|
+
let parsedNationalIdentifier;
|
|
5398
|
+
// 1a. Alpha prefix
|
|
5399
|
+
if (workingInput.length > 2 && /^[A-Z]{2}/.test(workingInput)) {
|
|
5400
|
+
const alphaCode = workingInput.slice(0, 2);
|
|
5401
|
+
const numericCode = EarTag.countryCodes[alphaCode];
|
|
5402
|
+
if (numericCode) {
|
|
5403
|
+
// Replace alpha with numeric for further parsing
|
|
5404
|
+
workingInput = numericCode + workingInput.slice(2);
|
|
5405
|
+
this._raw = workingInput; // Update _raw as it now contains numeric country code
|
|
5406
|
+
}
|
|
5407
|
+
// If unknown alpha, workingInput remains as is, will be handled by numeric check or fallback
|
|
5408
|
+
}
|
|
5409
|
+
// 1b. Numeric country code (already in workingInput, or converted from alpha)
|
|
5410
|
+
const countryPattern = "(372|826|899|528|250|276|056)";
|
|
5411
|
+
const regex12 = new RegExp(`^[0-9]{0,7}(${countryPattern})([0-9]{7})([0-9]{5})`);
|
|
5412
|
+
let match12 = regex12.exec(workingInput);
|
|
5413
|
+
if (match12) {
|
|
5414
|
+
parsedCountryCode = match12[1];
|
|
5415
|
+
parsedNationalIdentifier = `${match12[3]}${match12[4]}`;
|
|
5416
|
+
}
|
|
5417
|
+
else {
|
|
5418
|
+
const regex11 = new RegExp(`^[0-9]{0,7}(${countryPattern})([0-9]{6})([0-9]{5})`);
|
|
5419
|
+
let match11 = regex11.exec(workingInput);
|
|
5420
|
+
if (match11) {
|
|
5421
|
+
parsedCountryCode = match11[1];
|
|
5422
|
+
parsedNationalIdentifier = `${match11[3]}${match11[4]}`;
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
// Part 2: If no country code parsed yet, try fallback
|
|
5426
|
+
if (!parsedCountryCode && fallbackCountryCode) {
|
|
5427
|
+
const numericFallback = EarTag.countryCodes[fallbackCountryCode];
|
|
5428
|
+
if (numericFallback) {
|
|
5429
|
+
// `workingInput` at this point is the original input (cleaned, no recognized country code)
|
|
5430
|
+
// Assume `workingInput` is the national identifier part (must be 11 or 12 digits)
|
|
5431
|
+
if (workingInput.length === 12 || workingInput.length === 11) {
|
|
5432
|
+
parsedCountryCode = numericFallback;
|
|
5433
|
+
parsedNationalIdentifier = workingInput;
|
|
5434
|
+
// Update _raw to reflect the tag as if it had the country code
|
|
5435
|
+
this._raw = numericFallback + workingInput;
|
|
5436
|
+
}
|
|
5437
|
+
}
|
|
5438
|
+
}
|
|
5439
|
+
// Part 3: Finalize and set properties
|
|
5440
|
+
if (parsedCountryCode && parsedNationalIdentifier) {
|
|
5441
|
+
this._isoCountryCode = parsedCountryCode;
|
|
5442
|
+
if (parsedNationalIdentifier.length === 11) {
|
|
5443
|
+
// Pad 11-digit national ID to 12-digits by prepending "0"
|
|
5444
|
+
this._nationalIdentifier = "0" + parsedNationalIdentifier;
|
|
5445
|
+
}
|
|
5446
|
+
else if (parsedNationalIdentifier.length === 12) {
|
|
5447
|
+
this._nationalIdentifier = parsedNationalIdentifier;
|
|
5448
|
+
}
|
|
5449
|
+
else {
|
|
5450
|
+
// This case should ideally not be reached if lengths are checked properly before.
|
|
5451
|
+
this._isEartag = false;
|
|
5452
|
+
return;
|
|
5453
|
+
}
|
|
5454
|
+
this._isEartag = true;
|
|
5455
|
+
}
|
|
5456
|
+
else {
|
|
5457
|
+
this._isEartag = false;
|
|
5458
|
+
}
|
|
5459
|
+
}
|
|
5460
|
+
static parse(str, fallbackCountryCode) {
|
|
5461
|
+
return new EarTag(str, fallbackCountryCode);
|
|
5462
|
+
}
|
|
5463
|
+
static format(str, marketCountry) {
|
|
5464
|
+
let t = EarTag.parse(str, marketCountry);
|
|
5465
|
+
if (t.isEartag()) {
|
|
5466
|
+
return t.toString();
|
|
5467
|
+
}
|
|
5468
|
+
return null;
|
|
5469
|
+
}
|
|
5470
|
+
toString() {
|
|
5471
|
+
if (!this._isEartag) {
|
|
5472
|
+
return "Invalid EarTag";
|
|
5473
|
+
}
|
|
5474
|
+
return `${EarTag.countryCodesByNumber[this.isoCountryCode]} ${this.nationalIdentifier.slice(0, 7)} ${this.nationalIdentifier.slice(7)}`;
|
|
5475
|
+
}
|
|
5476
|
+
isISO24631() {
|
|
5477
|
+
return EarTag.regexISO24631.test(this._raw);
|
|
5478
|
+
}
|
|
5479
|
+
toISO24631() {
|
|
5480
|
+
if (!this.isISO24631()) {
|
|
5481
|
+
return "Not a ISO24631 EarTag";
|
|
5482
|
+
}
|
|
5483
|
+
// ISO 24631 Formatting for movements
|
|
5484
|
+
const res = EarTag.regexISO24631.exec(this._raw);
|
|
5485
|
+
return `${res[1]} ${res[2]} ${res[3]} ${res[4]} ${res[5]} ${res[6]} ${res[7]} ${res[8]}`;
|
|
5486
|
+
}
|
|
5487
|
+
}
|
|
5488
|
+
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})/;
|
|
5489
|
+
EarTag.countryCodes = {
|
|
5490
|
+
IE: "372",
|
|
5491
|
+
UK: "826",
|
|
5492
|
+
XI: "899",
|
|
5493
|
+
NL: "528",
|
|
5494
|
+
FR: "250",
|
|
5495
|
+
DE: "276",
|
|
5496
|
+
BE: "056",
|
|
5497
|
+
};
|
|
5498
|
+
|
|
5499
|
+
function lotComparator(a, b) {
|
|
5500
|
+
const aMatch = a.lotNumber.match(/^(\d+)(\D*)$/);
|
|
5501
|
+
const bMatch = b.lotNumber.match(/^(\d+)(\D*)$/);
|
|
5502
|
+
// If neither matches the pattern, fall back to string comparison
|
|
5503
|
+
if (!aMatch && !bMatch) {
|
|
5504
|
+
return a.lotNumber.localeCompare(b.lotNumber);
|
|
5505
|
+
}
|
|
5506
|
+
// If only one matches, the one with numbers comes after
|
|
5507
|
+
if (!aMatch)
|
|
5508
|
+
return -1;
|
|
5509
|
+
if (!bMatch)
|
|
5510
|
+
return 1;
|
|
5511
|
+
// Handle cases with numbers
|
|
5512
|
+
const aNum = parseInt(aMatch[1], 10);
|
|
5513
|
+
const bNum = parseInt(bMatch[1], 10);
|
|
5514
|
+
// Compare numeric parts first
|
|
5515
|
+
if (aNum !== bNum)
|
|
5516
|
+
return aNum - bNum;
|
|
5517
|
+
// Get alphabetic suffixes (or empty string if none)
|
|
5518
|
+
const aAlpha = (aMatch === null || aMatch === void 0 ? void 0 : aMatch[2]) || "";
|
|
5519
|
+
const bAlpha = (bMatch === null || bMatch === void 0 ? void 0 : bMatch[2]) || "";
|
|
5520
|
+
// Compare by length first (shorter comes first)
|
|
5521
|
+
if (aAlpha.length !== bAlpha.length)
|
|
5522
|
+
return aAlpha.length - bAlpha.length;
|
|
5523
|
+
// Then compare alphabetically
|
|
5524
|
+
return aAlpha.localeCompare(bAlpha);
|
|
5525
|
+
}
|
|
5526
|
+
function sortByLotNumber(lots) {
|
|
5527
|
+
return [...lots].sort(lotComparator);
|
|
5528
|
+
}
|
|
5529
|
+
/***
|
|
5530
|
+
* Generate the next lot number in a sequence:
|
|
5531
|
+
*/
|
|
5532
|
+
function nextLotNumber(previousLotNumber) {
|
|
5533
|
+
const match = previousLotNumber.match(/^(\d+)(\D*)$/);
|
|
5534
|
+
if (match) {
|
|
5535
|
+
// Has numeric part
|
|
5536
|
+
const numPart = parseInt(match[1], 10);
|
|
5537
|
+
const alphaPart = match[2];
|
|
5538
|
+
if (alphaPart === "") {
|
|
5539
|
+
// Just a number: 1 -> 2
|
|
5540
|
+
return (numPart + 1).toString();
|
|
5541
|
+
}
|
|
5542
|
+
else {
|
|
5543
|
+
// Alphanumeric: increment the alpha part
|
|
5544
|
+
const nextAlpha = incrementAlphaSequence(alphaPart);
|
|
5545
|
+
return numPart + nextAlpha;
|
|
5546
|
+
}
|
|
5547
|
+
}
|
|
5548
|
+
else {
|
|
5549
|
+
// Pure alphabetic: A -> B, Z -> AA, etc.
|
|
5550
|
+
return incrementAlphaSequence(previousLotNumber);
|
|
5551
|
+
}
|
|
5552
|
+
}
|
|
5553
|
+
function incrementAlphaSequence(alpha) {
|
|
5554
|
+
if (alpha === "") {
|
|
5555
|
+
return "A";
|
|
5556
|
+
}
|
|
5557
|
+
// Convert to uppercase for consistent handling
|
|
5558
|
+
alpha = alpha.toUpperCase();
|
|
5559
|
+
// Check if we're at the end of sequence (all Z's)
|
|
5560
|
+
if (alpha === "Z".repeat(alpha.length)) {
|
|
5561
|
+
// Z -> AA, ZZ -> AAA, etc.
|
|
5562
|
+
return "A".repeat(alpha.length + 1);
|
|
5563
|
+
}
|
|
5564
|
+
// Convert string to array for easier manipulation
|
|
5565
|
+
let chars = alpha.split("");
|
|
5566
|
+
let carry = true;
|
|
5567
|
+
// Start from the rightmost character and work backwards
|
|
5568
|
+
for (let i = chars.length - 1; i >= 0 && carry; i--) {
|
|
5569
|
+
if (chars[i] === "Z") {
|
|
5570
|
+
chars[i] = "A";
|
|
5571
|
+
// carry remains true
|
|
5572
|
+
}
|
|
5573
|
+
else {
|
|
5574
|
+
// Increment the character
|
|
5575
|
+
chars[i] = String.fromCharCode(chars[i].charCodeAt(0) + 1);
|
|
5576
|
+
carry = false;
|
|
5577
|
+
}
|
|
5578
|
+
}
|
|
5579
|
+
// If we still have carry, prepend an A
|
|
5580
|
+
if (carry) {
|
|
5581
|
+
chars.unshift("A");
|
|
5582
|
+
}
|
|
5583
|
+
return chars.join("");
|
|
5584
|
+
}
|
|
5585
|
+
|
|
5586
|
+
export { EarTag, Studio, StudioHeaders, types as StudioTypes, createAppManifest, Studio as default, lotComparator, nextLotNumber, sortByLotNumber };
|
|
5216
5587
|
//# sourceMappingURL=index.esm.js.map
|