UNPKG

tsdav

Version:

WebDAV, CALDAV, and CARDDAV client for Nodejs and the Browser

2 lines (1 loc) 35.2 kB
import"cross-fetch/polyfill";import e from"debug";import t from"xml-js";import{encode as r}from"base-64";var a;!function(e){e.CALENDAR_SERVER="http://calendarserver.org/ns/",e.CALDAV_APPLE="http://apple.com/ns/ical/",e.CALDAV="urn:ietf:params:xml:ns:caldav",e.CARDDAV="urn:ietf:params:xml:ns:carddav",e.DAV="DAV:"}(a||(a={}));const s={[a.CALDAV]:"xmlns:c",[a.CARDDAV]:"xmlns:card",[a.CALENDAR_SERVER]:"xmlns:cs",[a.CALDAV_APPLE]:"xmlns:ca",[a.DAV]:"xmlns:d"};var o,n;!function(e){e.CALDAV="c",e.CARDDAV="card",e.CALENDAR_SERVER="cs",e.CALDAV_APPLE="ca",e.DAV="d"}(o||(o={})),function(e){e.VEVENT="VEVENT",e.VTODO="VTODO",e.VJOURNAL="VJOURNAL",e.VFREEBUSY="VFREEBUSY",e.VTIMEZONE="VTIMEZONE",e.VALARM="VALARM"}(n||(n={}));const c=e=>{const t=Number(e);if(!Number.isNaN(t))return t;const r=e.toLowerCase();return"true"===r||"false"!==r&&e},d=(e,t)=>{if(!e&&!t)return!0;if(!e||!t)return!1;const r=e.trim(),a=t.trim();if(Math.abs(r.length-a.length)>1)return!1;const s="/"===r.slice(-1)?r.slice(0,-1):r,o="/"===a.slice(-1)?a.slice(0,-1):a;return e.includes(o)||t.includes(s)},i=(e,t)=>{if(!e&&!t)return!0;if(!e||!t)return!1;const r=e.trim(),a=t.trim(),s="/"===r.slice(-1)?r.slice(0,-1):r,o="/"===a.slice(-1)?a.slice(0,-1):a;return e.includes(o)||t.includes(s)},l=e=>e.reduce(((e,t)=>({...e,[s[t]]:t})),{}),u=e=>Object.entries(e).reduce(((e,[t,r])=>r?{...e,[t]:r}:e),{}),h=(e,t)=>t?{[e]:t}:{},p=(e,t)=>e?t&&0!==t.length?Object.fromEntries(Object.entries(e).filter((([e])=>!t.includes(e)))):e:{};var f=Object.freeze({__proto__:null,cleanupFalsy:u,conditionalParam:h,excludeHeaders:p,getDAVAttribute:l,urlContains:i,urlEquals:d});const v=e("tsdav:request"),y=async e=>{var r;const{url:a,init:s,convertIncoming:o=!0,parseOutgoing:n=!0,fetchOptions:d={}}=e,{headers:i={},body:l,namespace:h,method:p,attributes:f}=s,y=o?t.js2xml({_declaration:{_attributes:{version:"1.0",encoding:"utf-8"}},...l,_attributes:f},{compact:!0,spaces:2,elementNameFn:e=>h&&!/^.+:.+/.test(e)?`${h}:${e}`:e}):l,O=await fetch(a,{headers:{"Content-Type":"text/xml;charset=UTF-8",...u(i)},body:y,method:p,...d}),m=await O.text();if(!O.ok||!(null===(r=O.headers.get("content-type"))||void 0===r?void 0:r.includes("xml"))||!n)return[{href:O.url,ok:O.ok,status:O.status,statusText:O.statusText,raw:m}];const A=t.xml2js(m,{compact:!0,trim:!0,textFn:(e,t)=>{try{const r=t._parent,a=Object.keys(r),s=a[a.length-1],o=r[s];if(o.length>0){o[o.length-1]=c(e)}else r[s]=c(e)}catch(e){v(e.stack)}},elementNameFn:e=>e.replace(/^.+:/,"").replace(/([-_]\w)/g,(e=>e[1].toUpperCase())),attributesFn:e=>{const t={...e};return delete t.xmlns,t},ignoreDeclaration:!0});return(Array.isArray(A.multistatus.response)?A.multistatus.response:[A.multistatus.response]).map((e=>{var t,r;if(!e)return{status:O.status,statusText:O.statusText,ok:O.ok};const a=/^\S+\s(?<status>\d+)\s(?<statusText>.+)$/.exec(e.status);return{raw:A,href:e.href,status:(null==a?void 0:a.groups)?Number.parseInt(null==a?void 0:a.groups.status,10):O.status,statusText:null!==(r=null===(t=null==a?void 0:a.groups)||void 0===t?void 0:t.statusText)&&void 0!==r?r:O.statusText,ok:!e.error,error:e.error,responsedescription:e.responsedescription,props:(Array.isArray(e.propstat)?e.propstat:[e.propstat]).reduce(((e,t)=>({...e,...null==t?void 0:t.prop})),{})}}))},O=async e=>{const{url:t,props:r,depth:s,headers:n,headersToExclude:c,fetchOptions:d={}}=e;return y({url:t,init:{method:"PROPFIND",headers:p(u({depth:s,...n}),c),namespace:o.DAV,body:{propfind:{_attributes:l([a.CALDAV,a.CALDAV_APPLE,a.CALENDAR_SERVER,a.CARDDAV,a.DAV]),prop:r}}},fetchOptions:d})},m=async e=>{const{url:t,data:r,headers:a,headersToExclude:s,fetchOptions:o={}}=e;return fetch(t,{method:"PUT",body:r,headers:p(a,s),...o})},A=async e=>{const{url:t,data:r,etag:a,headers:s,headersToExclude:o,fetchOptions:n={}}=e;return fetch(t,{method:"PUT",body:r,headers:p(u({"If-Match":a,...s}),o),...n})},g=async e=>{const{url:t,headers:r,etag:a,headersToExclude:s,fetchOptions:o={}}=e;return fetch(t,{method:"DELETE",headers:p(u({"If-Match":a,...r}),s),...o})};var C=Object.freeze({__proto__:null,createObject:m,davRequest:y,deleteObject:g,propfind:O,updateObject:A});function w(e,t){const r=e=>t.every((t=>e[t]));return Array.isArray(e)?e.every((e=>r(e))):r(e)}const D=(e,t)=>t.reduce(((t,r)=>e[r]?t:`${t.length?`${t},`:""}${r.toString()}`),""),b=e("tsdav:collection"),V=async e=>{const{url:t,body:r,depth:a,defaultNamespace:s=o.DAV,headers:n,headersToExclude:c,fetchOptions:d={}}=e,i=await y({url:t,init:{method:"REPORT",headers:p(u({depth:a,...n}),c),namespace:s,body:r},fetchOptions:d});return 1!==i.length||i[0].raw?i:[]},$=async e=>{const{url:t,props:r,depth:a,headers:s,headersToExclude:n,fetchOptions:c={}}=e;return y({url:t,init:{method:"MKCOL",headers:p(u({depth:a,...s}),n),namespace:o.DAV,body:r?{mkcol:{set:{prop:r}}}:void 0},fetchOptions:c})},E=async e=>{var t,r,a,s,n;const{collection:c,headers:d,headersToExclude:i,fetchOptions:l={}}=e;return null!==(n=null===(s=null===(a=null===(r=null===(t=(await O({url:c.url,props:{[`${o.DAV}:supported-report-set`]:{}},depth:"0",headers:p(d,i),fetchOptions:l}))[0])||void 0===t?void 0:t.props)||void 0===r?void 0:r.supportedReportSet)||void 0===a?void 0:a.supportedReport)||void 0===s?void 0:s.map((e=>Object.keys(e.report)[0])))&&void 0!==n?n:[]},T=async e=>{var t,r,a;const{collection:s,headers:n,headersToExclude:c,fetchOptions:d={}}=e,l=(await O({url:s.url,props:{[`${o.CALENDAR_SERVER}:getctag`]:{}},depth:"0",headers:p(n,c),fetchOptions:d})).filter((e=>i(s.url,e.href)))[0];if(!l)throw new Error("Collection does not exist on server");return{isDirty:`${s.ctag}`!=`${null===(t=l.props)||void 0===t?void 0:t.getctag}`,newCtag:null===(a=null===(r=l.props)||void 0===r?void 0:r.getctag)||void 0===a?void 0:a.toString()}},k=e=>{const{url:t,props:r,headers:s,syncLevel:n,syncToken:c,headersToExclude:d,fetchOptions:i}=e;return y({url:t,init:{method:"REPORT",namespace:o.DAV,headers:p({...s},d),body:{"sync-collection":{_attributes:l([a.CALDAV,a.CARDDAV,a.DAV]),"sync-level":n,"sync-token":c,[`${o.DAV}:prop`]:r}}},fetchOptions:i})},U=async e=>{var t,r,a,s,n,c,d,l,u,h,f;const{collection:v,method:y,headers:O,headersToExclude:m,account:A,detailedResult:g,fetchOptions:C={}}=e,V=["accountType","homeUrl"];if(!A||!w(A,V)){if(!A)throw new Error("no account for smartCollectionSync");throw new Error(`account must have ${D(A,V)} before smartCollectionSync`)}const $=null!=y?y:(null===(t=v.reports)||void 0===t?void 0:t.includes("syncCollection"))?"webdav":"basic";if(b(`smart collection sync with type ${A.accountType} and method ${$}`),"webdav"===$){const e=await k({url:v.url,props:{[`${o.DAV}:getetag`]:{},[`${"caldav"===A.accountType?o.CALDAV:o.CARDDAV}:${"caldav"===A.accountType?"calendar-data":"address-data"}`]:{},[`${o.DAV}:displayname`]:{}},syncLevel:1,syncToken:v.syncToken,headers:p(O,m),fetchOptions:C}),t=e.filter((e=>{var t;const r="caldav"===A.accountType?".ics":".vcf";return(null===(t=e.href)||void 0===t?void 0:t.slice(-4))===r})),u=t.filter((e=>404!==e.status)).map((e=>e.href)),h=t.filter((e=>404===e.status)).map((e=>e.href)),f=(u.length&&null!==(a=await(null===(r=null==v?void 0:v.objectMultiGet)||void 0===r?void 0:r.call(v,{url:v.url,props:{[`${o.DAV}:getetag`]:{},[`${"caldav"===A.accountType?o.CALDAV:o.CARDDAV}:${"caldav"===A.accountType?"calendar-data":"address-data"}`]:{}},objectUrls:u,depth:"1",headers:p(O,m),fetchOptions:C})))&&void 0!==a?a:[]).map((e=>{var t,r,a,s,o,n,c,d,i,l;return{url:null!==(t=e.href)&&void 0!==t?t:"",etag:null===(r=e.props)||void 0===r?void 0:r.getetag,data:"caldav"===(null==A?void 0:A.accountType)?null!==(o=null===(s=null===(a=e.props)||void 0===a?void 0:a.calendarData)||void 0===s?void 0:s._cdata)&&void 0!==o?o:null===(n=e.props)||void 0===n?void 0:n.calendarData:null!==(i=null===(d=null===(c=e.props)||void 0===c?void 0:c.addressData)||void 0===d?void 0:d._cdata)&&void 0!==i?i:null===(l=e.props)||void 0===l?void 0:l.addressData}})),y=null!==(s=v.objects)&&void 0!==s?s:[],w=f.filter((e=>y.every((t=>!i(t.url,e.url))))),D=y.reduce(((e,t)=>{const r=f.find((e=>i(e.url,t.url)));return r&&r.etag&&r.etag!==t.etag?[...e,r]:e}),[]),b=h.map((e=>({url:e,etag:""}))),V=y.filter((e=>f.some((t=>i(e.url,t.url)&&t.etag===e.etag))));return{...v,objects:g?{created:w,updated:D,deleted:b}:[...V,...w,...D],syncToken:null!==(l=null===(d=null===(c=null===(n=e[0])||void 0===n?void 0:n.raw)||void 0===c?void 0:c.multistatus)||void 0===d?void 0:d.syncToken)&&void 0!==l?l:v.syncToken}}if("basic"===$){const{isDirty:e,newCtag:t}=await T({collection:v,headers:p(O,m),fetchOptions:C}),r=null!==(u=v.objects)&&void 0!==u?u:[],a=null!==(f=await(null===(h=v.fetchObjects)||void 0===h?void 0:h.call(v,{collection:v,headers:p(O,m),fetchOptions:C})))&&void 0!==f?f:[],s=a.filter((e=>r.every((t=>!i(t.url,e.url))))),o=r.reduce(((e,t)=>{const r=a.find((e=>i(e.url,t.url)));return r&&r.etag&&r.etag!==t.etag?[...e,r]:e}),[]),n=r.filter((e=>a.every((t=>!i(t.url,e.url))))),c=r.filter((e=>a.some((t=>i(e.url,t.url)&&t.etag===e.etag))));if(e)return{...v,objects:g?{created:s,updated:o,deleted:n}:[...c,...s,...o],ctag:t}}return g?{...v,objects:{created:[],updated:[],deleted:[]}}:v};var _=Object.freeze({__proto__:null,collectionQuery:V,isCollectionDirty:T,makeCollection:$,smartCollectionSync:U,supportedReportSet:E,syncCollection:k});const R=e("tsdav:addressBook"),L=async e=>{const{url:t,props:r,filters:s,depth:n,headers:c,headersToExclude:d,fetchOptions:i={}}=e;return V({url:t,body:{"addressbook-query":u({_attributes:l([a.CARDDAV,a.DAV]),[`${o.DAV}:prop`]:r,filter:null!=s?s:{"prop-filter":{_attributes:{name:"FN"}}}})},defaultNamespace:o.CARDDAV,depth:n,headers:p(c,d),fetchOptions:i})},j=async e=>{const{url:t,props:r,objectUrls:s,depth:n,headers:c,headersToExclude:d,fetchOptions:i={}}=e;return V({url:t,body:{"addressbook-multiget":u({_attributes:l([a.DAV,a.CARDDAV]),[`${o.DAV}:prop`]:r,[`${o.DAV}:href`]:s})},defaultNamespace:o.CARDDAV,depth:n,headers:p(c,d),fetchOptions:i})},x=async e=>{const{account:t,headers:r,props:a,headersToExclude:s,fetchOptions:n={}}=null!=e?e:{},c=["homeUrl","rootUrl"];if(!t||!w(t,c)){if(!t)throw new Error("no account for fetchAddressBooks");throw new Error(`account must have ${D(t,c)} before fetchAddressBooks`)}const d=await O({url:t.homeUrl,props:null!=a?a:{[`${o.DAV}:displayname`]:{},[`${o.CALENDAR_SERVER}:getctag`]:{},[`${o.DAV}:resourcetype`]:{},[`${o.DAV}:sync-token`]:{}},depth:"1",headers:p(r,s),fetchOptions:n});return Promise.all(d.filter((e=>{var t,r;return Object.keys(null!==(r=null===(t=e.props)||void 0===t?void 0:t.resourcetype)&&void 0!==r?r:{}).includes("addressbook")})).map((e=>{var r,a,s,o,n,c,d,i,l;const u=null!==(s=null===(a=null===(r=e.props)||void 0===r?void 0:r.displayname)||void 0===a?void 0:a._cdata)&&void 0!==s?s:null===(o=e.props)||void 0===o?void 0:o.displayname;return R(`Found address book named ${"string"==typeof u?u:""},\n props: ${JSON.stringify(e.props)}`),{url:new URL(null!==(n=e.href)&&void 0!==n?n:"",null!==(c=t.rootUrl)&&void 0!==c?c:"").href,ctag:null===(d=e.props)||void 0===d?void 0:d.getctag,displayName:"string"==typeof u?u:"",resourcetype:Object.keys(null===(i=e.props)||void 0===i?void 0:i.resourcetype),syncToken:null===(l=e.props)||void 0===l?void 0:l.syncToken}})).map((async e=>({...e,reports:await E({collection:e,headers:p(r,s),fetchOptions:n})}))))},S=async e=>{const{addressBook:t,headers:r,objectUrls:a,headersToExclude:s,urlFilter:n=e=>e,useMultiGet:c=!0,fetchOptions:d={}}=e;R(`Fetching vcards from ${null==t?void 0:t.url}`);const i=["url"];if(!t||!w(t,i)){if(!t)throw new Error("cannot fetchVCards for undefined addressBook");throw new Error(`addressBook must have ${D(t,i)} before fetchVCards`)}const l=(null!=a?a:(await L({url:t.url,props:{[`${o.DAV}:getetag`]:{}},depth:"1",headers:p(r,s),fetchOptions:d})).map((e=>{var t;return e.ok&&null!==(t=e.href)&&void 0!==t?t:""}))).map((e=>e.startsWith("http")||!e?e:new URL(e,t.url).href)).filter(n).map((e=>new URL(e).pathname));let u=[];return l.length>0&&(u=c?await j({url:t.url,props:{[`${o.DAV}:getetag`]:{},[`${o.CARDDAV}:address-data`]:{}},objectUrls:l,depth:"1",headers:p(r,s),fetchOptions:d}):await L({url:t.url,props:{[`${o.DAV}:getetag`]:{},[`${o.CARDDAV}:address-data`]:{}},depth:"1",headers:p(r,s),fetchOptions:d})),u.map((e=>{var r,a,s,o,n,c;return{url:new URL(null!==(r=e.href)&&void 0!==r?r:"",t.url).href,etag:null===(a=e.props)||void 0===a?void 0:a.getetag,data:null!==(n=null===(o=null===(s=e.props)||void 0===s?void 0:s.addressData)||void 0===o?void 0:o._cdata)&&void 0!==n?n:null===(c=e.props)||void 0===c?void 0:c.addressData}}))},N=async e=>{const{addressBook:t,vCardString:r,filename:a,headers:s,headersToExclude:o,fetchOptions:n={}}=e;return m({url:new URL(a,t.url).href,data:r,headers:p({"content-type":"text/vcard; charset=utf-8","If-None-Match":"*",...s},o),fetchOptions:n})},H=async e=>{const{vCard:t,headers:r,headersToExclude:a,fetchOptions:s={}}=e;return A({url:t.url,data:t.data,etag:t.etag,headers:p({"content-type":"text/vcard; charset=utf-8",...r},a),fetchOptions:s})},P=async e=>{const{vCard:t,headers:r,headersToExclude:a,fetchOptions:s={}}=e;return g({url:t.url,etag:t.etag,headers:p(r,a),fetchOptions:s})};var B=Object.freeze({__proto__:null,addressBookMultiGet:j,addressBookQuery:L,createVCard:N,deleteVCard:P,fetchAddressBooks:x,fetchVCards:S,updateVCard:H});const F=e("tsdav:calendar"),I=async e=>{var t,r,a;const{account:s,headers:n,headersToExclude:c,fetchOptions:d={}}=e,l=["principalUrl","rootUrl"];if(!w(s,l))throw new Error(`account must have ${D(s,l)} before fetchUserAddresses`);F(`Fetch user addresses from ${s.principalUrl}`);const u=(await O({url:s.principalUrl,props:{[`${o.CALDAV}:calendar-user-address-set`]:{}},depth:"0",headers:p(n,c),fetchOptions:d})).find((e=>i(s.principalUrl,e.href)));if(!u||!u.ok)throw new Error("cannot find calendarUserAddresses");const h=(null===(a=null===(r=null===(t=null==u?void 0:u.props)||void 0===t?void 0:t.calendarUserAddressSet)||void 0===r?void 0:r.href)||void 0===a?void 0:a.filter(Boolean))||[];return F(`Fetched calendar user addresses ${h}`),h},M=async e=>{const{url:t,props:r,filters:s,timezone:n,depth:c,headers:d,headersToExclude:i,fetchOptions:h={}}=e;return V({url:t,body:{"calendar-query":u({_attributes:l([a.CALDAV,a.CALENDAR_SERVER,a.CALDAV_APPLE,a.DAV]),[`${o.DAV}:prop`]:r,filter:s,timezone:n})},defaultNamespace:o.CALDAV,depth:c,headers:p(d,i),fetchOptions:h})},z=async e=>{const{url:t,props:r,objectUrls:s,filters:n,timezone:c,depth:d,headers:i,headersToExclude:h,fetchOptions:f={}}=e;return V({url:t,body:{"calendar-multiget":u({_attributes:l([a.DAV,a.CALDAV]),[`${o.DAV}:prop`]:r,[`${o.DAV}:href`]:s,filter:n,timezone:c})},defaultNamespace:o.CALDAV,depth:d,headers:p(i,h),fetchOptions:f})},Z=async e=>{const{url:t,props:r,depth:s,headers:n,headersToExclude:c,fetchOptions:d={}}=e;return y({url:t,init:{method:"MKCALENDAR",headers:p(u({depth:s,...n}),c),namespace:o.DAV,body:{[`${o.CALDAV}:mkcalendar`]:{_attributes:l([a.DAV,a.CALDAV,a.CALDAV_APPLE]),set:{prop:r}}}},fetchOptions:d})},G=async e=>{const{headers:t,account:r,props:a,projectedProps:s,headersToExclude:c,fetchOptions:d={}}=null!=e?e:{},i=["homeUrl","rootUrl"];if(!r||!w(r,i)){if(!r)throw new Error("no account for fetchCalendars");throw new Error(`account must have ${D(r,i)} before fetchCalendars`)}const l=await O({url:r.homeUrl,props:null!=a?a:{[`${o.CALDAV}:calendar-description`]:{},[`${o.CALDAV}:calendar-timezone`]:{},[`${o.DAV}:displayname`]:{},[`${o.CALDAV_APPLE}:calendar-color`]:{},[`${o.CALENDAR_SERVER}:getctag`]:{},[`${o.DAV}:resourcetype`]:{},[`${o.CALDAV}:supported-calendar-component-set`]:{},[`${o.DAV}:sync-token`]:{}},depth:"1",headers:p(t,c),fetchOptions:d});return Promise.all(l.filter((e=>{var t,r;return Object.keys(null!==(r=null===(t=e.props)||void 0===t?void 0:t.resourcetype)&&void 0!==r?r:{}).includes("calendar")})).filter((e=>{var t,r,a,s;return(Array.isArray(null===(t=e.props)||void 0===t?void 0:t.supportedCalendarComponentSet.comp)?null===(r=e.props)||void 0===r?void 0:r.supportedCalendarComponentSet.comp.map((e=>e._attributes.name)):[null===(s=null===(a=e.props)||void 0===a?void 0:a.supportedCalendarComponentSet.comp)||void 0===s?void 0:s._attributes.name]).some((e=>Object.values(n).includes(e)))})).map((e=>{var t,a,o,n,c,d,i,l,u,p,f,v,y,O,m,A;const g=null===(t=e.props)||void 0===t?void 0:t.calendarDescription,C=null===(a=e.props)||void 0===a?void 0:a.calendarTimezone;return{description:"string"==typeof g?g:"",timezone:"string"==typeof C?C:"",url:new URL(null!==(o=e.href)&&void 0!==o?o:"",null!==(n=r.rootUrl)&&void 0!==n?n:"").href,ctag:null===(c=e.props)||void 0===c?void 0:c.getctag,calendarColor:null===(d=e.props)||void 0===d?void 0:d.calendarColor,displayName:null!==(l=null===(i=e.props)||void 0===i?void 0:i.displayname._cdata)&&void 0!==l?l:null===(u=e.props)||void 0===u?void 0:u.displayname,components:Array.isArray(null===(p=e.props)||void 0===p?void 0:p.supportedCalendarComponentSet.comp)?null===(f=e.props)||void 0===f?void 0:f.supportedCalendarComponentSet.comp.map((e=>e._attributes.name)):[null===(y=null===(v=e.props)||void 0===v?void 0:v.supportedCalendarComponentSet.comp)||void 0===y?void 0:y._attributes.name],resourcetype:Object.keys(null===(O=e.props)||void 0===O?void 0:O.resourcetype),syncToken:null===(m=e.props)||void 0===m?void 0:m.syncToken,...h("projectedProps",Object.fromEntries(Object.entries(null!==(A=e.props)&&void 0!==A?A:{}).filter((([e])=>null==s?void 0:s[e]))))}})).map((async e=>({...e,reports:await E({collection:e,headers:p(t,c),fetchOptions:d})}))))},Q=async e=>{const{calendar:t,objectUrls:r,filters:a,timeRange:s,headers:n,expand:c,urlFilter:d=e=>Boolean(null==e?void 0:e.includes(".ics")),useMultiGet:i=!0,headersToExclude:l,fetchOptions:u={}}=e;if(s){const e=/^\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\d:\d\d)|Z)?)?)?)?$/i,t=/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(([+-]\d\d:\d\d)|Z)?$/i;if(!(e.test(s.start)&&e.test(s.end)||t.test(s.start)&&t.test(s.end)))throw new Error("invalid timeRange format, not in ISO8601")}F(`Fetching calendar objects from ${null==t?void 0:t.url}`);const h=["url"];if(!t||!w(t,h)){if(!t)throw new Error("cannot fetchCalendarObjects for undefined calendar");throw new Error(`calendar must have ${D(t,h)} before fetchCalendarObjects`)}const f=null!=a?a:[{"comp-filter":{_attributes:{name:"VCALENDAR"},"comp-filter":{_attributes:{name:"VEVENT"},...s?{"time-range":{_attributes:{start:`${new Date(s.start).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`,end:`${new Date(s.end).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`}}}:{}}}}],v=(null!=r?r:(await M({url:t.url,props:{[`${o.DAV}:getetag`]:{...c&&s?{[`${o.CALDAV}:expand`]:{_attributes:{start:`${new Date(s.start).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`,end:`${new Date(s.end).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`}}}:{}}},filters:f,depth:"1",headers:p(n,l),fetchOptions:u})).map((e=>{var t;return null!==(t=e.href)&&void 0!==t?t:""}))).map((e=>e.startsWith("http")||!e?e:new URL(e,t.url).href)).filter(d).map((e=>new URL(e).pathname));let y=[];return v.length>0&&(y=!i||c?await M({url:t.url,props:{[`${o.DAV}:getetag`]:{},[`${o.CALDAV}:calendar-data`]:{...c&&s?{[`${o.CALDAV}:expand`]:{_attributes:{start:`${new Date(s.start).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`,end:`${new Date(s.end).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`}}}:{}}},filters:f,depth:"1",headers:p(n,l),fetchOptions:u}):await z({url:t.url,props:{[`${o.DAV}:getetag`]:{},[`${o.CALDAV}:calendar-data`]:{...c&&s?{[`${o.CALDAV}:expand`]:{_attributes:{start:`${new Date(s.start).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`,end:`${new Date(s.end).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`}}}:{}}},objectUrls:v,depth:"1",headers:p(n,l),fetchOptions:u})),y.map((e=>{var r,a,s,o,n,c;return{url:new URL(null!==(r=e.href)&&void 0!==r?r:"",t.url).href,etag:`${null===(a=e.props)||void 0===a?void 0:a.getetag}`,data:null!==(n=null===(o=null===(s=e.props)||void 0===s?void 0:s.calendarData)||void 0===o?void 0:o._cdata)&&void 0!==n?n:null===(c=e.props)||void 0===c?void 0:c.calendarData}}))},q=async e=>{const{calendar:t,iCalString:r,filename:a,headers:s,headersToExclude:o,fetchOptions:n={}}=e;return m({url:new URL(a,t.url).href,data:r,headers:p({"content-type":"text/calendar; charset=utf-8","If-None-Match":"*",...s},o),fetchOptions:n})},J=async e=>{const{calendarObject:t,headers:r,headersToExclude:a,fetchOptions:s={}}=e;return A({url:t.url,data:t.data,etag:t.etag,headers:p({"content-type":"text/calendar; charset=utf-8",...r},a),fetchOptions:s})},K=async e=>{const{calendarObject:t,headers:r,headersToExclude:a,fetchOptions:s={}}=e;return g({url:t.url,etag:t.etag,headers:p(r,a),fetchOptions:s})},W=async e=>{var t;const{oldCalendars:r,account:a,detailedResult:s,headers:o,headersToExclude:n,fetchOptions:c={}}=e;if(!a)throw new Error("Must have account before syncCalendars");const d=null!==(t=null!=r?r:a.calendars)&&void 0!==t?t:[],l=await G({account:a,headers:p(o,n),fetchOptions:c}),u=l.filter((e=>d.every((t=>!i(t.url,e.url)))));F(`new calendars: ${u.map((e=>e.displayName))}`);const h=d.reduce(((e,t)=>{const r=l.find((e=>i(e.url,t.url)));return r&&(r.syncToken&&`${r.syncToken}`!=`${t.syncToken}`||r.ctag&&`${r.ctag}`!=`${t.ctag}`)?[...e,r]:e}),[]);F(`updated calendars: ${h.map((e=>e.displayName))}`);const f=await Promise.all(h.map((async e=>await U({collection:{...e,objectMultiGet:z},method:"webdav",headers:p(o,n),account:a,fetchOptions:c})))),v=d.filter((e=>l.every((t=>!i(t.url,e.url)))));F(`deleted calendars: ${v.map((e=>e.displayName))}`);const y=d.filter((e=>l.some((t=>i(t.url,e.url)&&(t.syncToken&&`${t.syncToken}`!=`${e.syncToken}`||t.ctag&&`${t.ctag}`!=`${e.ctag}`)))));return s?{created:u,updated:h,deleted:v}:[...y,...u,...f]},Y=async e=>{const{url:t,timeRange:r,depth:s,headers:n,headersToExclude:c,fetchOptions:d={}}=e;if(!r)throw new Error("timeRange is required");{const e=/^\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\d:\d\d)|Z)?)?)?)?$/i,t=/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(([+-]\d\d:\d\d)|Z)?$/i;if(!(e.test(r.start)&&e.test(r.end)||t.test(r.start)&&t.test(r.end)))throw new Error("invalid timeRange format, not in ISO8601")}return(await V({url:t,body:{"free-busy-query":u({_attributes:l([a.CALDAV]),[`${o.CALDAV}:time-range`]:{_attributes:{start:`${new Date(r.start).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`,end:`${new Date(r.end).toISOString().slice(0,19).replace(/[-:.]/g,"")}Z`}}})},defaultNamespace:o.CALDAV,depth:s,headers:p(n,c),fetchOptions:d}))[0]};var X=Object.freeze({__proto__:null,calendarMultiGet:z,calendarQuery:M,createCalendarObject:q,deleteCalendarObject:K,fetchCalendarObjects:Q,fetchCalendarUserAddresses:I,fetchCalendars:G,freeBusyQuery:Y,makeCalendar:Z,syncCalendars:W,updateCalendarObject:J});const ee=e("tsdav:account"),te=async e=>{var t,r;ee("Service discovery...");const{account:a,headers:s,headersToExclude:o,fetchOptions:n={}}=e,c=new URL(a.serverUrl),d=new URL(`/.well-known/${a.accountType}`,c);d.protocol=null!==(t=c.protocol)&&void 0!==t?t:"http";try{const e=await fetch(d.href,{headers:p(s,o),method:"PROPFIND",redirect:"manual",...n});if(e.status>=300&&e.status<400){const t=e.headers.get("Location");if("string"==typeof t&&t.length){ee(`Service discovery redirected to ${t}`);const e=new URL(t,c);return e.hostname===d.hostname&&d.port&&!e.port&&(e.port=d.port),e.protocol=null!==(r=c.protocol)&&void 0!==r?r:"http",e.href}}}catch(e){ee(`Service discovery failed: ${e.stack}`)}return c.href},re=async e=>{var t,r,a,s,n;const{account:c,headers:d,headersToExclude:i,fetchOptions:l={}}=e,u=["rootUrl"];if(!w(c,u))throw new Error(`account must have ${D(c,u)} before fetchPrincipalUrl`);ee(`Fetching principal url from path ${c.rootUrl}`);const[h]=await O({url:c.rootUrl,props:{[`${o.DAV}:current-user-principal`]:{}},depth:"0",headers:p(d,i),fetchOptions:l});if(!h.ok&&(ee(`Fetch principal url failed: ${h.statusText}`),401===h.status))throw new Error("Invalid credentials");return ee(`Fetched principal url ${null===(r=null===(t=h.props)||void 0===t?void 0:t.currentUserPrincipal)||void 0===r?void 0:r.href}`),new URL(null!==(n=null===(s=null===(a=h.props)||void 0===a?void 0:a.currentUserPrincipal)||void 0===s?void 0:s.href)&&void 0!==n?n:"",c.rootUrl).href},ae=async e=>{var t,r;const{account:a,headers:s,headersToExclude:n,fetchOptions:c={}}=e,d=["principalUrl","rootUrl"];if(!w(a,d))throw new Error(`account must have ${D(a,d)} before fetchHomeUrl`);ee(`Fetch home url from ${a.principalUrl}`);const l=(await O({url:a.principalUrl,props:"caldav"===a.accountType?{[`${o.CALDAV}:calendar-home-set`]:{}}:{[`${o.CARDDAV}:addressbook-home-set`]:{}},depth:"0",headers:p(s,n),fetchOptions:c})).find((e=>i(a.principalUrl,e.href)));if(!l||!l.ok)throw new Error("cannot find homeUrl");const u=new URL("caldav"===a.accountType?null===(t=null==l?void 0:l.props)||void 0===t?void 0:t.calendarHomeSet.href:null===(r=null==l?void 0:l.props)||void 0===r?void 0:r.addressbookHomeSet.href,a.rootUrl).href;return ee(`Fetched home url ${u}`),u},se=async e=>{const{account:t,headers:r,loadCollections:a=!1,loadObjects:s=!1,headersToExclude:o,fetchOptions:n={}}=e,c={...t};return c.rootUrl=await te({account:t,headers:p(r,o),fetchOptions:n}),c.principalUrl=await re({account:c,headers:p(r,o),fetchOptions:n}),c.homeUrl=await ae({account:c,headers:p(r,o),fetchOptions:n}),(a||s)&&("caldav"===t.accountType?c.calendars=await G({headers:p(r,o),account:c,fetchOptions:n}):"carddav"===t.accountType&&(c.addressBooks=await x({headers:p(r,o),account:c,fetchOptions:n}))),s&&("caldav"===t.accountType&&c.calendars?c.calendars=await Promise.all(c.calendars.map((async e=>({...e,objects:await Q({calendar:e,headers:p(r,o),fetchOptions:n})})))):"carddav"===t.accountType&&c.addressBooks&&(c.addressBooks=await Promise.all(c.addressBooks.map((async e=>({...e,objects:await S({addressBook:e,headers:p(r,o),fetchOptions:n})})))))),c};var oe=Object.freeze({__proto__:null,createAccount:se,fetchHomeUrl:ae,fetchPrincipalUrl:re,serviceDiscovery:te});const ne=e("tsdav:authHelper"),ce=(e,t)=>(...r)=>e({...t,...r[0]}),de=e=>(ne(`Basic auth token generated: ${r(`${e.username}:${e.password}`)}`),{authorization:`Basic ${r(`${e.username}:${e.password}`)}`}),ie=async(e,t)=>{const r=["authorizationCode","redirectUrl","clientId","clientSecret","tokenUrl"];if(!w(e,r))throw new Error(`Oauth credentials missing: ${D(e,r)}`);const a=new URLSearchParams({grant_type:"authorization_code",code:e.authorizationCode,redirect_uri:e.redirectUrl,client_id:e.clientId,client_secret:e.clientSecret});ne(e.tokenUrl),ne(a.toString());const s=await fetch(e.tokenUrl,{method:"POST",body:a.toString(),headers:{"content-length":`${a.toString().length}`,"content-type":"application/x-www-form-urlencoded"},...null!=t?t:{}});if(s.ok){return await s.json()}return ne(`Fetch Oauth tokens failed: ${await s.text()}`),{}},le=async(e,t)=>{const r=["refreshToken","clientId","clientSecret","tokenUrl"];if(!w(e,r))throw new Error(`Oauth credentials missing: ${D(e,r)}`);const a=new URLSearchParams({client_id:e.clientId,client_secret:e.clientSecret,refresh_token:e.refreshToken,grant_type:"refresh_token"}),s=await fetch(e.tokenUrl,{method:"POST",body:a.toString(),headers:{"Content-Type":"application/x-www-form-urlencoded"},...null!=t?t:{}});if(s.ok){return await s.json()}return ne(`Refresh access token failed: ${await s.text()}`),{}},ue=async(e,t)=>{var r;ne("Fetching oauth headers");let a={};return e.refreshToken?(e.refreshToken&&!e.accessToken||Date.now()>(null!==(r=e.expiration)&&void 0!==r?r:0))&&(a=await le(e,t)):a=await ie(e,t),ne(`Oauth tokens fetched: ${a.access_token}`),{tokens:a,headers:{authorization:`Bearer ${a.access_token}`}}};var he=Object.freeze({__proto__:null,defaultParam:ce,fetchOauthTokens:ie,getBasicAuthHeaders:de,getOauthHeaders:ue,refreshAccessToken:le});const pe=async e=>{var t;const{serverUrl:r,credentials:a,authMethod:s,defaultAccountType:o,authFunction:n}=e;let c={};switch(s){case"Basic":c=de(a);break;case"Oauth":c=(await ue(a)).headers;break;case"Digest":c={Authorization:`Digest ${a.digestString}`};break;case"Custom":c=null!==(t=await(null==n?void 0:n(a)))&&void 0!==t?t:{};break;default:throw new Error("Invalid auth method")}const d=o?await se({account:{serverUrl:r,credentials:a,accountType:o},headers:c}):void 0,i=ce(m,{url:r,headers:c}),l=ce(A,{headers:c,url:r}),u=ce(g,{headers:c,url:r}),h=ce(O,{headers:c}),p=ce(V,{headers:c}),f=ce($,{headers:c}),v=ce(k,{headers:c}),C=ce(E,{headers:c}),w=ce(T,{headers:c}),D=ce(U,{headers:c,account:d}),b=ce(M,{headers:c}),_=ce(z,{headers:c}),R=ce(Z,{headers:c}),B=ce(G,{headers:c,account:d}),F=ce(I,{headers:c,account:d}),Y=ce(Q,{headers:c}),X=ce(q,{headers:c}),ee=ce(J,{headers:c}),te=ce(K,{headers:c}),re=ce(W,{account:d,headers:c}),ae=ce(L,{headers:c}),oe=ce(j,{headers:c});return{davRequest:async e=>{const{init:t,...r}=e,{headers:a,...s}=t;return y({...r,init:{...s,headers:{...c,...a}}})},propfind:h,createAccount:async e=>{const{account:t,headers:s,loadCollections:o,loadObjects:n}=e;return se({account:{serverUrl:r,credentials:a,...t},headers:{...c,...s},loadCollections:o,loadObjects:n})},createObject:i,updateObject:l,deleteObject:u,calendarQuery:b,addressBookQuery:ae,collectionQuery:p,makeCollection:f,calendarMultiGet:_,makeCalendar:R,syncCollection:v,supportedReportSet:C,isCollectionDirty:w,smartCollectionSync:D,fetchCalendars:B,fetchCalendarUserAddresses:F,fetchCalendarObjects:Y,createCalendarObject:X,updateCalendarObject:ee,deleteCalendarObject:te,syncCalendars:re,fetchAddressBooks:ce(x,{account:d,headers:c}),addressBookMultiGet:oe,fetchVCards:ce(S,{headers:c}),createVCard:ce(N,{headers:c}),updateVCard:ce(H,{headers:c}),deleteVCard:ce(P,{headers:c})}};class fe{constructor(e){var t,r,a;this.serverUrl=e.serverUrl,this.credentials=e.credentials,this.authMethod=null!==(t=e.authMethod)&&void 0!==t?t:"Basic",this.accountType=null!==(r=e.defaultAccountType)&&void 0!==r?r:"caldav",this.authFunction=e.authFunction,this.fetchOptions=null!==(a=e.fetchOptions)&&void 0!==a?a:{}}async login(){var e;switch(this.authMethod){case"Basic":this.authHeaders=de(this.credentials);break;case"Oauth":this.authHeaders=(await ue(this.credentials,this.fetchOptions)).headers;break;case"Digest":this.authHeaders={Authorization:`Digest ${this.credentials.digestString}`};break;case"Custom":this.authHeaders=await(null===(e=this.authFunction)||void 0===e?void 0:e.call(this,this.credentials));break;default:throw new Error("Invalid auth method")}this.account=this.accountType?await se({account:{serverUrl:this.serverUrl,credentials:this.credentials,accountType:this.accountType},headers:this.authHeaders,fetchOptions:this.fetchOptions}):void 0}async davRequest(e){const{init:t,...r}=e,{headers:a,...s}=t;return y({...r,init:{...s,headers:{...this.authHeaders,...a}},fetchOptions:this.fetchOptions})}async createObject(...e){return ce(m,{url:this.serverUrl,headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async updateObject(...e){return ce(A,{url:this.serverUrl,headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async deleteObject(...e){return ce(g,{url:this.serverUrl,headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async propfind(...e){return ce(O,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async createAccount(e){const{account:t,headers:r,loadCollections:a,loadObjects:s,fetchOptions:o}=e;return se({account:{serverUrl:this.serverUrl,credentials:this.credentials,...t},headers:{...this.authHeaders,...r},loadCollections:a,loadObjects:s,fetchOptions:null!=o?o:this.fetchOptions})}async collectionQuery(...e){return ce(V,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async makeCollection(...e){return ce($,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async syncCollection(...e){return ce(k,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async supportedReportSet(...e){return ce(E,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async isCollectionDirty(...e){return ce(T,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async smartCollectionSync(...e){return ce(U,{headers:this.authHeaders,fetchOptions:this.fetchOptions,account:this.account})(e[0])}async calendarQuery(...e){return ce(M,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async makeCalendar(...e){return ce(Z,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async calendarMultiGet(...e){return ce(z,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async fetchCalendars(...e){return ce(G,{headers:this.authHeaders,account:this.account,fetchOptions:this.fetchOptions})(null==e?void 0:e[0])}async fetchCalendarUserAddresses(...e){return ce(I,{headers:this.authHeaders,account:this.account,fetchOptions:this.fetchOptions})(null==e?void 0:e[0])}async fetchCalendarObjects(...e){return ce(Q,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async createCalendarObject(...e){return ce(q,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async updateCalendarObject(...e){return ce(J,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async deleteCalendarObject(...e){return ce(K,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async syncCalendars(...e){return ce(W,{headers:this.authHeaders,account:this.account,fetchOptions:this.fetchOptions})(e[0])}async addressBookQuery(...e){return ce(L,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async addressBookMultiGet(...e){return ce(j,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async fetchAddressBooks(...e){return ce(x,{headers:this.authHeaders,account:this.account,fetchOptions:this.fetchOptions})(null==e?void 0:e[0])}async fetchVCards(...e){return ce(S,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async createVCard(...e){return ce(N,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async updateVCard(...e){return ce(H,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}async deleteVCard(...e){return ce(P,{headers:this.authHeaders,fetchOptions:this.fetchOptions})(e[0])}}var ve={DAVNamespace:a,DAVNamespaceShort:o,DAVAttributeMap:s,...Object.freeze({__proto__:null,DAVClient:fe,createDAVClient:pe}),...C,..._,...oe,...B,...X,...he,...f};export{s as DAVAttributeMap,fe as DAVClient,a as DAVNamespace,o as DAVNamespaceShort,L as addressBookQuery,z as calendarMultiGet,M as calendarQuery,u as cleanupFalsy,V as collectionQuery,se as createAccount,q as createCalendarObject,pe as createDAVClient,m as createObject,N as createVCard,y as davRequest,ve as default,K as deleteCalendarObject,g as deleteObject,P as deleteVCard,x as fetchAddressBooks,Q as fetchCalendarObjects,I as fetchCalendarUserAddresses,G as fetchCalendars,ie as fetchOauthTokens,S as fetchVCards,Y as freeBusyQuery,de as getBasicAuthHeaders,l as getDAVAttribute,ue as getOauthHeaders,T as isCollectionDirty,Z as makeCalendar,O as propfind,le as refreshAccessToken,U as smartCollectionSync,E as supportedReportSet,W as syncCalendars,k as syncCollection,J as updateCalendarObject,A as updateObject,H as updateVCard,i as urlContains,d as urlEquals};