@xiboplayer/schedule 0.4.1 → 0.4.4
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/package.json +2 -2
- package/src/schedule.js +30 -0
- package/src/schedule.test.js +70 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xiboplayer/schedule",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Complete scheduling solution: campaigns, dayparting, interrupts, and overlays",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"./overlays": "./src/overlays.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@xiboplayer/utils": "0.4.
|
|
14
|
+
"@xiboplayer/utils": "0.4.4"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"vitest": "^2.0.0"
|
package/src/schedule.js
CHANGED
|
@@ -41,6 +41,36 @@ export class ScheduleManager {
|
|
|
41
41
|
return this.schedule?.dataConnectors || [];
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Get dependants map: layoutId → filenames that must be cached before that layout plays.
|
|
46
|
+
* Includes both per-layout and global dependants.
|
|
47
|
+
* Used by download manager to prioritize sub-playlist media alongside its parent layout.
|
|
48
|
+
* @returns {Map<number, string[]>} layoutId → dependant filenames
|
|
49
|
+
*/
|
|
50
|
+
getDependantsMap() {
|
|
51
|
+
const map = new Map();
|
|
52
|
+
if (!this.schedule) return map;
|
|
53
|
+
|
|
54
|
+
const globalDeps = this.schedule.dependants || [];
|
|
55
|
+
|
|
56
|
+
const addLayout = (layout) => {
|
|
57
|
+
const id = parseInt(String(layout.file || layout.id).replace('.xlf', ''), 10);
|
|
58
|
+
const deps = [...globalDeps, ...(layout.dependants || [])];
|
|
59
|
+
if (deps.length > 0) map.set(id, deps);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (this.schedule.layouts) {
|
|
63
|
+
for (const layout of this.schedule.layouts) addLayout(layout);
|
|
64
|
+
}
|
|
65
|
+
if (this.schedule.campaigns) {
|
|
66
|
+
for (const campaign of this.schedule.campaigns) {
|
|
67
|
+
for (const layout of campaign.layouts) addLayout(layout);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return map;
|
|
72
|
+
}
|
|
73
|
+
|
|
44
74
|
/**
|
|
45
75
|
* Check if a schedule item is active based on recurrence rules.
|
|
46
76
|
* Supports Week, Day, and Month recurrence types.
|
package/src/schedule.test.js
CHANGED
|
@@ -707,4 +707,74 @@ describe('ScheduleManager - Actions and Commands', () => {
|
|
|
707
707
|
expect(windowMs).toBeGreaterThanOrEqual(60 * 60 * 1000); // at least 1 hour
|
|
708
708
|
});
|
|
709
709
|
});
|
|
710
|
+
|
|
711
|
+
describe('getDependantsMap', () => {
|
|
712
|
+
it('should return empty map when no schedule', () => {
|
|
713
|
+
const map = manager.getDependantsMap();
|
|
714
|
+
expect(map.size).toBe(0);
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
it('should collect per-layout dependants from standalone layouts', () => {
|
|
718
|
+
manager.setSchedule({
|
|
719
|
+
layouts: [
|
|
720
|
+
{ file: '472.xlf', dependants: ['11.pdf', 'video.mp4'] },
|
|
721
|
+
{ file: '500.xlf', dependants: ['logo.png'] },
|
|
722
|
+
],
|
|
723
|
+
campaigns: [],
|
|
724
|
+
});
|
|
725
|
+
const map = manager.getDependantsMap();
|
|
726
|
+
expect(map.get(472)).toEqual(['11.pdf', 'video.mp4']);
|
|
727
|
+
expect(map.get(500)).toEqual(['logo.png']);
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
it('should collect per-layout dependants from campaign layouts', () => {
|
|
731
|
+
manager.setSchedule({
|
|
732
|
+
layouts: [],
|
|
733
|
+
campaigns: [
|
|
734
|
+
{
|
|
735
|
+
id: 'c1',
|
|
736
|
+
layouts: [
|
|
737
|
+
{ file: '300.xlf', dependants: ['font.woff2'] },
|
|
738
|
+
],
|
|
739
|
+
},
|
|
740
|
+
],
|
|
741
|
+
});
|
|
742
|
+
const map = manager.getDependantsMap();
|
|
743
|
+
expect(map.get(300)).toEqual(['font.woff2']);
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
it('should merge global dependants with per-layout dependants', () => {
|
|
747
|
+
manager.setSchedule({
|
|
748
|
+
dependants: ['global-font.woff2'],
|
|
749
|
+
layouts: [
|
|
750
|
+
{ file: '472.xlf', dependants: ['11.pdf'] },
|
|
751
|
+
],
|
|
752
|
+
campaigns: [],
|
|
753
|
+
});
|
|
754
|
+
const map = manager.getDependantsMap();
|
|
755
|
+
expect(map.get(472)).toEqual(['global-font.woff2', '11.pdf']);
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
it('should skip layouts with no dependants', () => {
|
|
759
|
+
manager.setSchedule({
|
|
760
|
+
layouts: [
|
|
761
|
+
{ file: '100.xlf', dependants: [] },
|
|
762
|
+
{ file: '200.xlf', dependants: ['bg.jpg'] },
|
|
763
|
+
],
|
|
764
|
+
campaigns: [],
|
|
765
|
+
});
|
|
766
|
+
const map = manager.getDependantsMap();
|
|
767
|
+
expect(map.has(100)).toBe(false);
|
|
768
|
+
expect(map.get(200)).toEqual(['bg.jpg']);
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
it('should handle file IDs without .xlf extension', () => {
|
|
772
|
+
manager.setSchedule({
|
|
773
|
+
layouts: [{ file: '472', dependants: ['11.pdf'] }],
|
|
774
|
+
campaigns: [],
|
|
775
|
+
});
|
|
776
|
+
const map = manager.getDependantsMap();
|
|
777
|
+
expect(map.get(472)).toEqual(['11.pdf']);
|
|
778
|
+
});
|
|
779
|
+
});
|
|
710
780
|
});
|