@xiboplayer/pwa 0.7.15 → 0.7.16

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.
Files changed (48) hide show
  1. package/dist/assets/chunk-7ZXdHUL4.js +1 -0
  2. package/dist/assets/html2canvas-Cjd84h1M.js +6 -0
  3. package/dist/assets/{html2canvas-C3_jqeKW.js.map → html2canvas-Cjd84h1M.js.map} +1 -1
  4. package/dist/assets/main-BxyDlH8x.js +108 -0
  5. package/dist/assets/main-BxyDlH8x.js.map +1 -0
  6. package/dist/assets/main-DpLXt_A1.js +3 -0
  7. package/dist/assets/main-DpLXt_A1.js.map +1 -0
  8. package/dist/assets/{pdf-BL2XXCfX.js → pdf-CfAvK6QT.js} +2 -2
  9. package/dist/assets/{pdf-BL2XXCfX.js.map → pdf-CfAvK6QT.js.map} +1 -1
  10. package/dist/assets/{setup-cquLiEJA.js → setup-Dr31Tx8X.js} +2 -2
  11. package/dist/assets/{setup-cquLiEJA.js.map → setup-Dr31Tx8X.js.map} +1 -1
  12. package/dist/assets/{src-CMBYiOs4.js → src-B-j3XW3-.js} +3 -3
  13. package/dist/assets/{src-CMBYiOs4.js.map → src-B-j3XW3-.js.map} +1 -1
  14. package/dist/assets/{src-DCHcQ-Z7.js → src-BCLLyeh_.js} +3 -3
  15. package/dist/assets/{src-DCHcQ-Z7.js.map → src-BCLLyeh_.js.map} +1 -1
  16. package/dist/assets/src-BSReyr0v.js +2 -0
  17. package/dist/assets/{src-DPOUYQMT.js.map → src-BSReyr0v.js.map} +1 -1
  18. package/dist/assets/src-D8PF0mN4.js +2 -0
  19. package/dist/assets/{src-Dfm-7Za-.js.map → src-D8PF0mN4.js.map} +1 -1
  20. package/dist/assets/{src-WWbeHES3.js → src-DAN2Deef.js} +2 -2
  21. package/dist/assets/{src-WWbeHES3.js.map → src-DAN2Deef.js.map} +1 -1
  22. package/dist/assets/src-DlR7dlm-.js +3 -0
  23. package/dist/assets/src-DlR7dlm-.js.map +1 -0
  24. package/dist/assets/{src-Br0nlcJt.js → src-Kaan1uxV.js} +2 -2
  25. package/dist/assets/{src-Br0nlcJt.js.map → src-Kaan1uxV.js.map} +1 -1
  26. package/dist/assets/src-Xntm4zXY.js +629 -0
  27. package/dist/assets/src-Xntm4zXY.js.map +1 -0
  28. package/dist/assets/src-bWHpkXu3.js +16 -0
  29. package/dist/assets/{src-DpE7HVLC.js.map → src-bWHpkXu3.js.map} +1 -1
  30. package/dist/assets/{src-D7r8nqnZ.js → src-vZDSh8Wj.js} +2 -2
  31. package/dist/assets/{src-D7r8nqnZ.js.map → src-vZDSh8Wj.js.map} +1 -1
  32. package/dist/assets/{sync-manager-C_rxYFpb.js → sync-manager-D6eMk5NM.js} +2 -2
  33. package/dist/assets/{sync-manager-C_rxYFpb.js.map → sync-manager-D6eMk5NM.js.map} +1 -1
  34. package/dist/index.html +6 -7
  35. package/dist/setup.html +5 -7
  36. package/dist/sw-pwa.js +2 -2
  37. package/dist/sw-pwa.js.map +1 -1
  38. package/package.json +13 -13
  39. package/dist/assets/html2canvas-C3_jqeKW.js +0 -6
  40. package/dist/assets/main-C-Rkfq5h.js +0 -735
  41. package/dist/assets/main-C-Rkfq5h.js.map +0 -1
  42. package/dist/assets/src-BfPGb2rS.js +0 -1
  43. package/dist/assets/src-DPOUYQMT.js +0 -2
  44. package/dist/assets/src-Dfm-7Za-.js +0 -2
  45. package/dist/assets/src-Dfnol-_C.js +0 -1
  46. package/dist/assets/src-DpE7HVLC.js +0 -16
  47. package/dist/assets/src-jHYXY4sl.js +0 -1
  48. /package/dist/assets/{modulepreload-polyfill-wMinxHhO.js → modulepreload-polyfill-Cf3xff8G.js} +0 -0
