oneentry 1.0.154 → 1.0.156
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/README.md +21 -0
- package/changelog.md +86 -1
- package/dist/attribute-sets/attributeSetsInterfaces.d.ts +0 -9
- package/dist/attribute-sets/attributeSetsSchemas.d.ts +0 -4
- package/dist/attribute-sets/attributeSetsSchemas.js +0 -2
- package/dist/base/stateModule.d.ts +1 -0
- package/dist/base/stateModule.js +3 -0
- package/dist/base/syncModules.d.ts +34 -109
- package/dist/base/syncModules.js +43 -276
- package/dist/base/timeIntervals.d.ts +95 -0
- package/dist/base/timeIntervals.js +321 -0
- package/dist/base/utils.d.ts +65 -5
- package/dist/base/validation.js +0 -1
- package/dist/blocks/blocksApi.js +11 -1
- package/dist/forms/formsInterfaces.d.ts +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +6 -0
- package/dist/pages/pagesApi.js +11 -0
- package/dist/templates-preview/templatesPreviewInterfaces.d.ts +1 -3
- package/dist/templates-preview/templatesPreviewSchemas.d.ts +0 -2
- package/dist/templates-preview/templatesPreviewSchemas.js +0 -1
- package/package.json +1 -1
- package/dist/base/result.d.ts +0 -39
- package/dist/base/result.js +0 -154
package/dist/base/syncModules.js
CHANGED
|
@@ -286,253 +286,6 @@ class SyncModules {
|
|
|
286
286
|
return data;
|
|
287
287
|
}
|
|
288
288
|
}
|
|
289
|
-
/**
|
|
290
|
-
* Adds a specified number of days to a date.
|
|
291
|
-
* @param {Date} date - The initial date.
|
|
292
|
-
* @param {number} days - The number of days to add.
|
|
293
|
-
* @returns {any} The new date with added days.
|
|
294
|
-
*/
|
|
295
|
-
_addDays(date, days) {
|
|
296
|
-
const result = new Date(date);
|
|
297
|
-
result.setUTCDate(result.getUTCDate() + days);
|
|
298
|
-
return result;
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Common logic for processing schedule dates (weekly, monthly, or both).
|
|
302
|
-
*
|
|
303
|
-
* Abstracts date iteration for three scheduling modes:
|
|
304
|
-
*
|
|
305
|
-
* - **`inEveryWeek` only**: starting from the start date, generates dates
|
|
306
|
-
* with a 7-day step until the end of the current month.
|
|
307
|
-
*
|
|
308
|
-
* - **`inEveryMonth` only**: pins the day-of-month from the start date
|
|
309
|
-
* and repeats it for each of the next 12 months. If the month does not
|
|
310
|
-
* have that day (e.g. Feb 31), the iteration is skipped.
|
|
311
|
-
*
|
|
312
|
-
* - **`inEveryWeek` + `inEveryMonth`**: for each of the next 12 months finds
|
|
313
|
-
* the first occurrence of the target weekday (from the start date), then
|
|
314
|
-
* iterates all occurrences of that weekday in the month with a 7-day step.
|
|
315
|
-
*
|
|
316
|
-
* `processDate(currentDate)` is called for every resolved date.
|
|
317
|
-
* @param {Date} date - The date for which to process intervals.
|
|
318
|
-
* @param {object} config - Configuration for schedule repetition.
|
|
319
|
-
* @param {boolean} config.inEveryWeek - Whether to repeat weekly.
|
|
320
|
-
* @param {boolean} config.inEveryMonth - Whether to repeat monthly.
|
|
321
|
-
* @param {(currentDate: Date) => void} processDate - Callback function to process each date.
|
|
322
|
-
*/
|
|
323
|
-
_processScheduleDates(date, config, processDate) {
|
|
324
|
-
// Handle weekly schedules
|
|
325
|
-
if (config.inEveryWeek && !config.inEveryMonth) {
|
|
326
|
-
let currentDate = new Date(date);
|
|
327
|
-
// Calculate the last day of the current month
|
|
328
|
-
const endOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0);
|
|
329
|
-
while (currentDate <= endOfMonth) {
|
|
330
|
-
processDate(currentDate);
|
|
331
|
-
// Move to the next week
|
|
332
|
-
currentDate = this._addDays(currentDate, 7);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
// Handle monthly schedules
|
|
336
|
-
if (config.inEveryMonth && !config.inEveryWeek) {
|
|
337
|
-
const startDate = new Date(date);
|
|
338
|
-
const targetDayOfMonth = startDate.getUTCDate();
|
|
339
|
-
const numberOfMonths = 12;
|
|
340
|
-
for (let i = 0; i < numberOfMonths; i++) {
|
|
341
|
-
const currentDate = new Date(startDate);
|
|
342
|
-
currentDate.setUTCMonth(currentDate.getUTCMonth() + i);
|
|
343
|
-
// Try setting the current date to the target day of the month
|
|
344
|
-
currentDate.setUTCDate(targetDayOfMonth);
|
|
345
|
-
// Check if we have exceeded the month
|
|
346
|
-
if (currentDate.getUTCMonth() !== (startDate.getUTCMonth() + i) % 12) {
|
|
347
|
-
continue; // Skip this month if exceeded
|
|
348
|
-
}
|
|
349
|
-
processDate(currentDate);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
// Handle both weekly and monthly schedules
|
|
353
|
-
if (config.inEveryMonth && config.inEveryWeek) {
|
|
354
|
-
const startDate = new Date(date);
|
|
355
|
-
const targetDayOfWeek = startDate.getUTCDay();
|
|
356
|
-
const numberOfMonths = 12;
|
|
357
|
-
for (let i = 0; i < numberOfMonths; i++) {
|
|
358
|
-
const currentDate = new Date(startDate);
|
|
359
|
-
currentDate.setUTCMonth(currentDate.getUTCMonth() + i);
|
|
360
|
-
// Set to the first day of the month
|
|
361
|
-
currentDate.setUTCDate(1);
|
|
362
|
-
// Find the first target day of the week in the current month
|
|
363
|
-
const daysUntilTargetDay = (targetDayOfWeek - currentDate.getUTCDay() + 7) % 7;
|
|
364
|
-
currentDate.setUTCDate(currentDate.getUTCDate() + daysUntilTargetDay);
|
|
365
|
-
// Iterate over all target days of the week in the current month
|
|
366
|
-
while (currentDate.getUTCMonth() ===
|
|
367
|
-
(startDate.getUTCMonth() + i) % 12) {
|
|
368
|
-
processDate(currentDate);
|
|
369
|
-
// Move to the next week (same day of the week)
|
|
370
|
-
currentDate.setUTCDate(currentDate.getUTCDate() + 7);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Generates intervals for a specific date based on a schedule.
|
|
377
|
-
*
|
|
378
|
-
* For each date resolved by `_processScheduleDates`, iterates over
|
|
379
|
-
* the `schedule.times` array of time ranges. Each range is a pair
|
|
380
|
-
* `[startTime, endTime]` with `{ hours, minutes }` fields.
|
|
381
|
-
* Creates an ISO interval `[start.toISOString(), end.toISOString()]`
|
|
382
|
-
* and adds it to `utcIntervals` (Set deduplicates automatically).
|
|
383
|
-
* @param {Date} date - The date for which to generate intervals.
|
|
384
|
-
* @param {object} schedule - The schedule defining the intervals.
|
|
385
|
-
* @param {boolean} schedule.inEveryWeek - The number of weeks between intervals.
|
|
386
|
-
* @param {any[]} schedule.times - The times for each interval.
|
|
387
|
-
* @param {boolean} schedule.inEveryMonth - The month intervals for each interval.
|
|
388
|
-
* @param {Set<Array<string>>} utcIntervals - A set to store unique intervals.
|
|
389
|
-
*/
|
|
390
|
-
_generateIntervalsForDate(date, schedule, utcIntervals) {
|
|
391
|
-
this._processScheduleDates(date, schedule, (currentDate) => {
|
|
392
|
-
schedule.times.forEach((timeRange) => {
|
|
393
|
-
const [startTime, endTime] = timeRange;
|
|
394
|
-
const intervalStart = new Date(currentDate);
|
|
395
|
-
intervalStart.setUTCHours(startTime.hours, startTime.minutes, 0, 0);
|
|
396
|
-
const intervalEnd = new Date(currentDate);
|
|
397
|
-
intervalEnd.setUTCHours(endTime.hours, endTime.minutes, 0, 0);
|
|
398
|
-
utcIntervals.add([
|
|
399
|
-
intervalStart.toISOString(),
|
|
400
|
-
intervalEnd.toISOString(),
|
|
401
|
-
]);
|
|
402
|
-
});
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* Adds time intervals to schedules.
|
|
407
|
-
*
|
|
408
|
-
* Accepts an array of schedule groups (structure of `timeInterval` attributes
|
|
409
|
-
* for pages/products). For each group iterates over `values` — the set of
|
|
410
|
-
* concrete schedules. Each schedule contains a date range `dates[0..1]`.
|
|
411
|
-
*
|
|
412
|
-
* If both boundaries are equal (`isSameDay`), intervals are generated only
|
|
413
|
-
* for that single date. Otherwise — for every day in the range inclusive.
|
|
414
|
-
*
|
|
415
|
-
* The result (`schedule.timeIntervals`) is a sorted array of ISO pairs,
|
|
416
|
-
* ready to pass to UI components.
|
|
417
|
-
* @param {any[]} schedules - The schedules to process.
|
|
418
|
-
* @returns {any} Schedules with added time intervals.
|
|
419
|
-
*/
|
|
420
|
-
_addTimeIntervalsToSchedules(schedules) {
|
|
421
|
-
schedules === null || schedules === void 0 ? void 0 : schedules.forEach((scheduleGroup) => {
|
|
422
|
-
// Skip if scheduleGroup.values is not an array
|
|
423
|
-
if (!scheduleGroup ||
|
|
424
|
-
!scheduleGroup.values ||
|
|
425
|
-
!Array.isArray(scheduleGroup.values)) {
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
scheduleGroup.values.forEach((schedule) => {
|
|
429
|
-
const utcIntervals = new Set();
|
|
430
|
-
const startDate = new Date(schedule.dates[0]);
|
|
431
|
-
const endDate = new Date(schedule.dates[1]);
|
|
432
|
-
const isSameDay = startDate.toISOString() === endDate.toISOString();
|
|
433
|
-
if (isSameDay) {
|
|
434
|
-
this._generateIntervalsForDate(startDate, schedule, utcIntervals);
|
|
435
|
-
}
|
|
436
|
-
else {
|
|
437
|
-
for (let currentDate = new Date(startDate); currentDate <= endDate; currentDate = this._addDays(currentDate, 1)) {
|
|
438
|
-
this._generateIntervalsForDate(currentDate, schedule, utcIntervals);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
schedule.timeIntervals = Array.from(utcIntervals).sort();
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
return schedules;
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* Generates intervals for a specific date for form schedules.
|
|
448
|
-
*
|
|
449
|
-
* Unlike `_generateIntervalsForDate`, time ranges here have a different shape:
|
|
450
|
-
* each `timeInterval` contains `start`, `end` and `period`
|
|
451
|
-
* (slot length in minutes). The method slices the [start, end) window into
|
|
452
|
-
* fixed-length slots of `period` minutes:
|
|
453
|
-
*
|
|
454
|
-
* start=09:00, end=12:00, period=30 → [09:00–09:30], [09:30–10:00], …, [11:30–12:00]
|
|
455
|
-
*
|
|
456
|
-
* Generation stops if the next slot would exceed `end`.
|
|
457
|
-
* Each slot is added to `utcIntervals` (Set deduplicates automatically).
|
|
458
|
-
* @param {Date} date - The date for which to generate intervals.
|
|
459
|
-
* @param {object} interval - The interval configuration.
|
|
460
|
-
* @param {boolean} interval.inEveryWeek - Indicates whether the schedule is weekly.
|
|
461
|
-
* @param {boolean} interval.inEveryMonth - Indicates whether the schedule is monthly.
|
|
462
|
-
* @param {any[]} timeIntervals - The time intervals to process.
|
|
463
|
-
* @param {Set<Array<string>>} utcIntervals - A set to store unique intervals.
|
|
464
|
-
*/
|
|
465
|
-
_generateIntervalsForFormDate(date, interval, timeIntervals, utcIntervals) {
|
|
466
|
-
const generateTimeSlotsForDate = (currentDate) => {
|
|
467
|
-
timeIntervals.forEach((timeInterval) => {
|
|
468
|
-
let currentStart = timeInterval.start;
|
|
469
|
-
const endTime = timeInterval.end;
|
|
470
|
-
// Slice the window into slots of `period` minutes each.
|
|
471
|
-
while (currentStart.hours < endTime.hours ||
|
|
472
|
-
(currentStart.hours === endTime.hours &&
|
|
473
|
-
currentStart.minutes < endTime.minutes)) {
|
|
474
|
-
const intervalStart = new Date(currentDate);
|
|
475
|
-
intervalStart.setUTCHours(currentStart.hours, currentStart.minutes, 0, 0);
|
|
476
|
-
// Compute slot end: add period minutes with hour carry normalization.
|
|
477
|
-
const nextMinutes = currentStart.minutes + timeInterval.period;
|
|
478
|
-
const nextHours = currentStart.hours + Math.floor(nextMinutes / 60);
|
|
479
|
-
const minutes = nextMinutes % 60;
|
|
480
|
-
// If the slot end exceeds `end` — stop; partial slots are not emitted.
|
|
481
|
-
if (nextHours > endTime.hours ||
|
|
482
|
-
(nextHours === endTime.hours && minutes > endTime.minutes)) {
|
|
483
|
-
break;
|
|
484
|
-
}
|
|
485
|
-
const intervalEnd = new Date(currentDate);
|
|
486
|
-
intervalEnd.setUTCHours(nextHours, minutes, 0, 0);
|
|
487
|
-
utcIntervals.add([
|
|
488
|
-
intervalStart.toISOString(),
|
|
489
|
-
intervalEnd.toISOString(),
|
|
490
|
-
]);
|
|
491
|
-
currentStart = { hours: nextHours, minutes };
|
|
492
|
-
}
|
|
493
|
-
});
|
|
494
|
-
};
|
|
495
|
-
this._processScheduleDates(date, interval, generateTimeSlotsForDate);
|
|
496
|
-
}
|
|
497
|
-
/**
|
|
498
|
-
* Adds time intervals to form schedules (different structure).
|
|
499
|
-
*
|
|
500
|
-
* Same as `_addTimeIntervalsToSchedules` but for `timeInterval` attributes
|
|
501
|
-
* in **forms** (different API data structure):
|
|
502
|
-
* - `interval.range[0..1]` instead of `schedule.dates[0..1]`
|
|
503
|
-
* - `interval.intervals` — array of time ranges with slots (`period`)
|
|
504
|
-
* instead of `[startTime, endTime]` pairs
|
|
505
|
-
*
|
|
506
|
-
* Result is written to `interval.timeIntervals`.
|
|
507
|
-
* @param {any[]} intervals - The intervals to process.
|
|
508
|
-
* @returns {any} Intervals with added time intervals.
|
|
509
|
-
*/
|
|
510
|
-
_addTimeIntervalsToFormSchedules(intervals) {
|
|
511
|
-
intervals.forEach((interval) => {
|
|
512
|
-
var _a, _b;
|
|
513
|
-
if (!interval.intervals || !Array.isArray(interval.intervals)) {
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
const utcIntervals = new Set();
|
|
517
|
-
const startDate = new Date(interval.range[0]);
|
|
518
|
-
const endDate = new Date(interval.range[1]);
|
|
519
|
-
const isSameDay = startDate.toISOString() === endDate.toISOString();
|
|
520
|
-
const intervalConfig = {
|
|
521
|
-
inEveryWeek: (_a = interval.inEveryWeek) !== null && _a !== void 0 ? _a : false,
|
|
522
|
-
inEveryMonth: (_b = interval.inEveryMonth) !== null && _b !== void 0 ? _b : false,
|
|
523
|
-
};
|
|
524
|
-
if (isSameDay) {
|
|
525
|
-
this._generateIntervalsForFormDate(startDate, intervalConfig, interval.intervals, utcIntervals);
|
|
526
|
-
}
|
|
527
|
-
else {
|
|
528
|
-
for (let currentDate = new Date(startDate); currentDate <= endDate; currentDate = this._addDays(currentDate, 1)) {
|
|
529
|
-
this._generateIntervalsForFormDate(currentDate, intervalConfig, interval.intervals, utcIntervals);
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
interval.timeIntervals = Array.from(utcIntervals).sort();
|
|
533
|
-
});
|
|
534
|
-
return intervals;
|
|
535
|
-
}
|
|
536
289
|
/**
|
|
537
290
|
* Transforms additionalFields from array to object keyed by marker.
|
|
538
291
|
*
|
|
@@ -557,16 +310,20 @@ class SyncModules {
|
|
|
557
310
|
* Contains an object `{ marker: AttrObject }`. For each attribute:
|
|
558
311
|
* - `_normalizeAdditionalFields` is called;
|
|
559
312
|
* - numeric types (`integer`, `float`) are cast to a JS number (or `null`);
|
|
560
|
-
* - `timeInterval` attributes are enriched with computed `timeIntervals`;
|
|
561
313
|
* - the whole object is re-sorted by `position`.
|
|
562
314
|
*
|
|
563
315
|
* **2. `attributes`** — form attributes (different API structure).
|
|
564
|
-
* Same `additionalFields`
|
|
316
|
+
* Same `additionalFields` processing,
|
|
565
317
|
* but numbers are not normalized here (commented out — logic differs).
|
|
566
318
|
*
|
|
567
319
|
* **3. `type`** — a single attribute from an attribute set.
|
|
568
320
|
* Same transformations as in case 1, but without sorting.
|
|
569
321
|
*
|
|
322
|
+
* `timeInterval` attributes are left exactly as the API returned them — a
|
|
323
|
+
* compact recurrence rule. Resolving one into concrete slots is the caller's
|
|
324
|
+
* job, via `expandTimeIntervals`: the rule is open-ended, so only the caller
|
|
325
|
+
* knows how wide a window it needs.
|
|
326
|
+
*
|
|
570
327
|
* If none of the keys are found — data is returned unchanged.
|
|
571
328
|
* @param {any} data - The data to normalize.
|
|
572
329
|
* @returns {any} Normalized attributes.
|
|
@@ -582,15 +339,6 @@ class SyncModules {
|
|
|
582
339
|
const numValue = Number(d.value);
|
|
583
340
|
d.value = isNaN(numValue) ? null : numValue;
|
|
584
341
|
}
|
|
585
|
-
// add timeIntervals
|
|
586
|
-
if (data.attributeValues[attr].type === 'timeInterval') {
|
|
587
|
-
const schedules = data.attributeValues[attr].value;
|
|
588
|
-
// console.log('Schedules: ', JSON.stringify(schedules));
|
|
589
|
-
if (Array.isArray(schedules) && schedules.length > 0) {
|
|
590
|
-
const result = this._addTimeIntervalsToSchedules(schedules);
|
|
591
|
-
data.attributeValues[attr].value = result;
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
342
|
});
|
|
595
343
|
return {
|
|
596
344
|
...data,
|
|
@@ -608,22 +356,12 @@ class SyncModules {
|
|
|
608
356
|
if ('attributes' in data) {
|
|
609
357
|
const d = data.attributes;
|
|
610
358
|
Object.keys(d).forEach((attr) => {
|
|
611
|
-
var _a;
|
|
612
359
|
this._normalizeAdditionalFields(d[attr]);
|
|
613
360
|
for (const field of booleanFields) {
|
|
614
361
|
if (field in d[attr] && d[attr][field] === null) {
|
|
615
362
|
d[attr][field] = false;
|
|
616
363
|
}
|
|
617
364
|
}
|
|
618
|
-
// Add time intervals
|
|
619
|
-
if (d[attr].type === 'timeInterval') {
|
|
620
|
-
const intervals = (_a = d[attr].localizeInfos) === null || _a === void 0 ? void 0 : _a.intervals;
|
|
621
|
-
// console.log('Schedules:: ', JSON.stringify(intervals));
|
|
622
|
-
if (intervals && Array.isArray(intervals) && intervals.length > 0) {
|
|
623
|
-
const result = this._addTimeIntervalsToFormSchedules(intervals);
|
|
624
|
-
d[attr].localizeInfos.intervals = result;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
365
|
});
|
|
628
366
|
return data;
|
|
629
367
|
}
|
|
@@ -640,14 +378,6 @@ class SyncModules {
|
|
|
640
378
|
const numValue = Number(data.value);
|
|
641
379
|
data.value = isNaN(numValue) ? null : numValue;
|
|
642
380
|
}
|
|
643
|
-
// Add time intervals
|
|
644
|
-
if (data.type === 'timeInterval') {
|
|
645
|
-
const schedules = data.value;
|
|
646
|
-
if (Array.isArray(schedules) && schedules.length > 0) {
|
|
647
|
-
const result = this._addTimeIntervalsToSchedules(schedules);
|
|
648
|
-
data.value = result;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
381
|
}
|
|
652
382
|
return data;
|
|
653
383
|
}
|
|
@@ -698,6 +428,35 @@ class SyncModules {
|
|
|
698
428
|
this.state.guestId = guestId || undefined;
|
|
699
429
|
return this;
|
|
700
430
|
}
|
|
431
|
+
/**
|
|
432
|
+
* Sets the device-metadata override in the state.
|
|
433
|
+
*
|
|
434
|
+
* Once set, the string is sent as the `x-device-metadata` header on POST
|
|
435
|
+
* requests and token refresh instead of the environment-derived fingerprint.
|
|
436
|
+
* The API binds refresh tokens to this header, so server-side flows that issue
|
|
437
|
+
* tokens on behalf of a browser (e.g. an OAuth code exchange) must set the
|
|
438
|
+
* browser's string (obtained there via `getDeviceMetadata`). Pass an empty
|
|
439
|
+
* string to clear the override and fall back to the computed fingerprint.
|
|
440
|
+
* @param {string} deviceMetadata - The metadata string to send (empty string clears the override).
|
|
441
|
+
* @returns {any} The instance of SyncModules for chaining.
|
|
442
|
+
*/
|
|
443
|
+
setDeviceMetadata(deviceMetadata) {
|
|
444
|
+
this.state.deviceMetadata = deviceMetadata || undefined;
|
|
445
|
+
return this;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Returns the device-metadata string the SDK sends as the `x-device-metadata` header.
|
|
449
|
+
*
|
|
450
|
+
* Public counterpart of `_getDeviceMetadata`: an explicit override (config or
|
|
451
|
+
* `setDeviceMetadata`) wins, otherwise the environment-derived fingerprint is
|
|
452
|
+
* computed. Use it in the browser to obtain the string that a server-side
|
|
453
|
+
* token-issuing flow (OAuth code exchange) must forward, so the issued refresh
|
|
454
|
+
* token stays refreshable from this browser.
|
|
455
|
+
* @returns {string} The metadata string sent with requests from this instance.
|
|
456
|
+
*/
|
|
457
|
+
getDeviceMetadata() {
|
|
458
|
+
return this._getDeviceMetadata();
|
|
459
|
+
}
|
|
701
460
|
/**
|
|
702
461
|
* Get deviceMetadata
|
|
703
462
|
*
|
|
@@ -724,10 +483,18 @@ class SyncModules {
|
|
|
724
483
|
* lives until the process restarts.
|
|
725
484
|
*
|
|
726
485
|
* In a Node.js environment (no `window`) returns a simplified object without screen/navigator.
|
|
486
|
+
*
|
|
487
|
+
* An explicitly provided string (`deviceMetadata` in config or `setDeviceMetadata`)
|
|
488
|
+
* takes precedence over the environment-derived fingerprint — this lets a server
|
|
489
|
+
* issue tokens bound to the browser's fingerprint (see `IConfig.deviceMetadata`).
|
|
727
490
|
* @returns {string} - Returns an object containing device metadata.
|
|
728
491
|
*/
|
|
729
492
|
_getDeviceMetadata() {
|
|
730
493
|
var _a;
|
|
494
|
+
// Explicit override wins: the API binds refresh tokens to this header, so
|
|
495
|
+
// server-side token issuance must be able to stamp the browser's string.
|
|
496
|
+
if (this.state.deviceMetadata)
|
|
497
|
+
return this.state.deviceMetadata;
|
|
731
498
|
// Check if we're in a browser environment
|
|
732
499
|
if (typeof globalThis === 'undefined') {
|
|
733
500
|
return '';
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { IAttributeValue, ITimeIntervalAttributeValue, ITimeIntervalEntitySchedule, ITimeIntervalSchedule, ITimeIntervalWindow, TimeIntervalPair } from './utils';
|
|
2
|
+
/**
|
|
3
|
+
* Expands a `timeInterval` schedule into concrete UTC slots for a given window.
|
|
4
|
+
*
|
|
5
|
+
* A schedule as returned by the API is a compact **recurrence rule** — an
|
|
6
|
+
* anchor date plus daily time ranges plus repeat flags — not a list of slots.
|
|
7
|
+
* Materializing it wholesale is what makes `timeInterval` attributes expensive
|
|
8
|
+
* (a year of half-hour slots runs to megabytes), so expansion is on demand and
|
|
9
|
+
* the window is required: only the caller knows how far it needs to resolve.
|
|
10
|
+
*
|
|
11
|
+
* Both schedule shapes the API returns are accepted:
|
|
12
|
+
* - **entity** — `attributeValues[marker].value[].values[]` on pages, products,
|
|
13
|
+
* blocks and attribute sets: a `dates` range with `times` pairs;
|
|
14
|
+
* - **form** — `attributes[marker].localizeInfos.intervals[]`: a `range` with
|
|
15
|
+
* `intervals` that carry a slot `period` in minutes.
|
|
16
|
+
*
|
|
17
|
+
* Semantics:
|
|
18
|
+
* - `dates[0]` / `range[0]` is both the recurrence phase and the first valid
|
|
19
|
+
* day — nothing earlier is emitted, however wide the window;
|
|
20
|
+
* - `dates[1]` / `range[1]` ends validity; when it does not extend past the
|
|
21
|
+
* start, the schedule is anchored to that day — with a recurrence flag set,
|
|
22
|
+
* recurrence is then open-ended and the window alone bounds the result;
|
|
23
|
+
* - `inEveryWeek` repeats every 7 days from the anchor; `inEveryMonth` repeats
|
|
24
|
+
* on the same day-of-month, skipping months that are too short; with both set
|
|
25
|
+
* the weekly rule applies, which is what it has always meant in practice;
|
|
26
|
+
* - with neither flag the schedule is a plain date range — every day of it;
|
|
27
|
+
* - the result is deduplicated and sorted by start, then end.
|
|
28
|
+
* @param {ITimeIntervalEntitySchedule | ITimeIntervalSchedule} schedule - A single schedule entry from a `timeInterval` attribute.
|
|
29
|
+
* @param {ITimeIntervalWindow} window - Inclusive `{ from, to }` range to resolve, compared at UTC day granularity.
|
|
30
|
+
* @returns {TimeIntervalPair[]} Sorted, deduplicated `[start, end]` ISO pairs; empty when the schedule is malformed or does not overlap the window.
|
|
31
|
+
* To expand a whole attribute at once, prefer {@link expandAttributeTimeIntervals}
|
|
32
|
+
* — it walks the groups and merges the results for you. Reach for this function
|
|
33
|
+
* directly when you already hold a single schedule, e.g. a form's
|
|
34
|
+
* `localizeInfos.intervals[]`.
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* import { expandTimeIntervals } from 'oneentry';
|
|
38
|
+
*
|
|
39
|
+
* // Form attributes are an array keyed by `marker`, and carry their schedules
|
|
40
|
+
* // already typed on `localizeInfos.intervals`.
|
|
41
|
+
* const field = form.attributes.find((a) => a.marker === 'booking');
|
|
42
|
+
*
|
|
43
|
+
* const slots = (field?.localizeInfos.intervals ?? []).flatMap((schedule) =>
|
|
44
|
+
* expandTimeIntervals(schedule, { from: '2025-05-01', to: '2025-05-31' }),
|
|
45
|
+
* );
|
|
46
|
+
* // [['2025-05-07T09:00:00.000Z', '2025-05-07T10:00:00.000Z'], …]
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function expandTimeIntervals(schedule: ITimeIntervalEntitySchedule | ITimeIntervalSchedule, window: ITimeIntervalWindow): TimeIntervalPair[];
|
|
50
|
+
/**
|
|
51
|
+
* Narrows an attribute value to a `timeInterval` attribute.
|
|
52
|
+
*
|
|
53
|
+
* `IAttributeValue.value` is `unknown` — its shape depends on `type` — so this
|
|
54
|
+
* guard is what lets you reach the schedules without a cast.
|
|
55
|
+
* @param {IAttributeValue | undefined} attr - The attribute value to test.
|
|
56
|
+
* @returns {boolean} True when the attribute is a `timeInterval` carrying an array of groups.
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* const attr = page.attributeValues.interval;
|
|
60
|
+
* if (isTimeIntervalAttribute(attr)) {
|
|
61
|
+
* attr.value[0].values[0].dates; // fully typed, no cast
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function isTimeIntervalAttribute(attr: IAttributeValue | undefined): attr is ITimeIntervalAttributeValue;
|
|
66
|
+
/**
|
|
67
|
+
* Expands a whole `timeInterval` attribute into concrete UTC slots for a window.
|
|
68
|
+
*
|
|
69
|
+
* The one-call path for the common case: it walks the attribute's groups and
|
|
70
|
+
* their schedules, expands each with {@link expandTimeIntervals}, and merges the
|
|
71
|
+
* results. Merging matters — deduplication and ordering only hold within a
|
|
72
|
+
* single schedule, so combining groups by hand can yield duplicate or unsorted
|
|
73
|
+
* slots.
|
|
74
|
+
*
|
|
75
|
+
* Anything that is not a `timeInterval` attribute yields an empty array, so this
|
|
76
|
+
* is safe to call on an arbitrary attribute without checking `type` first.
|
|
77
|
+
*
|
|
78
|
+
* For **form** attributes the schedules are already typed at
|
|
79
|
+
* `localizeInfos.intervals`, so no equivalent helper is needed — map over them
|
|
80
|
+
* and call {@link expandTimeIntervals} directly.
|
|
81
|
+
* @param {IAttributeValue | undefined} attr - A `timeInterval` attribute value, e.g. `page.attributeValues.interval`.
|
|
82
|
+
* @param {ITimeIntervalWindow} window - Inclusive `{ from, to }` range to resolve, compared at UTC day granularity.
|
|
83
|
+
* @returns {TimeIntervalPair[]} Sorted, deduplicated `[start, end]` ISO pairs across every group; empty when the attribute is not a `timeInterval`.
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* import { expandAttributeTimeIntervals } from 'oneentry';
|
|
87
|
+
*
|
|
88
|
+
* const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
|
|
89
|
+
* from: '2025-04-01',
|
|
90
|
+
* to: '2025-04-30',
|
|
91
|
+
* });
|
|
92
|
+
* // [['2025-04-14T09:00:00.000Z', '2025-04-14T10:00:00.000Z'], …]
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function expandAttributeTimeIntervals(attr: IAttributeValue | undefined, window: ITimeIntervalWindow): TimeIntervalPair[];
|