@@ -1 +0,0 @@
1
- import{C as e,S as t,_ as n,a as r,b as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y,v as b,w as x,x as S,y as C}from"./src-CMBYiOs4.js";export{u as CmsApiClient,r as CmsApiError,l as EventEmitter,c as LOG_LEVELS,v as PLAYER_API,_ as SHELL_ONLY_KEYS,p as VERSION,n as applyCmsLogLevel,a as computeCmsId,d as config,b as createLogger,s as deleteByIds,y as extractPwaConfig,m as fetchWithRetry,C as getLogLevel,i as isDebug,S as mapCmsLogLevel,h as openIDB,f as queryByIndex,t as registerLogSink,e as setLogLevel,g as setPlayerApi,x as unregisterLogSink,o as warnPlatformMismatch};
@@ -1,2 +0,0 @@
1
- import{v as e}from"./src-CMBYiOs4.js";var t={name:`@xiboplayer/schedule`,version:`0.7.15`,description:`Complete scheduling solution: campaigns, dayparting, interrupts, and overlays`,type:`module`,main:`./src/index.js`,types:`./src/index.d.ts`,exports:{".":`./src/index.js`,"./schedule":`./src/schedule.js`,"./interrupts":`./src/interrupts.js`,"./overlays":`./src/overlays.js`},scripts:{test:`vitest run`,"test:watch":`vitest`,"test:coverage":`vitest run --coverage`},dependencies:{"@xiboplayer/utils":`workspace:*`},devDependencies:{vitest:`^4.1.2`},keywords:[`xibo`,`digital-signage`,`scheduling`,`dayparting`,`campaigns`,`interrupts`,`overlays`,`shareOfVoice`],author:`Pau Aliagas <linuxnow@gmail.com>`,license:`AGPL-3.0-or-later`,repository:{type:`git`,url:`git+https://github.com/xibo-players/xiboplayer.git`,directory:`packages/schedule`},homepage:`https://xiboplayer.org`},n=e(`schedule:criteria`),r=[`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`,`Saturday`],i={weatherTemp:`temperature`,weatherHumidity:`humidity`,weatherWindSpeed:`windSpeed`,weatherCondition:`condition`,weatherCloudCover:`cloudCover`};function a(e,t,a={},o={}){switch(e){case`dayOfWeek`:return r[t.getDay()];case`dayOfMonth`:return String(t.getDate());case`month`:return String(t.getMonth()+1);case`hour`:return String(t.getHours());case`isoDay`:return String(t.getDay()===0?7:t.getDay());default:if(i[e]){let t=i[e];return o[t]===void 0?(n.debug(`Weather metric "${e}" requested but no weather data available`),null):String(o[t])}return a[e]===void 0?(n.debug(`Unknown metric: ${e}`),null):String(a[e])}}function o(e,t,r,i){if(e===null)return!1;if(i===`number`){let n=parseFloat(e),i=parseFloat(r);if(isNaN(n)||isNaN(i))return!1;switch(t){case`equals`:return n===i;case`notEquals`:return n!==i;case`greaterThan`:return n>i;case`greaterThanOrEquals`:return n>=i;case`lessThan`:return n<i;case`lessThanOrEquals`:return n<=i;default:return!1}}let a=e.toLowerCase(),o=r.toLowerCase();switch(t){case`equals`:return a===o;case`notEquals`:return a!==o;case`contains`:return a.includes(o);case`notContains`:return!a.includes(o);case`startsWith`:return a.startsWith(o);case`endsWith`:return a.endsWith(o);case`in`:return o.split(`,`).map(e=>e.trim().toLowerCase()).includes(a);case`greaterThan`:return a>o;case`lessThan`:return a<o;default:return n.debug(`Unknown condition: ${t}`),!1}}function s(e,t={}){if(!e||e.length===0)return!0;let r=t.now||new Date,i=t.displayProperties||{},s=t.weatherData||{};for(let t of e){let e=a(t.metric,r,i,s);if(!o(e,t.condition,t.value,t.type))return n.debug(`Criteria failed: ${t.metric} ${t.condition} "${t.value}" (actual: "${e}")`),!1}return!0}function c(e){return parseInt(String(e).replace(`.xlf`,``),10)}function l(e,t=null){let n=new DOMParser().parseFromString(e,`text/xml`).querySelector(`layout`);if(!n)return{duration:60,isDynamic:!1};let r=parseInt(n.getAttribute(`duration`)||`0`,10);if(r>0)return{duration:r,isDynamic:!1};let i=0,a=!1;for(let e of n.querySelectorAll(`region`)){let n=e.getAttribute(`type`);if(n===`drawer`)continue;let r=n===`canvas`,o=0;for(let n of e.querySelectorAll(`media`)){let e=parseInt(n.getAttribute(`duration`)||`0`,10),i=parseInt(n.getAttribute(`useDuration`)||`1`,10),s=n.getAttribute(`fileId`)||``,c=t?.get(s),l;c===void 0?e>0&&i!==0?l=e:(l=60,a=!0):l=c,r?o=Math.max(o,l):o+=l}i=Math.max(i,o)}return{duration:i>0?i:60,isDynamic:a}}function u(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function d(e,t,n){if(!t||t===0)return!0;let r=n-36e5,i=e.filter(e=>e>r);if(i.length>=t)return!1;if(i.length>0){let e=36e5/t;if(n-Math.max(...i)<e)return!1}return!0}function f(e,t,n){let r=e.filter(e=>!e.maxPlaysPerHour||e.maxPlaysPerHour===0?!0:d(t.get(e.file)||[],e.maxPlaysPerHour,n));if(r.length===0)return[];let i=Math.max(...r.map(e=>e.priority));return r.filter(e=>e.priority===i).map(e=>e.file)}function p(e,t,n={}){let r=n.from||new Date,i=n.hours||2,a=new Date(r.getTime()+i*36e5);n.currentLayoutStartedAt;let o=n.defaultLayout||null,s=n.durations||null;if(!e||e.length===0)return[];let c=[],l=new Date(r),u=t%e.length;for(;l<a&&c.length<500;){let t=e[u],n=s&&s.get(t.layoutId)||t.duration,r=l.getTime()+n*1e3;c.push({layoutFile:t.layoutId,startTime:new Date(l),endTime:new Date(r),duration:n,isDefault:o?t.layoutId===o:!1}),l=new Date(r),u=(u+1)%e.length}return c}function m(e,t){for(e=Math.abs(Math.round(e)),t=Math.abs(Math.round(t));t;)[e,t]=[t,e%t];return e}function h(e,t){return e===0||t===0?0:Math.abs(Math.round(e)*Math.round(t))/m(e,t)}function g(e){return e.reduce((e,t)=>h(e,t),1)}function _(e,t,n={}){let{defaultLayout:r=null,defaultDuration:i=60}=n;if(e.length===0&&!r)return{queue:[],periodSeconds:0};let a=new Map;for(let t of e)t.duration>0&&a.set(t.file,t.duration);let o=e=>t.get(e)||a.get(e)||i,s=e.filter(e=>e.maxPlaysPerHour>0),c;s.length>0?(c=g(s.map(e=>Math.round(3600/e.maxPlaysPerHour))),c>7200&&(c=7200)):c=e.reduce((e,t)=>e+o(t.file),0)+(r&&!e.some(e=>e.file===r)?o(r):0)||i;let l=[],d=new Map,p=0,m=c*1e3;for(;p<m&&l.length<500;){let t=f(e,d,p);if(t.length===0){if(r){let e=o(r);l.push({layoutId:r,duration:e}),p+=e*1e3}else p+=6e4;continue}for(let n=0;n<t.length&&p<m&&l.length<500;n++){let r=t[n],i=o(r);if(l.push({layoutId:r,duration:i}),d.has(r)||d.set(r,[]),d.get(r).push(p),p+=i*1e3,!u(t,f(e,d,p)))break}}if(l.length===0&&r){let e=o(r);l.push({layoutId:r,duration:e})}return{queue:l,periodSeconds:c}}var v=e(`Schedule`),y=class{constructor(e={}){this.schedule=null,this.playHistory=new Map,this.interruptScheduler=e.interruptScheduler||null,this.displayProperties=e.displayProperties||{},this.weatherData={},this.playerLocation=null,this._layoutMetadata=new Map,this._scheduleQueue=null,this._queuePosition=0,this._queueLayoutSet=null}setSchedule(e){this.schedule=e,this._invalidateQueue()}setWeatherData(e){this.weatherData=e||{}}getDataConnectors(){return this.schedule?.dataConnectors||[]}getDependantsMap(){let e=new Map;if(!this.schedule)return e;let t=this.schedule.dependants||[],n=n=>{let r=c(n.file||n.id),i=[...t,...n.dependants||[]];i.length>0&&e.set(r,i)};if(this.schedule.layouts)for(let e of this.schedule.layouts)n(e);if(this.schedule.campaigns)for(let e of this.schedule.campaigns)for(let t of e.layouts)n(t);return e}isRecurringScheduleActive(e,t){if(!e.recurrenceType)return!0;if(e.recurrenceRange&&t>new Date(e.recurrenceRange))return!1;switch(e.recurrenceType){case`Week`:if(e.recurrenceRepeatsOn){let n=this.getIsoDayOfWeek(t);if(!e.recurrenceRepeatsOn.split(`,`).map(e=>parseInt(e.trim())).includes(n))return!1}return!0;case`Day`:{let n=e.recurrenceDetail||1;if(n>1&&e.fromdt){let r=new Date(e.fromdt),i=t.getTime()-r.getTime(),a=Math.floor(i/864e5);if(a<0||a%n!==0)return!1}return!0}case`Month`:{if(e.recurrenceRepeatsOn){let n=e.recurrenceRepeatsOn.split(`,`).map(e=>parseInt(e.trim())),r=t.getDate();if(!n.includes(r))return!1}let n=e.recurrenceDetail||1;if(n>1&&e.fromdt){let r=new Date(e.fromdt),i=(t.getFullYear()-r.getFullYear())*12+t.getMonth()-r.getMonth();if(i<0||i%n!==0)return!1}return!0}default:return v.debug(`Unsupported recurrence type: ${e.recurrenceType}`),!0}}getIsoDayOfWeek(e){let t=e.getDay();return t===0?7:t}isTimeActive(e,t){let n=e.fromdt?new Date(e.fromdt):null,r=e.todt?new Date(e.todt):null;if(e.recurrenceType===`Week`||e.recurrenceType===`Day`||e.recurrenceType===`Month`){if(n&&r){let e=t.getHours()*3600+t.getMinutes()*60+t.getSeconds(),i=n.getHours()*3600+n.getMinutes()*60+n.getSeconds(),a=r.getHours()*3600+r.getMinutes()*60+r.getSeconds();return i<=a?e>=i&&e<=a:e>=i||e<=a}return!0}return!(n&&t<n||r&&t>r)}getCurrentLayouts(){return this._getLayoutsAt(new Date)}getLayoutsAtTime(e){return this._getLayoutsAt(e,{skipRateLimiting:!0,skipInterrupts:!0,quiet:!0})}getAllLayoutsAtTime(e){if(!this.schedule)return[];let t=e,n=[];if(this.schedule.layouts)for(let e of this.schedule.layouts)this.isRecurringScheduleActive(e,t)&&this.isTimeActive(e,t)&&(e.criteria&&e.criteria.length>0&&!s(e.criteria,{now:t,displayProperties:this.displayProperties,weatherData:this.weatherData})||e.isGeoAware&&e.geoLocation&&!this.isWithinGeoFence(e.geoLocation)||n.push({file:e.file,priority:e.priority||0,maxPlaysPerHour:e.maxPlaysPerHour||0,duration:e.duration||0}));if(this.schedule.campaigns){for(let e of this.schedule.campaigns)if(this.isRecurringScheduleActive(e,t)&&this.isTimeActive(e,t))for(let t of e.layouts)n.push({file:t.file,priority:e.priority||0,maxPlaysPerHour:t.maxPlaysPerHour||0,duration:t.duration||0})}return n}detectConflicts(e={}){let t=e.from||new Date,n=e.hours||24,r=new Date(t.getTime()+n*36e5),i=6e4,a=[],o=null;for(let e=t.getTime();e<r.getTime();e+=i){let t=new Date(e),n=this.getAllLayoutsAtTime(t);if(n.length===0){o&&=(a.push(o),null);continue}let r=Math.max(...n.map(e=>e.priority)),s=n.filter(e=>e.priority<r);if(s.length===0){o&&=(a.push(o),null);continue}let c=n.filter(e=>e.priority===r),l=c.map(e=>e.file).sort().join(`,`),u=s.map(e=>`${e.file}:${e.priority}`).sort().join(`,`);o&&o._winnerKey===l&&o._hiddenKey===u?o.endTime=new Date(e+i):(o&&a.push(o),o={startTime:new Date(e),endTime:new Date(e+i),winner:{file:c[0].file,priority:r},hidden:s.map(e=>({file:e.file,priority:e.priority})),_winnerKey:l,_hiddenKey:u})}o&&a.push(o);for(let e of a)delete e._winnerKey,delete e._hiddenKey;return a}_getLayoutsAt(e,t={}){if(!this.schedule)return[];let{skipRateLimiting:n=!1,skipInterrupts:r=!1,quiet:i=!1}=t,a=i?()=>{}:(...e)=>v.info(...e),o=[];if(this._maxActivePriority=0,this.schedule.campaigns)for(let t of this.schedule.campaigns)this.isRecurringScheduleActive(t,e)&&this.isTimeActive(t,e)&&(this._maxActivePriority=Math.max(this._maxActivePriority,t.priority||0),o.push({type:`campaign`,priority:t.priority,layouts:t.layouts,campaignId:t.id}));if(this.schedule.layouts){for(let t of this.schedule.layouts)if(this.isRecurringScheduleActive(t,e)&&this.isTimeActive(t,e)){if(t.criteria&&t.criteria.length>0&&!s(t.criteria,{now:e,displayProperties:this.displayProperties,weatherData:this.weatherData})){a(`[Schedule] Layout`,t.id,`filtered by criteria`);continue}if(t.isGeoAware&&t.geoLocation&&!this.isWithinGeoFence(t.geoLocation)){a(`[Schedule] Layout`,t.id,`filtered by geofence`);continue}if(this._maxActivePriority=Math.max(this._maxActivePriority,t.priority||0),!n&&!this.canPlayLayout(t.id,t.maxPlaysPerHour)){a(`[Schedule] Layout`,t.id,`filtered by maxPlaysPerHour (limit:`,t.maxPlaysPerHour,`)`);continue}o.push({type:`layout`,priority:t.priority||0,layouts:[t],layoutId:t.id})}}if(o.length===0)return this.schedule.default?[this.schedule.default]:[];let c=Math.max(...o.map(e=>e.priority));a(`[Schedule] Max priority:`,c,`from`,o.length,`active items`);let l=[];for(let e of o)e.priority===c?(a(`[Schedule] Including priority`,e.priority,`layouts:`,e.layouts.map(e=>e.file)),l.push(...e.layouts)):a(`[Schedule] Skipping priority`,e.priority,`< max`,c);this._layoutMetadata.clear();for(let e of l)this._layoutMetadata.set(e.file,{syncEvent:e.syncEvent||!1,shareOfVoice:e.shareOfVoice||0,scheduleid:e.scheduleid,priority:e.priority||0});if(!r&&this.interruptScheduler){let{normalLayouts:e,interruptLayouts:t}=this.interruptScheduler.separateLayouts(l);if(t.length>0){a(`[Schedule] Found`,t.length,`interrupt layouts with shareOfVoice`);let n=this.interruptScheduler.processInterrupts(e,t).map(e=>e.file);return a(`[Schedule] Final layouts (with interrupts):`,n),n}}let u=l.map(e=>e.file);return a(`[Schedule] Final layouts:`,u),u}shouldCheckSchedule(e){return e?Date.now()-e>=6e4:!0}canPlayLayout(e,t){return d(this.playHistory.get(e)||[],t,Date.now())}recordPlay(e){this.playHistory.has(e)||this.playHistory.set(e,[]);let t=this.playHistory.get(e);t.push(Date.now());let n=Date.now()-3600*1e3,r=t.filter(e=>e>n);this.playHistory.set(e,r),v.info(`Recorded play for layout ${e} (${r.length} plays in last hour)`)}isSyncEvent(e){return this._layoutMetadata.get(e)?.syncEvent===!0}getLayoutMetadata(e){return this._layoutMetadata.get(e)||null}getScheduleQueue(e,t={}){let n=this.getAllLayoutsAtTime(new Date),r=n.map(e=>`${e.file}:${e.priority}:${e.maxPlaysPerHour}`).sort().join(`|`);if(this._scheduleQueue&&this._queueLayoutSet===r)return this._scheduleQueue;let i=_(n,e,{defaultLayout:this.schedule?.default||null,defaultDuration:60,dynamicLayouts:t.dynamicLayouts||new Set}),a=this._queueLayoutSet;return this._scheduleQueue=i,this._queueLayoutSet=r,a!==r&&(this._queuePosition=0),i.queue.length>0&&(v.info(`[Schedule] Built queue: ${i.queue.length} entries, period ${i.periodSeconds}s (pos ${this._queuePosition})`),v.info(`[Schedule] Queue: ${i.queue.map(e=>`${e.layoutId}(${e.duration}s)`).join(` → `)}`)),i}popNextFromQueue(e,t={}){let{queue:n}=this.getScheduleQueue(e,t);if(n.length===0)return null;let r=n[this._queuePosition%n.length];return this._queuePosition=(this._queuePosition+1)%n.length,r}getQueuePosition(){return this._queuePosition}rewindQueue(e,t,n={}){let{queue:r}=this.getScheduleQueue(t,n);if(r.length===0)return null;this._queuePosition=(this._queuePosition-e+r.length*e)%r.length;let i=r[this._queuePosition];return this._queuePosition=(this._queuePosition+1)%r.length,i}peekNextInQueue(e,t={}){let{queue:n}=this.getScheduleQueue(e,t);return n.length===0?null:n[this._queuePosition%n.length]}peekAfterNext(e,t={}){let{queue:n}=this.getScheduleQueue(e,t);return n.length<=1?null:n[(this._queuePosition+1)%n.length]}invalidateQueue(){this._invalidateQueue()}_invalidateQueue(){this._scheduleQueue=null}hasSyncEvents(){for(let e of this._layoutMetadata.values())if(e.syncEvent)return!0;return!1}getActiveActions(){if(!this.schedule?.actions)return[];let e=new Date;return this.schedule.actions.filter(t=>this.isTimeActive(t,e))}getCommands(){return this.schedule?.commands||[]}findActionByTrigger(e){return this.getActiveActions().find(t=>t.triggerCode===e)||null}clearPlayHistory(){this.playHistory.clear(),v.info(`Play history cleared`)}setLocation(e,t){this.playerLocation={latitude:e,longitude:t},v.info(`Location set: ${e}, ${t}`)}setDisplayProperties(e){this.displayProperties=e||{}}isWithinGeoFence(e,t=500){if(!this.playerLocation)return v.debug(`No player location, skipping geofence check`),!0;if(!e)return!0;let n=e.split(`,`).map(e=>parseFloat(e.trim()));if(n.length<2||isNaN(n[0])||isNaN(n[1]))return v.warn(`Invalid geoLocation format:`,e),!0;let r=n[0],i=n[1],a=n[2]||t,o=this.haversineDistance(this.playerLocation.latitude,this.playerLocation.longitude,r,i),s=o<=a;return v.info(`Geofence: ${o.toFixed(0)}m from (${r},${i}), radius ${a}m → ${s?`WITHIN`:`OUTSIDE`}`),s}haversineDistance(e,t,n,r){let i=e=>e*Math.PI/180,a=i(n-e),o=i(r-t),s=Math.sin(a/2)**2+Math.cos(i(e))*Math.cos(i(n))*Math.sin(o/2)**2;return 6371e3*2*Math.atan2(Math.sqrt(s),Math.sqrt(1-s))}},b=new y,x=e(`schedule:interrupts`),S=class{constructor(){this.interruptCommittedDurations=new Map}isInterrupt(e){return!!(e.shareOfVoice&&e.shareOfVoice>0)}resetCommittedDurations(){this.interruptCommittedDurations.clear(),x.debug(`Reset interrupt committed durations`)}getCommittedDuration(e){return this.interruptCommittedDurations.get(e)||0}addCommittedDuration(e,t){let n=this.getCommittedDuration(e);this.interruptCommittedDurations.set(e,n+t)}isInterruptDurationSatisfied(e){if(!e.shareOfVoice)return!0;let t=e.id||e.file,n=e.shareOfVoice/100*3600;return this.getCommittedDuration(t)>=n}getRequiredSeconds(e){return e.shareOfVoice?e.shareOfVoice/100*3600:0}processInterrupts(e,t){if(!t||t.length===0)return x.debug(`No interrupt layouts, returning normal layouts`),e;if(!e||e.length===0)return x.warn(`No normal layouts available, interrupts will fill entire hour`),this.fillHourWithInterrupts(t);x.info(`Processing ${t.length} interrupt layouts with ${e.length} normal layouts`);for(let e of t){let t=e.id||e.file;this.interruptCommittedDurations.set(t,0)}let n=[],r=0,i=0,a=!1;for(;!a;){if(i>=t.length){i=0;let e=!0;for(let n of t)if(!this.isInterruptDurationSatisfied(n)){e=!1;break}if(e){a=!0;break}}let e=t[i];if(!this.isInterruptDurationSatisfied(e)){let t=e.id||e.file;this.addCommittedDuration(t,e.duration),r+=e.duration,n.push(e)}i++}if(x.debug(`Resolved ${n.length} interrupt plays (${r}s total)`),r>=3600)return x.info(`Interrupts fill entire hour (>= 3600s), no room for normal layouts`),n;let o=3600-r,s=this.fillTimeWithLayouts(e,o);x.debug(`Resolved ${s.length} normal plays (${o}s target)`);let c=this.interleaveLayouts(s,n);return x.info(`Final loop: ${c.length} layouts (${s.length} normal + ${n.length} interrupts)`),c}fillTimeWithLayouts(e,t){let n=[],r=t,i=0;for(;r>0;){i>=e.length&&(i=0);let t=e[i];n.push(t),r-=t.duration,i++}return n}fillHourWithInterrupts(e){return this.fillTimeWithLayouts(e,3600)}interleaveLayouts(e,t){let n=[],r=Math.max(e.length,t.length),i=Math.ceil(1*r/e.length),a=Math.floor(1*r/t.length);x.debug(`Interleaving: pickCount=${r}, normalPick=${i}, interruptPick=${a}`);let o=0,s=0,c=0;for(let l=0;l<r;l++)l%i===0&&(o>=e.length&&(o=0),n.push(e[o]),c+=e[o].duration,o++),l%a===0&&s<t.length&&(n.push(t[s]),c+=t[s].duration,s++);for(;c<3600;)o>=e.length&&(o=0),n.push(e[o]),c+=e[o].duration,o++;return x.debug(`Interleaved ${n.length} layouts, total duration: ${c}s`),n}separateLayouts(e){let t=[],n=[];for(let r of e)this.isInterrupt(r)?n.push(r):t.push(r);return{normalLayouts:t,interruptLayouts:n}}};new S;var C=e(`schedule:overlays`),w=class{constructor(){this.overlays=[],this.displayProperties={},this.scheduleManager=null,C.debug(`OverlayScheduler initialized`)}setScheduleManager(e){this.scheduleManager=e}setDisplayProperties(e){this.displayProperties=e||{}}setOverlays(e){this.overlays=e||[],C.info(`Loaded ${this.overlays.length} overlay(s)`)}getCurrentOverlays(){if(!this.overlays||this.overlays.length===0)return[];let e=new Date,t=[];for(let n of this.overlays){if(!this.isTimeActive(n,e)){C.debug(`Overlay ${n.file} not in time window`);continue}if(n.isGeoAware&&n.geoLocation&&this.scheduleManager&&!this.scheduleManager.isWithinGeoFence(n.geoLocation)){C.debug(`Overlay ${n.file} filtered by geofence`);continue}if(n.criteria&&n.criteria.length>0&&!s(n.criteria,{now:e,displayProperties:this.displayProperties})){C.debug(`Overlay ${n.file} filtered by criteria`);continue}t.push(n)}return t.sort((e,t)=>{let n=e.priority||0;return(t.priority||0)-n}),t.length>0&&C.info(`Active overlays: ${t.length}`),t}isTimeActive(e,t){if(this.scheduleManager){let n={...e};return!n.fromdt&&n.fromDt&&(n.fromdt=n.fromDt),!n.todt&&n.toDt&&(n.todt=n.toDt),this.scheduleManager.isTimeActive(n,t)}let n=e.fromdt||e.fromDt?new Date(e.fromdt||e.fromDt):null,r=e.todt||e.toDt?new Date(e.todt||e.toDt):null;return!(n&&t<n||r&&t>r)}shouldCheckOverlays(e){return e?Date.now()-e>=6e4:!0}getOverlayByFile(e){return this.overlays.find(t=>t.file===e)||null}clear(){this.overlays=[],C.debug(`Cleared all overlays`)}};new w;var T=t.version;export{b as a,l as c,y as i,c as l,w as n,_ as o,S as r,p as s,T as t};
2
- //# sourceMappingURL=src-DPOUYQMT.js.map
@@ -1,2 +0,0 @@
1
- import{t as e,v as t}from"./src-CMBYiOs4.js";var n={name:`@xiboplayer/cache`,version:`0.7.15`,description:`Offline caching and download management with parallel chunk downloads`,type:`module`,main:`./src/index.js`,types:`./src/index.d.ts`,exports:{".":`./src/index.js`,"./cache":`./src/cache.js`,"./store-client":`./src/store-client.js`,"./download-manager":`./src/download-manager.js`,"./cache-analyzer":`./src/cache-analyzer.js`,"./widget-html":`./src/widget-html.js`},scripts:{test:`vitest run`,"test:watch":`vitest`,"test:coverage":`vitest run --coverage`},dependencies:{"@xiboplayer/utils":`workspace:*`,"spark-md5":`^3.0.2`},devDependencies:{jsdom:`^29.0.1`,vitest:`^4.1.2`},keywords:[`xibo`,`digital-signage`,`cache`,`offline`,`download`,`indexeddb`],author:`Pau Aliagas <linuxnow@gmail.com>`,license:`AGPL-3.0-or-later`,repository:{type:`git`,url:`git+https://github.com/xibo-players/xiboplayer.git`,directory:`packages/cache`},homepage:`https://xiboplayer.org`},r=t(`Cache`),i=class{constructor(){this.dependants=new Map}addDependant(e,t){let n=String(e);this.dependants.has(n)||this.dependants.set(n,new Set),this.dependants.get(n).add(String(t))}removeLayoutDependants(e){let t=String(e),n=[];for(let[e,r]of this.dependants)r.delete(t),r.size===0&&(this.dependants.delete(e),n.push(e));return n.length>0&&r.info(`${n.length} media files orphaned after layout ${e} removed:`,n),n}isMediaReferenced(e){let t=this.dependants.get(String(e));return t?t.size>0:!1}async clearAll(){this.dependants.clear()}},a=new i,o=t(`StoreClient`),s=class{async has(e,t){try{let n=await fetch(`/store/${e}/${t}`,{method:`HEAD`});if(n.status===204)return!1;if(n.status===200)return n.headers.get(`X-Store-Complete`)!==`false`;if(n.status===404)return!1;let r=Error(`Store error: ${n.status}`);throw r.status=n.status,o.warn(`has(${e}/${t}): unexpected status ${n.status}`),r}catch(n){throw n.status||n.name===`AbortError`||n.name===`TimeoutError`||o.warn(`has(${e}/${t}): network error — ${n.message}`),n}}async get(e,t){try{let n=await fetch(`/store/${e}/${t}`);if(n.status===204||n.status===404)return n.body?.cancel(),null;if(!n.ok)throw n.body?.cancel(),Error(`Failed to get file: ${n.status}`);return await n.blob()}catch(e){return o.error(`get error:`,e.message),null}}async put(e,t,n,r=`application/octet-stream`){try{let i=await fetch(`/store/${e}/${t}`,{method:`PUT`,headers:{"Content-Type":r},body:n});return i.body?.cancel(),i.ok}catch(e){return o.error(`put error:`,e.message),!1}}async remove(e){try{let t=await(await fetch(`/store/delete`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({files:e})})).json();return{deleted:t.deleted||0,total:t.total||e.length}}catch(t){return o.error(`remove error:`,t.message),{deleted:0,total:e.length}}}async list(){try{return(await(await fetch(`/store/list`)).json()).files||[]}catch(e){return o.error(`list error:`,e.message),[]}}},c={media:{maxRetries:3,retryDelayMs:500,retryDelays:null,maxReenqueues:0,reenqueueDelayMs:0,skipHead:!1,cacheTtl:1/0},layout:{maxRetries:3,retryDelayMs:500,retryDelays:null,maxReenqueues:0,reenqueueDelayMs:0,skipHead:!1,cacheTtl:1/0},dataset:{maxRetries:4,retryDelayMs:0,retryDelays:[15e3,3e4,6e4,12e4],maxReenqueues:5,reenqueueDelayMs:6e4,skipHead:!0,cacheTtl:300},static:{maxRetries:3,retryDelayMs:500,retryDelays:null,maxReenqueues:0,reenqueueDelayMs:0,skipHead:!1,cacheTtl:1/0}};function l(e){return c[e]||c.media}var u=t(`Download`),d=6,f=50*1024*1024,p=3,m=100*1024*1024,h=2,g=6e5,_=15e3;function v(e){return{mp4:`video/mp4`,webm:`video/webm`,mp3:`audio/mpeg`,png:`image/png`,jpg:`image/jpeg`,jpeg:`image/jpeg`,gif:`image/gif`,svg:`image/svg+xml`,webp:`image/webp`,css:`text/css`,js:`application/javascript`,ttf:`font/ttf`,otf:`font/otf`,woff:`font/woff`,woff2:`font/woff2`,xml:`application/xml`,xlf:`application/xml`}[(e.path||e.code||``).split(`.`).pop()?.split(`?`)[0]?.toLowerCase()]||`application/octet-stream`}var y={normal:0,layout:1,high:2,urgent:3},b=Symbol(`BARRIER`);function x(e){try{let t=new URL(e,`http://localhost`),n=t.searchParams.get(`X-Amz-Date`),r=t.searchParams.get(`X-Amz-Expires`);if(n&&r){let e=n.replace(/(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z/,`$1-$2-$3T$4:$5:$6Z`),t=new Date(e).getTime()/1e3;return isNaN(t)?1/0:t+parseInt(r,10)}return 1/0}catch{return 1/0}}function S(e,t=30){let n=x(e);return n===1/0?!1:Date.now()/1e3>=n-t}var C=class{constructor(e,t={}){this.fileInfo=e,this.chunkIndex=t.chunkIndex??null,this.rangeStart=t.rangeStart??null,this.rangeEnd=t.rangeEnd??null,this.state=`pending`,this.blob=null,this._parentFile=null,this._priority=y.normal,this._typeConfig=l(e.type)}getUrl(){let e=this.fileInfo.path;if(S(e))throw Error(`URL expired for ${this.fileInfo.type}/${this.fileInfo.id} — waiting for fresh URL from next collection cycle`);return e}async start(){this.state=`downloading`;let e={};this.rangeStart!=null&&(e.Range=`bytes=${this.rangeStart}-${this.rangeEnd}`),this.chunkIndex!=null&&(e[`X-Store-Chunk-Index`]=String(this.chunkIndex),this._parentFile&&(e[`X-Store-Num-Chunks`]=String(this._parentFile.totalChunks),e[`X-Store-Chunk-Size`]=String(this._parentFile.options.chunkSize||104857600))),this.fileInfo.md5&&(e[`X-Store-MD5`]=this.fileInfo.md5),this.fileInfo.updateInterval&&(e[`X-Cache-TTL`]=String(this.fileInfo.updateInterval)),this.fileInfo.cmsDownloadUrl&&(e[`X-Cms-Download-Url`]=this.fileInfo.cmsDownloadUrl);let t=this._typeConfig.maxRetries;for(let n=1;n<=t;n++){let r=new AbortController,i=setTimeout(()=>r.abort(),g);try{let t=this.getUrl(),n={signal:r.signal};Object.keys(e).length>0&&(n.headers=e);let i=await fetch(t,n);if(!i.ok&&i.status!==206)throw Error(`Fetch failed: ${i.status}`);return this.blob=await i.blob(),this.state=`complete`,this.blob}catch(e){let i=r.signal.aborted?`Timeout after ${g/1e3}s`:e.message;if(n<t){let e=this._typeConfig.retryDelays?.[n-1]??this._typeConfig.retryDelayMs*n,r=this.chunkIndex==null?``:` chunk ${this.chunkIndex}`;u.warn(`[DownloadTask] ${this.fileInfo.type}/${this.fileInfo.id}${r} attempt ${n}/${t} failed: ${i}. Retrying in ${e/1e3}s...`),await new Promise(t=>setTimeout(t,e))}else throw this.state=`failed`,r.signal.aborted?Error(i):e}finally{clearTimeout(i)}}}},w=class{constructor(e,t={}){this.fileInfo=e,this.options=t,this.state=`pending`,this.tasks=[],this.completedChunks=0,this.totalChunks=0,this.totalBytes=0,this.downloadedBytes=0,this.onChunkDownloaded=null,this.skipChunks=e.skipChunks||new Set,this._contentType=`application/octet-stream`,this._chunkBlobs=new Map,this._runningCount=0,this._resolve=null,this._reject=null,this._promise=new Promise((e,t)=>{this._resolve=e,this._reject=t}),this._promise.catch(()=>{})}getUrl(){let e=this.fileInfo.path;if(S(e))throw Error(`URL expired for ${this.fileInfo.type}/${this.fileInfo.id} — waiting for fresh URL from next collection cycle`);return e}wait(){return this._promise}async prepare(e){try{this.state=`preparing`;let{id:t,type:n,size:r}=this.fileInfo;u.info(`[FileDownload] Starting:`,`${n}/${t}`),this.totalBytes=r&&r>0?parseInt(r):0,this._contentType=v(this.fileInfo);let i=l(this.fileInfo.type).skipHead;if(this.totalBytes===0&&!i){let e=this.getUrl(),t=new AbortController,n=setTimeout(()=>t.abort(),_);try{let n=await fetch(e,{method:`HEAD`,signal:t.signal});n.ok&&(this.totalBytes=parseInt(n.headers.get(`Content-Length`)||`0`),this._contentType=n.headers.get(`Content-Type`)||this._contentType)}finally{clearTimeout(n)}}u.info(`[FileDownload] File size:`,(this.totalBytes/1024/1024).toFixed(1),`MB`);let a=this.options.chunkSize||f;if(this.totalBytes>m){let e=[];for(let t=0;t<this.totalBytes;t+=a)e.push({start:t,end:Math.min(t+a-1,this.totalBytes-1),index:e.length});this.totalChunks=e.length;let r=e.filter(e=>!this.skipChunks.has(e.index)),i=e.length-r.length;for(let t of e)this.skipChunks.has(t.index)&&(this.downloadedBytes+=t.end-t.start+1);if(r.length===0){u.info(`[FileDownload] All chunks already cached, nothing to download`),this.state=`complete`,this._resolve(new Blob([],{type:this._contentType}));return}i>0&&u.info(`[FileDownload] Resuming: ${i} chunks cached, ${r.length} to download`);let o=i>0;if(o){let e=r.sort((e,t)=>e.index-t.index);for(let t of e){let e=new C(this.fileInfo,{chunkIndex:t.index,rangeStart:t.start,rangeEnd:t.end});e._parentFile=this,e._priority=y.normal,this.tasks.push(e)}}else for(let t of r){let n=new C(this.fileInfo,{chunkIndex:t.index,rangeStart:t.start,rangeEnd:t.end});n._parentFile=this,n._priority=t.index===0||t.index===e.length-1?y.high:y.normal,this.tasks.push(n)}let s=this.tasks.filter(e=>e._priority>=y.high).length;u.info(`[FileDownload] ${n}/${t}: ${this.tasks.length} chunks`+(s>0?` (${s} priority)`:``)+(o?` (resume)`:``))}else{this.totalChunks=1;let e=new C(this.fileInfo,{});e._parentFile=this,this.tasks.push(e)}e.enqueueChunkTasks(this.tasks),this.state=`downloading`}catch(e){u.error(`[FileDownload] Prepare failed:`,`${this.fileInfo.type}/${this.fileInfo.id}`,e),this.state=`failed`,this._reject(e)}}async onTaskComplete(e){if(this.completedChunks++,this.downloadedBytes+=e.blob.size,e.chunkIndex!=null&&this._chunkBlobs.set(e.chunkIndex,e.blob),this.options.onProgress&&this.options.onProgress(this.downloadedBytes,this.totalBytes),this.onChunkDownloaded&&e.chunkIndex!=null)try{await this.onChunkDownloaded(e.chunkIndex,e.blob,this.totalChunks)}catch(e){u.warn(`[FileDownload] onChunkDownloaded callback error:`,e)}if(this.completedChunks===this.tasks.length&&this.state!==`complete`){this.state=`complete`;let{type:t,id:n}=this.fileInfo;if(e.chunkIndex==null)u.info(`[FileDownload] Complete:`,`${t}/${n}`,`(${e.blob.size} bytes)`),this._resolve(e.blob);else if(this.onChunkDownloaded)u.info(`[FileDownload] Complete:`,`${t}/${n}`,`(progressive, ${this.totalChunks} chunks)`),this._resolve(new Blob([],{type:this._contentType}));else{let e=[];for(let t=0;t<this.totalChunks;t++){let n=this._chunkBlobs.get(t);n&&e.push(n)}let r=new Blob(e,{type:this._contentType});u.info(`[FileDownload] Complete:`,`${t}/${n}`,`(${r.size} bytes, reassembled)`),this._resolve(r)}this._chunkBlobs.clear()}}onTaskFailed(e,t){if(!(this.state===`complete`||this.state===`failed`)){if(t.message?.includes(`URL expired`)){let t=e.chunkIndex==null?``:` chunk ${e.chunkIndex}`;u.warn(`[FileDownload] URL expired, dropping${t}:`,`${this.fileInfo.type}/${this.fileInfo.id}`),this.tasks=this.tasks.filter(t=>t!==e),(this.tasks.length===0||this.completedChunks>=this.tasks.length)&&(this.state=`complete`,this._urlExpired=!0,this._resolve(new Blob([],{type:this._contentType})));return}u.error(`[FileDownload] Failed:`,`${this.fileInfo.type}/${this.fileInfo.id}`,t),this.state=`failed`,this._reject(t)}}},T=class{constructor(e){this.queue=e,this._filesToPrepare=[],this._tasks=[],this._maxPreparing=2}addFile(e){let t=E.stableKey(e);if(this.queue.active.has(t)){let n=this.queue.active.get(t);if(e.path&&e.path!==n.fileInfo.path){let t=x(n.fileInfo.path);x(e.path)>t&&(n.fileInfo.path=e.path)}return n}let n=new w(e,{chunkSize:this.queue.chunkSize,calculateMD5:this.queue.calculateMD5,onProgress:this.queue.onProgress});return this.queue.active.set(t,n),this._filesToPrepare.push(n),n}enqueueChunkTasks(e){this._tasks.push(...e)}async build(){return await this._prepareAll(),this._sortWithBarriers()}async _prepareAll(){await new Promise(e=>{let t=0,n=0,r=()=>{for(;t<this._maxPreparing&&n<this._filesToPrepare.length;){let i=this._filesToPrepare[n++];t++,i.prepare(this).finally(()=>{t--,n>=this._filesToPrepare.length&&t===0?e():r()})}};this._filesToPrepare.length===0?e():r()})}_sortWithBarriers(){let e=[],t=[],n=[],r=[];for(let i of this._tasks)if(i.chunkIndex==null)e.push(i);else if(i.chunkIndex===0)t.push(i);else{let e=i._parentFile?.totalChunks||0;e>1&&i.chunkIndex===e-1?n.push(i):r.push(i)}e.sort((e,t)=>(e._parentFile?.totalBytes||0)-(t._parentFile?.totalBytes||0)),r.sort((e,t)=>e.chunkIndex-t.chunkIndex);let i=[...e,...t,...n];return r.length>0&&i.push(b,...r),i}},E=class e{constructor(e={}){this.concurrency=e.concurrency||d,this.chunkSize=e.chunkSize||f,this.maxChunksPerFile=e.chunksPerFile||p,this.calculateMD5=e.calculateMD5,this.onProgress=e.onProgress,this.queue=[],this.active=new Map,this._activeTasks=[],this.running=0,this._prepareQueue=[],this._preparingCount=0,this._maxPreparing=2,this.paused=!1,this._reenqueueTimers=new Set}static stableKey(e){return`${e.type}/${e.id}`}enqueue(t){let n=e.stableKey(t);if(this.active.has(n)){let e=this.active.get(n);if(t.path&&t.path!==e.fileInfo.path){let r=x(e.fileInfo.path);x(t.path)>r&&(u.info(`[DownloadQueue] Refreshing URL for`,n),e.fileInfo.path=t.path)}return e}let r=new w(t,{chunkSize:this.chunkSize,calculateMD5:this.calculateMD5,onProgress:this.onProgress});return this.active.set(n,r),u.info(`[DownloadQueue] Enqueued:`,n),this._schedulePrepare(r),r}_schedulePrepare(e){this._prepareQueue.push(e),this._processPrepareQueue()}_processPrepareQueue(){for(;this._preparingCount<this._maxPreparing&&this._prepareQueue.length>0;){let e=this._prepareQueue.shift();this._preparingCount++,e.prepare(this).finally(()=>{this._preparingCount--,this._processPrepareQueue()})}}enqueueChunkTasks(e){for(let t of e)this.queue.push(t);this._sortQueue(),u.info(`[DownloadQueue] ${e.length} tasks added (${this.queue.length} pending, ${this.running} active)`),this.processQueue()}enqueueOrderedTasks(e){let t=0,n=0;for(let r of e)r===b?(this.queue.push(b),n++):(this.queue.push(r),t++);u.info(`[DownloadQueue] Ordered queue: ${t} tasks, ${n} barriers (${this.queue.length} pending, ${this.running} active)`),this.processQueue()}_sortQueue(){this.queue.sort((e,t)=>t._priority-e._priority)}prioritizeLayoutFiles(e,t=y.high){let n=new Set(e.map(String)),r=0;for(let e of this.queue){let i=e._parentFile?.fileInfo.saveAs||String(e._parentFile?.fileInfo.id);n.has(i)&&e._priority<t&&(e._priority=t,r++)}for(let e of this._activeTasks){let r=e._parentFile?.fileInfo.saveAs||String(e._parentFile?.fileInfo.id);n.has(r)&&e._priority<t&&(e._priority=t)}this._sortQueue(),u.info(`[DownloadQueue] Layout files prioritized:`,n.size,`files,`,r,`tasks boosted to`,t)}urgentChunk(e,t,n){let r=`${e}/${t}`,i=this.active.get(r);if(!i)return u.info(`[DownloadQueue] urgentChunk: file not active:`,r,`chunk`,n),!1;if(this._activeTasks.some(e=>e._parentFile===i&&e.chunkIndex===n&&e.state===`downloading`)){let e=this._activeTasks.find(e=>e._parentFile===i&&e.chunkIndex===n);return e&&e._priority<y.urgent?(e._priority=y.urgent,u.info(`[DownloadQueue] URGENT: ${r} chunk ${n} (already in-flight, limiting slots)`),!0):(u.info(`[DownloadQueue] urgentChunk: already urgent:`,r,`chunk`,n),!1)}let a=this.queue.findIndex(e=>e!==b&&e._parentFile===i&&e.chunkIndex===n);if(a===-1)return u.info(`[DownloadQueue] urgentChunk: chunk not in queue:`,r,`chunk`,n),!1;let o=this.queue.splice(a,1)[0];return o._priority=y.urgent,this.queue.unshift(o),u.info(`[DownloadQueue] URGENT: ${r} chunk ${n} (moved to front)`),this.processQueue(),!0}processQueue(){if(this.paused)return;let e=this.queue.some(e=>e!==b&&e._priority>=y.urgent)||this._activeTasks?.some(e=>e._priority>=y.urgent&&e.state===`downloading`),t=e?h:this.concurrency,n=e?y.urgent:0;for(;this.running<t&&this.queue.length>0;){let e=this.queue[0];if(e===b){if(this.running>0)break;this.queue.shift();continue}if(e._priority<n||!this._canStartTask(e)){let e=!1;for(let t=1;t<this.queue.length&&this.queue[t]!==b;t++){let r=this.queue[t];if(r._priority>=n&&this._canStartTask(r)){this.queue.splice(t,1),this._startTask(r),e=!0;break}}if(!e)break;continue}this.queue.shift(),this._startTask(e)}this.queue.length===0&&this.running===0&&u.info(`[DownloadQueue] All downloads complete`)}_canStartTask(e){return e._parentFile._runningCount<this.maxChunksPerFile}_startTask(e){this.running++,e._parentFile._runningCount++,this._activeTasks.push(e);let t=`${e.fileInfo.type}/${e.fileInfo.id}`,n=e.chunkIndex==null?``:` chunk ${e.chunkIndex}`;u.info(`[DownloadQueue] Starting: ${t}${n} (${this.running}/${this.concurrency} active)`),e.start().then(()=>(this.running--,e._parentFile._runningCount--,this._activeTasks=this._activeTasks.filter(t=>t!==e),u.info(`[DownloadQueue] Fetched: ${t}${n} (${this.running} active, ${this.queue.length} pending)`),this.processQueue(),e._parentFile.onTaskComplete(e))).catch(n=>{this.running--,e._parentFile._runningCount--,this._activeTasks=this._activeTasks.filter(t=>t!==e);let{maxReenqueues:r,reenqueueDelayMs:i}=e._typeConfig;if(r>0){if(e._reenqueueCount=(e._reenqueueCount||0)+1,e._reenqueueCount>r){u.error(`[DownloadQueue] ${t} exceeded ${r} re-enqueues, failing permanently`),this.processQueue(),e._parentFile.onTaskFailed(e,n);return}u.warn(`[DownloadQueue] ${t} failed all retries (attempt ${e._reenqueueCount}/${r}), scheduling re-enqueue in ${i/1e3}s`);let a=setTimeout(()=>{this._reenqueueTimers.delete(a),e.state=`pending`,e._parentFile.state=`downloading`,this.queue.push(e),u.info(`[DownloadQueue] ${t} re-enqueued for retry`),this.processQueue()},i);this._reenqueueTimers.add(a),this.processQueue();return}this.processQueue(),e._parentFile.onTaskFailed(e,n)})}removeCompleted(e){let t=this.active.get(e);t&&(t.state===`complete`||t.state===`failed`)&&(this.queue=this.queue.filter(e=>e===b||e._parentFile!==t),this.active.delete(e))}getTask(e){return this.active.get(e)||null}getProgress(){let e={};for(let[t,n]of this.active.entries())n.state===`complete`||n.state===`failed`||(e[t]={downloaded:n.downloadedBytes,total:n.totalBytes,percent:n.totalBytes>0?(n.downloadedBytes/n.totalBytes*100).toFixed(1):0,state:n.state});return e}clear(){this.queue=[],this.active.clear(),this.running=0,this._prepareQueue=[],this._preparingCount=0;for(let e of this._reenqueueTimers)clearTimeout(e);this._reenqueueTimers.clear()}},D=class{constructor(e={}){this.queue=new E(e)}enqueue(e){return this.queue.enqueue(e)}getTask(e){return this.queue.getTask(e)}getProgress(){return this.queue.getProgress()}prioritizeLayoutFiles(e,t){this.queue.prioritizeLayoutFiles(e,t),this.queue.processQueue()}urgentChunk(e,t,n){return this.queue.urgentChunk(e,t,n)}createTaskBuilder(){return new T(this.queue)}enqueueOrderedTasks(e){this.queue.enqueueOrderedTasks(e)}removeCompleted(e){this.queue.removeCompleted(e)}get running(){return this.queue.running}get queued(){return this.queue.queue.length}clear(){this.queue.clear()}},O=t(`CacheAnalyzer`);function k(e){if(e===0)return`0 B`;if(!Number.isFinite(e))return`∞`;let t=[`B`,`KB`,`MB`,`GB`,`TB`],n=Math.floor(Math.log(e)/Math.log(1024));return`${(e/1024**n).toFixed(n>0?1:0)} ${t[n]}`}var A=class{constructor(e,{threshold:t=80}={}){this.cache=e,this.threshold=t}async analyze(e){let t=await this.cache.list(),n=await this._getStorageEstimate(),r=new Set(e.map(e=>String(e.id))),i=[],a=[];for(let e of t)if(r.has(String(e.id)))i.push(e);else if(e.type===`widget`){let t=String(e.id).split(`/`)[0];r.has(t)?i.push(e):a.push(e)}else e.type===`static`?i.push(e):a.push(e);a.sort((e,t)=>(e.cachedAt||0)-(t.cachedAt||0));let o=a.reduce((e,t)=>e+(t.size||0),0),s={timestamp:Date.now(),storage:{usage:n.usage,quota:n.quota,percent:n.quota>0?Math.round(n.usage/n.quota*100):0},files:{required:i.length,orphaned:a.length,total:t.length},orphaned:a.map(e=>({id:e.id,type:e.type,size:e.size||0,cachedAt:e.cachedAt||0})),orphanedSize:o,evicted:[],threshold:this.threshold};if(O.info(`Storage: ${k(n.usage)} / ${k(n.quota)} (${s.storage.percent}%)`),O.info(`Cache: ${i.length} required, ${a.length} orphaned (${k(o)} reclaimable)`),a.length>0)for(let e of a){let t=Date.now()-(e.cachedAt||0),n=Math.floor(t/864e5),r=Math.floor(t%864e5/36e5),i=n>0?`${n}d ago`:`${r}h ago`;O.info(` Orphaned: ${e.type}/${e.id} (${k(e.size||0)}, cached ${i})`)}if(s.storage.percent>this.threshold&&a.length>0){O.warn(`Storage exceeds ${this.threshold}% threshold — evicting orphaned files`);let e=n.usage-n.quota*this.threshold/100;s.evicted=await this._evict(a,e)}else O.info(`No eviction needed (threshold: ${this.threshold}%)`);return s}async _getStorageEstimate(){try{if(typeof navigator<`u`&&navigator.storage?.estimate){let{usage:e,quota:t}=await navigator.storage.estimate();return{usage:e||0,quota:t||1/0}}}catch(e){O.warn(`Storage estimate unavailable:`,e.message)}return{usage:0,quota:1/0}}async _evict(e,t){let n=[],r=0;for(let i of e){if(r>=t)break;n.push(i),r+=i.size||0}if(n.length===0)return[];try{let e=n.map(e=>({type:e.type,id:e.id}));await this.cache.remove(e);for(let e of n)O.info(` Evicted: ${e.type}/${e.id} (${k(e.size||0)})`);O.info(`Evicted ${n.length} files, freed ${k(r)}`)}catch(e){return O.warn(`Eviction failed:`,e.message),[]}return n.map(e=>({id:e.id,type:e.type,size:e.size||0,cachedAt:e.cachedAt||0}))}},j=t(`Cache`),M=typeof window<`u`&&window.location.pathname.replace(/\/[^/]*$/,``).replace(/\/$/,``)||`/player/pwa`;async function N(t,n,r,i){let a=`${e}/widgets/${t}/${n}/${r}`,o=`<base href="${e}/media/file/">`,s=i;i.includes(`<base `)||(s=i.includes(`<head>`)?i.replace(`<head>`,`<head>`+o):i.includes(`<HEAD>`)?i.replace(`<HEAD>`,`<HEAD>`+o):o+i);let c=`<style>img,video{object-position:center center}</style>`;s.includes(`object-position:center center`)||(s.includes(`</head>`)?s=s.replace(`</head>`,c+`</head>`):s.includes(`</HEAD>`)&&(s=s.replace(`</HEAD>`,c+`</HEAD>`))),s=s.replace(/\[\[ViewPortWidth]]/g,`device-width`),s=s.replace(/https?:\/\/[^\s"')<]+\.m3u8\b/gi,e=>`/stream-proxy?url=`+encodeURIComponent(e));let l=RegExp(`https?://[^"'\\s)]+?(${e.replace(/\//g,`\\/`)}/dependencies/[^"'\\s?)]+)(\\?[^"'\\s)]*)?`,`g`);if(s=s.replace(l,(e,t)=>t),s=s.replace(/(<(?:script|link)\b[^>]*(?:src|href)=")(?!\/|https?:\/\/)(bundle\.min\.js|fonts\.css)(")/g,`$1${e}/dependencies/$2$3`),!s.includes(`xiboICTargetId`)){let e=`<script>var xiboICTargetId = '${r}';<\/script>`;s=s.includes(o)?s.replace(o,o+e):s.includes(`<head>`)?s.replace(`<head>`,`<head>`+e):e+s}return s=s.replace(/hostAddress\s*:\s*["']https?:\/\/[^"']+["']/g,`hostAddress: "${M}/ic"`),j.info(`Injected base tag in widget HTML`),(await fetch(`/store${e}/widgets/${t}/${n}/${r}`,{method:`PUT`,headers:{"Content-Type":`text/html; charset=utf-8`},body:s})).body?.cancel(),j.info(`Stored widget HTML at ${a} (${s.length} bytes)`),{cacheKey:a,html:s}}var P=n.version;export{D as a,S as c,s as d,i as f,b as i,c as l,N as n,w as o,a as p,A as r,T as s,P as t,l as u};
2
- //# sourceMappingURL=src-Dfm-7Za-.js.map
@@ -1 +0,0 @@
1
- import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,p as c,r as l,s as u,t as d,u as f}from"./src-Dfm-7Za-.js";export{i as BARRIER,l as CacheAnalyzer,r as CacheManager,e as DownloadManager,a as FILE_TYPES,s as FileDownload,u as LayoutTaskBuilder,n as StoreClient,d as VERSION,c as cacheManager,o as cacheWidgetHtml,f as getFileTypeConfig,t as isUrlExpired};
@@ -1,16 +0,0 @@
1
- import{o as e,t,v as n}from"./src-CMBYiOs4.js";import{r}from"./main-C-Rkfq5h.js";var i={name:`@xiboplayer/xmds`,version:`0.7.15`,description:`XMDS SOAP client for Xibo CMS communication`,type:`module`,main:`./src/index.js`,types:`./src/index.d.ts`,exports:{".":`./src/index.js`,"./xmds-client":`./src/xmds-client.js`,"./rest-client":`./src/rest-client.js`,"./schedule-parser":`./src/schedule-parser.js`},scripts:{test:`vitest run`,"test:watch":`vitest`,"test:coverage":`vitest run --coverage`},dependencies:{"@xiboplayer/utils":`workspace:*`},devDependencies:{vitest:`^4.1.2`},keywords:[`xibo`,`digital-signage`,`xmds`,`soap`,`cms`],author:`Pau Aliagas <linuxnow@gmail.com>`,license:`AGPL-3.0-or-later`,repository:{type:`git`,url:`git+https://github.com/xibo-players/xiboplayer.git`,directory:`packages/xmds`},homepage:`https://xiboplayer.org`};async function a(e){if(typeof navigator<`u`&&navigator.storage?.estimate)try{let t=await navigator.storage.estimate();e.availableSpace=t.quota-t.usage,e.totalSpace=t.quota}catch{}!e.timeZone&&typeof Intl<`u`&&(e.timeZone=Intl.DateTimeFormat().resolvedOptions().timeZone),e.statusDialog||=`Current Layout: ${e.currentLayoutId||`None`}`}var o=n(`REST`),s=class{constructor(e){this.config=e,this.schemaVersion=7,this.retryOptions=e.retryOptions||{maxRetries:2,baseDelayMs:2e3},this._token=null,this._tokenExpiresAt=0,this._displayId=null,this._etags=new Map,this._responseCache=new Map,this._maxCacheSize=100,o.info(`Using REST transport`)}getRestBaseUrl(){return this._isProxyMode()?`${window.location.origin}${t}`:(this.config.restApiUrl||`${this.config.cmsUrl}${t}`).replace(/\/+$/,``)}_isProxyMode(){return typeof window<`u`&&(window.electronAPI?.isElectron||window.location.hostname===`localhost`)}_cacheSet(e,t,n){if(this._etags.size>=this._maxCacheSize){let e=this._etags.keys().next().value;this._etags.delete(e),this._responseCache.delete(e)}this._etags.set(e,t),this._responseCache.set(e,n)}async _authenticate(){let t=`${this.getRestBaseUrl()}/auth`;o.debug(`Authenticating...`);let n=await e(t,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey})},this.retryOptions);if(!n.ok){let e=await n.text().catch(()=>``);throw Error(`Auth failed: ${n.status} ${n.statusText} ${e}`)}let r=await n.json();this._token=r.token,this._displayId=r.displayId,this._tokenExpiresAt=Date.now()+(r.expiresIn-60)*1e3,o.info(`Authenticated as display ${this._displayId}`)}getToken(){return this._token}async _getToken(){return(!this._token||Date.now()>=this._tokenExpiresAt)&&await this._authenticate(),this._token}async restGet(t,n={},r=!1){let i=await this._getToken(),a=new URL(`${this.getRestBaseUrl()}${t}`);for(let[e,t]of Object.entries(n))a.searchParams.set(e,String(t));let s=t,c={Authorization:`Bearer ${i}`},l=this._etags.get(s);l&&(c[`If-None-Match`]=l),o.debug(`GET ${t}`,n);let u=await e(a.toString(),{method:`GET`,headers:c},this.retryOptions);if(u.status===401){if(r)throw Error(`REST GET ${t} failed: 401 Unauthorized (after re-auth)`);return this._token=null,this.restGet(t,n,!0)}if(u.status===304){let e=this._responseCache.get(s);if(e)return o.debug(`${t} → 304 (using cache)`),e}if(!u.ok){let e=await u.text().catch(()=>``);throw Error(`REST GET ${t} failed: ${u.status} ${u.statusText} ${e}`)}let d=u.headers.get(`Content-Type`)||``,f;f=d.includes(`application/json`)?await u.json():await u.text();let p=u.headers.get(`ETag`);return p&&this._cacheSet(s,p,f),f}async restSend(t,n,r={},i=!1){let a=await this._getToken(),s=new URL(`${this.getRestBaseUrl()}${n}`);o.debug(`${t} ${n}`);let c=await e(s.toString(),{method:t,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${a}`},body:JSON.stringify(r)},this.retryOptions);if(c.status===401){if(i)throw Error(`REST ${t} ${n} failed: 401 Unauthorized (after re-auth)`);return this._token=null,this.restSend(t,n,r,!0)}if(!c.ok){let e=await c.text().catch(()=>``);throw Error(`REST ${t} ${n} failed: ${c.status} ${c.statusText} ${e}`)}return(c.headers.get(`Content-Type`)||``).includes(`application/json`)?await c.json():await c.text()}async registerDisplay(){await this._getToken();let e=typeof navigator<`u`?`${navigator.platform} ${navigator.userAgent}`:`unknown`,t=await this.restSend(`POST`,`/displays`,{displayName:this.config.displayName,clientType:this.config.clientType||`linux`,clientVersion:this.config.clientVersion||`0.1.0`,clientCode:this.config.clientCode||400,operatingSystem:e,macAddress:this.config.macAddress||`n/a`,xmrChannel:this.config.xmrChannel,xmrPubKey:this.config.xmrPubKey||``});return this._parseRegisterDisplayJson(t)}_parseRegisterDisplayJson(e){let t=e.display||e,n=t[`@attributes`]||{},r=n.code||t.code,i=n.message||t.message||``;if(r!==`READY`)return{code:r,message:i,settings:null};let a={},o=[],s=[];for(let[e,n]of Object.entries(t))if(!(e===`@attributes`||e===`file`)){if(e===`commands`){Array.isArray(n)&&(s=n.map(e=>({commandCode:e.code||e.commandCode||``,commandString:e.commandString||``})));continue}if(e===`tags`){let e=e=>typeof e==`object`?e.tag||e.value||``:String(e);if(Array.isArray(n))o=n.map(e).filter(Boolean);else if(n&&typeof n==`object`){let t=e(n);t&&(o=[t])}else typeof n==`string`&&n&&(o=[n]);continue}a[e]=typeof n==`object`?JSON.stringify(n):String(n)}let c=n.checkRf||``,l=n.checkSchedule||``,u={date:n.date||t.date||null,timezone:n.timezone||t.timezone||null,status:n.status||t.status||null,localDate:n.localDate||t.localDate||null,version_instructions:n.version_instructions||t.version_instructions||null},d=t.syncConfig||(t.syncGroup?{syncGroup:String(t.syncGroup),syncPublisherPort:parseInt(t.syncPublisherPort||`9590`,10),syncSwitchDelay:parseInt(t.syncSwitchDelay||`750`,10),syncVideoPauseDelay:parseInt(t.syncVideoPauseDelay||`100`,10),isLead:String(t.syncGroup)===`lead`}:null);return{code:r,message:i,settings:a,tags:o,commands:s,displayAttrs:u,checkRf:c,checkSchedule:l,syncConfig:d}}async requiredFiles(){let e=await this.restGet(`/displays/${this._displayId}/media`);return this._parseRequiredFilesV2(e)}_parseRequiredFilesV2(e){let t=[];for(let n of e.media||[])t.push({type:n.type||`media`,id:n.id==null?null:String(n.id),size:n.fileSize||0,md5:n.md5||null,download:`http`,path:n.url||null,saveAs:n.saveAs||null,fileType:null,code:null,layoutid:null,regionid:null,mediaid:null});for(let n of e.layouts||[])t.push({type:`layout`,id:n.id==null?null:String(n.id),size:n.fileSize||0,md5:n.md5||null,download:`http`,path:n.url||null,saveAs:null,fileType:null,code:null,layoutid:null,regionid:null,mediaid:null});for(let n of e.widgets||[])t.push({type:`dataset`,id:n.id==null?null:String(n.id),size:0,md5:n.md5||null,download:`http`,path:n.url||null,saveAs:null,fileType:null,code:null,layoutid:null,regionid:null,mediaid:null,updateInterval:n.updateInterval||0});for(let n of e.dependencies||[])t.push({type:`static`,id:n.id==null?null:String(n.id),size:n.fileSize||0,md5:n.md5||null,download:`http`,path:n.url||null,saveAs:null,fileType:n.type||null,code:null,layoutid:null,regionid:null,mediaid:null});return{files:t,purge:[]}}async schedule(){return this.restGet(`/displays/${this._displayId}/schedule`)}async getResource(e,t,n){return this.restGet(`/widgets/${e}/${t}/${n}`)}async notifyStatus(e){return await a(e),this.restSend(`PUT`,`/displays/${this._displayId}/status`,{statusData:e})}async mediaInventory(e){let t=Array.isArray(e)?{inventoryItems:e}:{inventory:e};return this.restSend(`PUT`,`/displays/${this._displayId}/inventory`,t)}async blackList(e,t,n){return o.warn(`BlackList not available in v2 API (${t}/${e}: ${n})`),!1}async submitLog(e,t=null){let n=Array.isArray(e)?{logs:e}:{logXml:e};return(await this.restSend(`POST`,`/displays/${this._displayId}/logs`,n))?.success===!0}async submitScreenShot(e){return(await this.restSend(`POST`,`/displays/${this._displayId}/screenshot`,{screenshot:e}))?.success===!0}async submitStats(e,t=null){try{let t=Array.isArray(e)?{stats:e}:{statXml:e},n=(await this.restSend(`POST`,`/displays/${this._displayId}/stats`,t))?.success===!0;return o.info(`SubmitStats result: ${n}`),n}catch(e){throw o.error(`SubmitStats failed:`,e),e}}async reportFaults(e){return(await this.restSend(`POST`,`/displays/${this._displayId}/faults`,{fault:e}))?.success===!0}async getWeather(){return this.restGet(`/displays/${this._displayId}/weather`)}static async isAvailable(n,r){try{let i=`${typeof window<`u`&&(window.electronAPI?.isElectron||window.location.hostname===`localhost`)?``:n.replace(/\/+$/,``)}${t}/health`,a=r?.timeoutMs||8e3,o={method:`GET`};typeof AbortSignal<`u`&&AbortSignal.timeout&&(o.signal=AbortSignal.timeout(a));let s=await e(i,o,r||{maxRetries:0});if(!s.ok)return!1;let c=await s.json();return c.version===2&&c.status===`ok`}catch{return!1}}};function c(e){let t=[];for(let n of e.children)n.tagName===`criteria`&&t.push({metric:n.getAttribute(`metric`)||``,condition:n.getAttribute(`condition`)||``,type:n.getAttribute(`type`)||`string`,value:n.textContent||``});return t}function l(e){let t=new DOMParser().parseFromString(e,`text/xml`),n={default:null,defaultDependants:[],dependants:[],layouts:[],campaigns:[],overlays:[],actions:[],commands:[],dataConnectors:[]},r=t.querySelector(`schedule`);if(r){let e=Array.from(r.children).filter(e=>e.tagName===`dependants`);for(let t of e)if(t.parentElement===r)for(let e of t.querySelectorAll(`file`))e.textContent&&n.dependants.push(e.textContent)}let i=t.querySelector(`default`);if(i){n.default=i.getAttribute(`file`);let e=i.querySelectorAll(`dependants > file`);e.length>0&&(n.defaultDependants=[...e].map(e=>e.textContent))}for(let e of t.querySelectorAll(`campaign`)){let t={id:e.getAttribute(`id`),priority:parseInt(e.getAttribute(`priority`)||`0`),fromdt:e.getAttribute(`fromdt`),todt:e.getAttribute(`todt`),scheduleid:e.getAttribute(`scheduleid`),maxPlaysPerHour:parseInt(e.getAttribute(`maxPlaysPerHour`)||`0`),shareOfVoice:parseInt(e.getAttribute(`shareOfVoice`)||`0`),isGeoAware:e.getAttribute(`isGeoAware`)===`1`,geoLocation:e.getAttribute(`geoLocation`)||``,syncEvent:e.getAttribute(`syncEvent`)===`1`,recurrenceType:e.getAttribute(`recurrenceType`)||null,recurrenceDetail:parseInt(e.getAttribute(`recurrenceDetail`)||`0`)||null,recurrenceRepeatsOn:e.getAttribute(`recurrenceRepeatsOn`)||null,recurrenceRange:e.getAttribute(`recurrenceRange`)||null,criteria:c(e),layouts:[]};for(let n of e.querySelectorAll(`layout`)){let e=n.getAttribute(`file`),r=n.querySelectorAll(`dependants > file`);t.layouts.push({id:String(e),file:e,fromdt:n.getAttribute(`fromdt`)||t.fromdt,todt:n.getAttribute(`todt`)||t.todt,scheduleid:t.scheduleid,priority:t.priority,campaignId:t.id,maxPlaysPerHour:parseInt(n.getAttribute(`maxPlaysPerHour`)||`0`),isGeoAware:n.getAttribute(`isGeoAware`)===`1`,geoLocation:n.getAttribute(`geoLocation`)||``,syncEvent:n.getAttribute(`syncEvent`)===`1`,shareOfVoice:parseInt(n.getAttribute(`shareOfVoice`)||`0`),duration:parseInt(n.getAttribute(`duration`)||`0`),cyclePlayback:n.getAttribute(`cyclePlayback`)===`1`,groupKey:n.getAttribute(`groupKey`)||null,playCount:parseInt(n.getAttribute(`playCount`)||`0`),dependants:r.length>0?[...r].map(e=>e.textContent):[],criteria:c(n)})}n.campaigns.push(t)}for(let e of t.querySelectorAll(`schedule > layout`)){let t=e.getAttribute(`file`),r=e.querySelectorAll(`dependants > file`);n.layouts.push({id:String(t),file:t,fromdt:e.getAttribute(`fromdt`),todt:e.getAttribute(`todt`),scheduleid:e.getAttribute(`scheduleid`),priority:parseInt(e.getAttribute(`priority`)||`0`),campaignId:null,maxPlaysPerHour:parseInt(e.getAttribute(`maxPlaysPerHour`)||`0`),isGeoAware:e.getAttribute(`isGeoAware`)===`1`,geoLocation:e.getAttribute(`geoLocation`)||``,syncEvent:e.getAttribute(`syncEvent`)===`1`,shareOfVoice:parseInt(e.getAttribute(`shareOfVoice`)||`0`),duration:parseInt(e.getAttribute(`duration`)||`0`),cyclePlayback:e.getAttribute(`cyclePlayback`)===`1`,groupKey:e.getAttribute(`groupKey`)||null,playCount:parseInt(e.getAttribute(`playCount`)||`0`),recurrenceType:e.getAttribute(`recurrenceType`)||null,recurrenceDetail:parseInt(e.getAttribute(`recurrenceDetail`)||`0`)||null,recurrenceRepeatsOn:e.getAttribute(`recurrenceRepeatsOn`)||null,recurrenceRange:e.getAttribute(`recurrenceRange`)||null,dependants:r.length>0?[...r].map(e=>e.textContent):[],criteria:c(e)})}let a=t.querySelector(`overlays`);if(a)for(let e of a.querySelectorAll(`overlay`)){let t=e.getAttribute(`file`);n.overlays.push({id:String(t),duration:parseInt(e.getAttribute(`duration`)||`60`),file:t,fromdt:e.getAttribute(`fromdt`),todt:e.getAttribute(`todt`),priority:parseInt(e.getAttribute(`priority`)||`0`),scheduleid:e.getAttribute(`scheduleid`),isGeoAware:e.getAttribute(`isGeoAware`)===`1`,geoLocation:e.getAttribute(`geoLocation`)||``,syncEvent:e.getAttribute(`syncEvent`)===`1`,maxPlaysPerHour:parseInt(e.getAttribute(`maxPlaysPerHour`)||`0`),recurrenceType:e.getAttribute(`recurrenceType`)||null,recurrenceDetail:parseInt(e.getAttribute(`recurrenceDetail`)||`0`)||null,recurrenceRepeatsOn:e.getAttribute(`recurrenceRepeatsOn`)||null,recurrenceRange:e.getAttribute(`recurrenceRange`)||null,criteria:c(e)})}let o=t.querySelector(`actions`);if(o)for(let e of o.querySelectorAll(`action`))n.actions.push({actionType:e.getAttribute(`actionType`)||``,triggerCode:e.getAttribute(`triggerCode`)||``,layoutCode:e.getAttribute(`layoutCode`)||``,commandCode:e.getAttribute(`commandCode`)||``,duration:parseInt(e.getAttribute(`duration`)||`0`),fromdt:e.getAttribute(`fromdt`),todt:e.getAttribute(`todt`),priority:parseInt(e.getAttribute(`priority`)||`0`),scheduleid:e.getAttribute(`scheduleid`),isGeoAware:e.getAttribute(`isGeoAware`)===`1`,geoLocation:e.getAttribute(`geoLocation`)||``});for(let e of t.querySelectorAll(`schedule > command`))n.commands.push({code:e.getAttribute(`code`)||``,date:e.getAttribute(`date`)||``});let s=t.querySelector(`dataConnectors`);if(s)for(let e of s.querySelectorAll(`connector`))n.dataConnectors.push({id:e.getAttribute(`id`)||``,dataConnectorId:e.getAttribute(`dataConnectorId`)||``,dataSetId:e.getAttribute(`dataSetId`)||``,dataKey:e.getAttribute(`dataKey`)||``,dataParams:e.getAttribute(`dataParams`)||``,js:e.getAttribute(`js`)||``,url:e.getAttribute(`url`)||``,updateInterval:parseInt(e.getAttribute(`updateInterval`)||`300`,10)});return n}var u=n(`XMDS`),d=class{constructor(e){this.config=e,this.schemaVersion=5,this.retryOptions=e.retryOptions||{maxRetries:2,baseDelayMs:2e3}}buildEnvelope(e,t){return`<?xml version="1.0" encoding="UTF-8"?>
2
- <soap:Envelope
3
- xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
4
- xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
5
- xmlns:tns="urn:xmds"
6
- xmlns:types="urn:xmds/encodedTypes"
7
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
8
- xmlns:xsd="http://www.w3.org/2001/XMLSchema">
9
- <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
10
- <tns:${e}>
11
- ${Object.entries(t).map(([e,t])=>`<${e} xsi:type="xsd:string">${String(t).replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}</${e}>`).join(`
12
- `)}
13
- </tns:${e}>
14
- </soap:Body>
15
- </soap:Envelope>`}rewriteXmdsUrl(e){return typeof window<`u`&&(window.electronAPI?.isElectron||window.location.hostname===`localhost`)?`/xmds-proxy?cms=${encodeURIComponent(e)}`:`${e}/xmds.php`}async call(t,n={}){let r=this.rewriteXmdsUrl(this.config.cmsUrl),i=`${r}${r.includes(`?`)?`&`:`?`}v=${this.schemaVersion}&method=${t}`,a=this.buildEnvelope(t,n);u.debug(`${t}`,n),u.debug(`URL: ${i}`);let o=await e(i,{method:`POST`,headers:{"Content-Type":`text/xml; charset=utf-8`},body:a},this.retryOptions);if(!o.ok)throw Error(`XMDS ${t} failed: ${o.status} ${o.statusText}`);let s=await o.text();return this.parseResponse(s,t)}parseResponse(e,t){let n=new DOMParser().parseFromString(e,`text/xml`),r=n.querySelector(`Fault`);if(r||=Array.from(n.querySelectorAll(`*`)).find(e=>e.localName===`Fault`||e.tagName.endsWith(`:Fault`)),r){let e=r.querySelector(`faultstring`)?.textContent||Array.from(r.querySelectorAll(`*`)).find(e=>e.localName===`faultstring`)?.textContent||`Unknown SOAP fault`;throw Error(`SOAP Fault: ${e}`)}let i=`${t}Response`,a=n.querySelector(i);if(a||=Array.from(n.querySelectorAll(`*`)).find(e=>e.localName===i||e.tagName.endsWith(`:`+i)),!a)throw Error(`No ${i} element in SOAP response`);let o=a.firstElementChild;return o?o.textContent:null}async registerDisplay(){let e=`${navigator.platform} ${navigator.userAgent}`,t=await this.call(`RegisterDisplay`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey,displayName:this.config.displayName,clientType:this.config.clientType||`linux`,clientVersion:this.config.clientVersion||`0.1.0`,clientCode:this.config.clientCode||`400`,operatingSystem:e,macAddress:this.config.macAddress||`n/a`,xmrChannel:this.config.xmrChannel||``,xmrPubKey:this.config.xmrPubKey||``,licenceResult:`licensed`});return this.parseRegisterDisplayResponse(t)}parseRegisterDisplayResponse(e){let t=new DOMParser().parseFromString(e,`text/xml`).querySelector(`display`);if(!t)throw Error(`Invalid RegisterDisplay response: no <display> element`);let n=t.getAttribute(`code`),r=t.getAttribute(`message`);if(n!==`READY`)return{code:n,message:r,settings:null};let i={},a=[],o=[];for(let e of t.children){let t=e.tagName.toLowerCase();if(t!==`file`){if(t===`commands`){for(let t of e.querySelectorAll(`command`))o.push({commandCode:t.getAttribute(`code`)||t.getAttribute(`commandCode`)||``,commandString:t.getAttribute(`commandString`)||``});continue}if(t===`tags`){for(let t of e.querySelectorAll(`tag`))t.textContent&&a.push(t.textContent);continue}i[e.tagName]=e.textContent}}let s=t.getAttribute(`checkRf`)||``,c=t.getAttribute(`checkSchedule`)||``,l={date:t.getAttribute(`date`)||null,timezone:t.getAttribute(`timezone`)||null,status:t.getAttribute(`status`)||null,localDate:t.getAttribute(`localDate`)||null,version_instructions:t.getAttribute(`version_instructions`)||null},u=i.syncGroup||null;return{code:n,message:r,settings:i,tags:a,commands:o,displayAttrs:l,checkRf:s,checkSchedule:c,syncConfig:u?{syncGroup:u,syncPublisherPort:parseInt(i.syncPublisherPort||`9590`,10),syncSwitchDelay:parseInt(i.syncSwitchDelay||`750`,10),syncVideoPauseDelay:parseInt(i.syncVideoPauseDelay||`100`,10),isLead:u===`lead`}:null}}async requiredFiles(){let e=await this.call(`RequiredFiles`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey});return this.parseRequiredFilesResponse(e)}parseRequiredFilesResponse(e){let n=new DOMParser().parseFromString(e,`text/xml`),r=[];for(let e of n.querySelectorAll(`file`)){let n={type:e.getAttribute(`type`),id:e.getAttribute(`id`),size:parseInt(e.getAttribute(`size`)||`0`),md5:e.getAttribute(`md5`),download:e.getAttribute(`download`),path:e.getAttribute(`path`),saveAs:e.getAttribute(`saveAs`)||null,fileType:e.getAttribute(`fileType`)||null,code:e.getAttribute(`code`),layoutid:e.getAttribute(`layoutid`),regionid:e.getAttribute(`regionid`),mediaid:e.getAttribute(`mediaid`)};if(n.path&&n.path.includes(`xmds.php`)){n.cmsDownloadUrl=n.path;let e=n.fileType;e===`L`||n.type===`layout`?n.path=`${t}/layouts/${n.id}`:e===`P`?n.path=`${t}/dependencies/${n.saveAs||n.id}`:n.path=`${t}/media/file/${n.saveAs||n.id}`}r.push(n)}let i=[],a=n.querySelector(`purge`);if(a)for(let e of a.querySelectorAll(`item`))i.push({id:e.getAttribute(`id`),storedAs:e.getAttribute(`storedAs`)});return{files:r,purge:i}}async schedule(){return l(await this.call(`Schedule`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey}))}async getResource(e,t,n){return await this.call(`GetResource`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey,layoutId:String(e),regionId:String(t),mediaId:String(n)})}async notifyStatus(e){return await a(e),await this.call(`NotifyStatus`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey,status:JSON.stringify(e)})}async mediaInventory(e){return await this.call(`MediaInventory`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey,mediaInventory:e})}async blackList(e,t,n){try{let r=await this.call(`BlackList`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey,mediaId:String(e),type:t||`media`,reason:n||`Failed to render`});return u.info(`BlackListed ${t}/${e}: ${n}`),r===`true`}catch(e){return u.warn(`BlackList failed:`,e),!1}}async submitLog(e,t=null){return await this.call(`SubmitLog`,{serverKey:this.config.cmsKey,hardwareKey:t||this.config.hardwareKey,logXml:e})===`true`}async submitScreenShot(e){return await this.call(`SubmitScreenShot`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey,screenShot:e})===`true`}async reportFaults(e){return this.call(`ReportFaults`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey,fault:e})}async getWeather(){return this.call(`GetWeather`,{serverKey:this.config.cmsKey,hardwareKey:this.config.hardwareKey})}async submitStats(e,t=null){try{let n=await this.call(`SubmitStats`,{serverKey:this.config.cmsKey,hardwareKey:t||this.config.hardwareKey,statXml:e})===`true`;return u.info(`SubmitStats result: ${n}`),n}catch(e){throw u.error(`SubmitStats failed:`,e),e}}},f=[`registerDisplay`,`requiredFiles`,`schedule`,`getResource`,`notifyStatus`,`mediaInventory`,`blackList`,`submitLog`,`submitScreenShot`,`submitStats`,`reportFaults`,`getWeather`];function p(e,t=`client`){for(let n of f)if(typeof e[n]!=`function`)throw Error(`${t} missing CmsClient method: ${n}()`)}var m=n(`Protocol`),h=3e3,g=class{constructor(e,t,n,r={}){this.cmsUrl=e,this.RestClient=t,this.XmdsClient=n,this.probeTimeoutMs=r.probeTimeoutMs||h,this.protocol=null,this.lastProbeTime=0}async probe(){let e=await this.RestClient.isAvailable(this.cmsUrl,{maxRetries:0,timeoutMs:this.probeTimeoutMs});return this.lastProbeTime=Date.now(),e}async detect(e,t){if(t===`rest`){this.protocol=`rest`,m.info(`Using REST transport (forced)`);let t=new this.RestClient(e);return p(t,`RestClient`),{client:t,protocol:`rest`}}if(t===`xmds`){this.protocol=`xmds`,m.info(`Using XMDS/SOAP transport (forced)`);let t=new this.XmdsClient(e);return p(t,`XmdsClient`),{client:t,protocol:`xmds`}}m.info(`Probing CMS for REST API availability...`);let n=!1;try{n=await this.probe()}catch(e){m.warn(`REST probe failed:`,e?.message||e)}if(n){this.protocol=`rest`,m.info(`REST transport detected — using PlayerRestApi`);let t=new this.RestClient(e);return p(t,`RestClient`),{client:t,protocol:`rest`}}this.protocol=`xmds`,m.info(`REST unavailable — using XMDS/SOAP transport`);let r=new this.XmdsClient(e);return p(r,`XmdsClient`),{client:r,protocol:`xmds`}}async reprobe(e){let t=this.protocol;m.info(`Re-probing CMS protocol...`);let n=!1;try{n=await this.probe()}catch(e){m.warn(`Re-probe failed:`,e?.message||e)}let r=n?`rest`:`xmds`;if(r!==t){m.info(`Protocol changed: ${t} → ${r}`),this.protocol=r;let i=n?new this.RestClient(e):new this.XmdsClient(e);return p(i,n?`RestClient`:`XmdsClient`),{client:i,protocol:r,changed:!0}}return m.info(`Protocol unchanged: ${r}`),{client:null,protocol:r,changed:!1}}getProtocol(){return this.protocol}},_=r({CMS_CLIENT_METHODS:()=>f,ProtocolDetector:()=>g,RestClient:()=>s,VERSION:()=>v,XmdsClient:()=>d,assertCmsClient:()=>p,parseScheduleResponse:()=>l}),v=i.version;export{d as n,s as r,_ as t};
16
- //# sourceMappingURL=src-DpE7HVLC.js.map
@@ -1 +0,0 @@
1
- import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c}from"./src-DPOUYQMT.js";export{o as InterruptScheduler,i as OverlayScheduler,n as ScheduleManager,c as VERSION,a as buildScheduleQueue,s as calculateTimeline,t as parseLayoutDuration,r as parseLayoutFile,e as scheduleManager};