canada-api 2.0.3 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 National Defence
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,41 +1,104 @@
1
1
  # canada-api
2
2
 
3
+ [![NPM Version](https://img.shields.io/npm/v/canada-api?branch=main)](https://www.npmjs.com/package/canada-api) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/dnd-mdn/canada-api/blob/main/LICENSE.md)
4
+
3
5
  Cross platform API for fetching public data from [canada.ca](https://www.canada.ca).
4
6
 
5
7
  ## Install
6
8
  ### Browsers
7
9
 
8
- <script src="https://cdn.jsdelivr.net/npm/canada-api@2.0.3"></script>
9
- <script>
10
- ca.meta("en/department-national-defence").then(meta => {
11
- console.log(meta)
12
- })
13
- </script>
10
+ ```html
11
+ <script src="https://cdn.jsdelivr.net/npm/canada-api@2.0.4"></script>
12
+ <script>
13
+ ca.meta("en/department-national-defence").then(meta => {
14
+ console.log(meta)
15
+ })
16
+ </script>
17
+ ```
14
18
 
15
19
  ### Nodejs
16
20
 
17
- npm install canada-api
21
+ ```javascript
22
+ const ca = require("canada-api")
23
+ ca.meta("en/department-national-defence")
24
+ ```
25
+
18
26
 
19
- const ca = require("canada-api")
20
- ca.meta("en/department-national-defence")
21
27
 
22
28
  ## Core API
23
- ### ca.fetch(url, [options])
24
- `Promise<Response>` Rate limited [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) with some error checking
25
- ### ca.fetch.limiter
26
- `Bottleneck` Access to [rate limiter](https://www.npmjs.com/package/bottleneck)
27
- ### ca.normalize(url, [type=path])
28
- `string` Normalize AEM url ('path', 'children', 'content', 'meta')
29
+
30
+ ### `ca.fetch(url[, options])`
31
+
32
+ - `url` {string|URL} absolute URL
33
+ - `options` {Object} fetch [options](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options) (Some limitations based on implementation)
34
+ - `jobOptions` {Object} rate limiter [job options](https://github.com/SGrondin/bottleneck#job-options)
35
+ - Returns: {Promise} Fulfills with {Response} upon success
36
+
37
+ Uses [cross-fetch](https://github.com/lquixada/cross-fetch#readme) for a universal [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/fetch) implementation. Calls are rate limited to avoid hitting request limits that result in throttling. Throws an {Error} if the request does not complete successfully or if the destination URL is not on [canada.ca](https://www.canada.ca).
38
+
39
+
40
+ ### `ca.fetch.limiter`
41
+
42
+ - {Bottleneck}
43
+
44
+ The [Rate limiter](https://github.com/SGrondin/bottleneck#readme) used in `ca.fetch()`.
45
+
46
+
47
+ ### `ca.normalize(url[, type])`
48
+
49
+ - `url` {string|URL} node URL
50
+ - `type` {string} Possible values `'path'`, `'children'`, `'content'` or `'meta'`. **Default**: `'path'`
51
+ - Returns: {string} Normalized path or URL
52
+
53
+ Validates and formats [canada.ca](https://www.canada.ca) URLs based on type. URLs can take many forms, so not all options will be valid. Throws an {Error} if the URL is invalid, or the type requested is not possible.
54
+
55
+
56
+ ### `ca.normalize.baseURL`
57
+
58
+ - {string}
59
+
60
+ Base URL used for resolving relative URLs as well as URL validation. Value is `'https://www.canada.ca'`.
61
+
29
62
 
30
63
 
31
64
  ## Basic API
32
- ### ca.children(url, [options])
33
- `Promise<Array>` Array of child nodes
34
- ### ca.content(url, [options])
35
- `Promise<Object|string>` Content of a node, as text or json
36
- ### ca.meta(url, [options])
37
- `Promise<Object>` Metadata object
65
+
66
+ ### `ca.children(url[, options])`
67
+
68
+ - `url` {string|URL} absolute or relative URL
69
+ - `options` {Object} fetch [options](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options)
70
+ - `jobOptions` {Object} rate limiter [job options](https://github.com/SGrondin/bottleneck#job-options)
71
+ - `rawContent` {boolean} Fulfills with unmodified {string} **Default:** `false`
72
+ - Returns: {Promise} Fulfills with {Object[]} of child nodes
73
+
74
+ Parses sitemaps to get a list of child nodes.
75
+
76
+
77
+ ### `ca.content(url[, options])`
78
+
79
+ - `url` {string|URL} absolute or relative URL
80
+ - `options` {Object} fetch [options](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options)
81
+ - `jobOptions` {Object} rate limiter [job options](https://github.com/SGrondin/bottleneck#job-options)
82
+ - `rawContent` {boolean} Fulfills with unmodified {string} **Default:** `false`
83
+ - Returns: {Promise} Fulfills with {string|Object}
84
+
85
+ Retrieves the document contents. The result depends on the `content-type` header of {Response}:
86
+ - `'application/json'` parses response and fulfills with {Object}
87
+ - `'text/html'` compresses whitespace and fulfills with {string}
88
+ - Other types are fulfilled as {string} with no modification
89
+
90
+
91
+ ### `ca.meta(url[, options])`
92
+
93
+ - `url` {string|URL} absolute or relative URL
94
+ - `options` {Object} fetch [options](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options)
95
+ - `jobOptions` {Object} rate limiter [job options](https://github.com/SGrondin/bottleneck#job-options)
96
+ - `rawContent` {boolean} Fulfills with unmodified {string} **Default:** `false`
97
+ - Returns: {Promise} Fulfills with {Object} with metadata properties
98
+
99
+ Nodes contain a variety of metadata properties that can be accessed through a public API. Some properties are reformatted for consistency if `rawContent` option is `false`. A separate document will be created as a reference for the most useful ones.
38
100
 
39
101
 
40
102
  ## Extended API
41
- TBD
103
+
104
+ TBD
package/dist/ca.js CHANGED
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("cross-fetch")):"function"==typeof define&&define.amd?define("ca",["cross-fetch"],e):"object"==typeof exports?exports.ca=e(require("cross-fetch")):t.ca=e(t.fetch)}("undefined"!=typeof self?self:this,(t=>(()=>{var e={209:function(t,e,s){t.exports=function(){"use strict";var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==s.g?s.g:"undefined"!=typeof self?self:{};var e,r,i={load:function(t,e,s={}){var r,i,n;for(r in e)n=e[r],s[r]=null!=(i=t[r])?i:n;return s},overwrite:function(t,e,s={}){var r,i;for(r in t)i=t[r],void 0!==e[r]&&(s[r]=i);return s}},n=class{constructor(t,e){this.incr=t,this.decr=e,this._first=null,this._last=null,this.length=0}push(t){var e;this.length++,"function"==typeof this.incr&&this.incr(),e={value:t,prev:this._last,next:null},null!=this._last?(this._last.next=e,this._last=e):this._first=this._last=e}shift(){var t;if(null!=this._first)return this.length--,"function"==typeof this.decr&&this.decr(),t=this._first.value,null!=(this._first=this._first.next)?this._first.prev=null:this._last=null,t}first(){if(null!=this._first)return this._first.value}getArray(){var t,e,s;for(t=this._first,s=[];null!=t;)s.push((e=t,t=t.next,e.value));return s}forEachShift(t){var e;for(e=this.shift();null!=e;)t(e),e=this.shift()}debug(){var t,e,s,r,i;for(t=this._first,i=[];null!=t;)i.push((e=t,t=t.next,{value:e.value,prev:null!=(s=e.prev)?s.value:void 0,next:null!=(r=e.next)?r.value:void 0}));return i}},o=class{constructor(t){if(this.instance=t,this._events={},null!=this.instance.on||null!=this.instance.once||null!=this.instance.removeAllListeners)throw new Error("An Emitter already exists for this object");this.instance.on=(t,e)=>this._addListener(t,"many",e),this.instance.once=(t,e)=>this._addListener(t,"once",e),this.instance.removeAllListeners=(t=null)=>null!=t?delete this._events[t]:this._events={}}_addListener(t,e,s){var r;return null==(r=this._events)[t]&&(r[t]=[]),this._events[t].push({cb:s,status:e}),this.instance}listenerCount(t){return null!=this._events[t]?this._events[t].length:0}async trigger(t,...e){var s,r;try{if("debug"!==t&&this.trigger("debug",`Event triggered: ${t}`,e),null==this._events[t])return;return this._events[t]=this._events[t].filter((function(t){return"none"!==t.status})),r=this._events[t].map((async t=>{var s,r;if("none"!==t.status){"once"===t.status&&(t.status="none");try{return"function"==typeof(null!=(r="function"==typeof t.cb?t.cb(...e):void 0)?r.then:void 0)?await r:r}catch(t){return s=t,this.trigger("error",s),null}}})),(await Promise.all(r)).find((function(t){return null!=t}))}catch(t){return s=t,this.trigger("error",s),null}}};e=n,r=o;var a,h,u=class extends Error{};h=i,a=u;var l,c,p=class{constructor(t,e,s,r,i,n,o,a){this.task=t,this.args=e,this.rejectOnDrop=i,this.Events=n,this._states=o,this.Promise=a,this.options=h.load(s,r),this.options.priority=this._sanitizePriority(this.options.priority),this.options.id===r.id&&(this.options.id=`${this.options.id}-${this._randomIndex()}`),this.promise=new this.Promise(((t,e)=>{this._resolve=t,this._reject=e})),this.retryCount=0}_sanitizePriority(t){var e;return(e=~~t!==t?5:t)<0?0:e>9?9:e}_randomIndex(){return Math.random().toString(36).slice(2)}doDrop({error:t,message:e="This job has been dropped by Bottleneck"}={}){return!!this._states.remove(this.options.id)&&(this.rejectOnDrop&&this._reject(null!=t?t:new a(e)),this.Events.trigger("dropped",{args:this.args,options:this.options,task:this.task,promise:this.promise}),!0)}_assertStatus(t){var e;if((e=this._states.jobStatus(this.options.id))!==t&&("DONE"!==t||null!==e))throw new a(`Invalid job status ${e}, expected ${t}. Please open an issue at https://github.com/SGrondin/bottleneck/issues`)}doReceive(){return this._states.start(this.options.id),this.Events.trigger("received",{args:this.args,options:this.options})}doQueue(t,e){return this._assertStatus("RECEIVED"),this._states.next(this.options.id),this.Events.trigger("queued",{args:this.args,options:this.options,reachedHWM:t,blocked:e})}doRun(){return 0===this.retryCount?(this._assertStatus("QUEUED"),this._states.next(this.options.id)):this._assertStatus("EXECUTING"),this.Events.trigger("scheduled",{args:this.args,options:this.options})}async doExecute(t,e,s,r){var i,n,o;0===this.retryCount?(this._assertStatus("RUNNING"),this._states.next(this.options.id)):this._assertStatus("EXECUTING"),n={args:this.args,options:this.options,retryCount:this.retryCount},this.Events.trigger("executing",n);try{if(o=await(null!=t?t.schedule(this.options,this.task,...this.args):this.task(...this.args)),e())return this.doDone(n),await r(this.options,n),this._assertStatus("DONE"),this._resolve(o)}catch(t){return i=t,this._onFailure(i,n,e,s,r)}}doExpire(t,e,s){var r,i;return this._states.jobStatus("RUNNING"===this.options.id)&&this._states.next(this.options.id),this._assertStatus("EXECUTING"),i={args:this.args,options:this.options,retryCount:this.retryCount},r=new a(`This job timed out after ${this.options.expiration} ms.`),this._onFailure(r,i,t,e,s)}async _onFailure(t,e,s,r,i){var n,o;if(s())return null!=(n=await this.Events.trigger("failed",t,e))?(o=~~n,this.Events.trigger("retry",`Retrying ${this.options.id} after ${o} ms`,e),this.retryCount++,r(o)):(this.doDone(e),await i(this.options,e),this._assertStatus("DONE"),this._reject(t))}doDone(t){return this._assertStatus("EXECUTING"),this._states.next(this.options.id),this.Events.trigger("done",t)}};c=i,l=u;var d;d=u;var _;_=n;var f,v,m,g,y,w="2.19.5",b={version:w},E=Object.freeze({version:w,default:b}),O=()=>console.log("You must import the full version of Bottleneck in order to use this feature."),j=()=>console.log("You must import the full version of Bottleneck in order to use this feature.");y=i,f=o,m=O,v=j,g=()=>console.log("You must import the full version of Bottleneck in order to use this feature.");var x,k,R=function(){class t{constructor(t={}){this.deleteKey=this.deleteKey.bind(this),this.limiterOptions=t,y.load(this.limiterOptions,this.defaults,this),this.Events=new f(this),this.instances={},this.Bottleneck=U,this._startAutoCleanup(),this.sharedConnection=null!=this.connection,null==this.connection&&("redis"===this.limiterOptions.datastore?this.connection=new m(Object.assign({},this.limiterOptions,{Events:this.Events})):"ioredis"===this.limiterOptions.datastore&&(this.connection=new v(Object.assign({},this.limiterOptions,{Events:this.Events}))))}key(t=""){var e;return null!=(e=this.instances[t])?e:(()=>{var e;return e=this.instances[t]=new this.Bottleneck(Object.assign(this.limiterOptions,{id:`${this.id}-${t}`,timeout:this.timeout,connection:this.connection})),this.Events.trigger("created",e,t),e})()}async deleteKey(t=""){var e,s;return s=this.instances[t],this.connection&&(e=await this.connection.__runCommand__(["del",...g.allKeys(`${this.id}-${t}`)])),null!=s&&(delete this.instances[t],await s.disconnect()),null!=s||e>0}limiters(){var t,e,s,r;for(t in s=[],e=this.instances)r=e[t],s.push({key:t,limiter:r});return s}keys(){return Object.keys(this.instances)}async clusterKeys(){var t,e,s,r,i,n,o,a,h;if(null==this.connection)return this.Promise.resolve(this.keys());for(n=[],t=null,h=`b_${this.id}-`.length,e="_settings".length;0!==t;)for([a,s]=await this.connection.__runCommand__(["scan",null!=t?t:0,"match",`b_${this.id}-*_settings`,"count",1e4]),t=~~a,r=0,o=s.length;r<o;r++)i=s[r],n.push(i.slice(h,-e));return n}_startAutoCleanup(){var t;return clearInterval(this.interval),"function"==typeof(t=this.interval=setInterval((async()=>{var t,e,s,r,i,n;for(e in i=Date.now(),r=[],s=this.instances){n=s[e];try{await n._store.__groupCheck__(i)?r.push(this.deleteKey(e)):r.push(void 0)}catch(e){t=e,r.push(n.Events.trigger("error",t))}}return r}),this.timeout/2)).unref?t.unref():void 0}updateSettings(t={}){if(y.overwrite(t,this.defaults,this),y.overwrite(t,t,this.limiterOptions),null!=t.timeout)return this._startAutoCleanup()}disconnect(t=!0){var e;if(!this.sharedConnection)return null!=(e=this.connection)?e.disconnect(t):void 0}}return t.prototype.defaults={timeout:3e5,connection:null,Promise,id:"group-key"},t}.call(t);k=i,x=o;var D,I,C,P,T,A,L,S,q,$=function(){class t{constructor(t={}){this.options=t,k.load(this.options,this.defaults,this),this.Events=new x(this),this._arr=[],this._resetPromise(),this._lastFlush=Date.now()}_resetPromise(){return this._promise=new this.Promise(((t,e)=>this._resolve=t))}_flush(){return clearTimeout(this._timeout),this._lastFlush=Date.now(),this._resolve(),this.Events.trigger("batch",this._arr),this._arr=[],this._resetPromise()}add(t){var e;return this._arr.push(t),e=this._promise,this._arr.length===this.maxSize?this._flush():null!=this.maxTime&&1===this._arr.length&&(this._timeout=setTimeout((()=>this._flush()),this.maxTime)),e}}return t.prototype.defaults={maxTime:null,maxSize:null,Promise},t}.call(t),B=(q=E)&&q.default||q,N=[].splice;S=i,P=class{constructor(t){this.Events=new r(this),this._length=0,this._lists=function(){var s,r,i;for(i=[],s=1,r=t;1<=r?s<=r:s>=r;1<=r?++s:--s)i.push(new e((()=>this.incr()),(()=>this.decr())));return i}.call(this)}incr(){if(0==this._length++)return this.Events.trigger("leftzero")}decr(){if(0==--this._length)return this.Events.trigger("zero")}push(t){return this._lists[t.options.priority].push(t)}queued(t){return null!=t?this._lists[t].length:this._length}shiftAll(t){return this._lists.forEach((function(e){return e.forEachShift(t)}))}getFirst(t=this._lists){var e,s,r;for(e=0,s=t.length;e<s;e++)if((r=t[e]).length>0)return r;return[]}shiftLastFrom(t){return this.getFirst(this._lists.slice(t).reverse()).shift()}},I=p,C=class{constructor(t,e,s){this.instance=t,this.storeOptions=e,this.clientId=this.instance._randomIndex(),c.load(s,s,this),this._nextRequest=this._lastReservoirRefresh=this._lastReservoirIncrease=Date.now(),this._running=0,this._done=0,this._unblockTime=0,this.ready=this.Promise.resolve(),this.clients={},this._startHeartbeat()}_startHeartbeat(){var t;return null==this.heartbeat&&(null!=this.storeOptions.reservoirRefreshInterval&&null!=this.storeOptions.reservoirRefreshAmount||null!=this.storeOptions.reservoirIncreaseInterval&&null!=this.storeOptions.reservoirIncreaseAmount)?"function"==typeof(t=this.heartbeat=setInterval((()=>{var t,e,s,r,i;if(r=Date.now(),null!=this.storeOptions.reservoirRefreshInterval&&r>=this._lastReservoirRefresh+this.storeOptions.reservoirRefreshInterval&&(this._lastReservoirRefresh=r,this.storeOptions.reservoir=this.storeOptions.reservoirRefreshAmount,this.instance._drainAll(this.computeCapacity())),null!=this.storeOptions.reservoirIncreaseInterval&&r>=this._lastReservoirIncrease+this.storeOptions.reservoirIncreaseInterval&&(({reservoirIncreaseAmount:t,reservoirIncreaseMaximum:s,reservoir:i}=this.storeOptions),this._lastReservoirIncrease=r,(e=null!=s?Math.min(t,s-i):t)>0))return this.storeOptions.reservoir+=e,this.instance._drainAll(this.computeCapacity())}),this.heartbeatInterval)).unref?t.unref():void 0:clearInterval(this.heartbeat)}async __publish__(t){return await this.yieldLoop(),this.instance.Events.trigger("message",t.toString())}async __disconnect__(t){return await this.yieldLoop(),clearInterval(this.heartbeat),this.Promise.resolve()}yieldLoop(t=0){return new this.Promise((function(e,s){return setTimeout(e,t)}))}computePenalty(){var t;return null!=(t=this.storeOptions.penalty)?t:15*this.storeOptions.minTime||5e3}async __updateSettings__(t){return await this.yieldLoop(),c.overwrite(t,t,this.storeOptions),this._startHeartbeat(),this.instance._drainAll(this.computeCapacity()),!0}async __running__(){return await this.yieldLoop(),this._running}async __queued__(){return await this.yieldLoop(),this.instance.queued()}async __done__(){return await this.yieldLoop(),this._done}async __groupCheck__(t){return await this.yieldLoop(),this._nextRequest+this.timeout<t}computeCapacity(){var t,e;return({maxConcurrent:t,reservoir:e}=this.storeOptions),null!=t&&null!=e?Math.min(t-this._running,e):null!=t?t-this._running:null!=e?e:null}conditionsCheck(t){var e;return null==(e=this.computeCapacity())||t<=e}async __incrementReservoir__(t){var e;return await this.yieldLoop(),e=this.storeOptions.reservoir+=t,this.instance._drainAll(this.computeCapacity()),e}async __currentReservoir__(){return await this.yieldLoop(),this.storeOptions.reservoir}isBlocked(t){return this._unblockTime>=t}check(t,e){return this.conditionsCheck(t)&&this._nextRequest-e<=0}async __check__(t){var e;return await this.yieldLoop(),e=Date.now(),this.check(t,e)}async __register__(t,e,s){var r,i;return await this.yieldLoop(),r=Date.now(),this.conditionsCheck(e)?(this._running+=e,null!=this.storeOptions.reservoir&&(this.storeOptions.reservoir-=e),i=Math.max(this._nextRequest-r,0),this._nextRequest=r+i+this.storeOptions.minTime,{success:!0,wait:i,reservoir:this.storeOptions.reservoir}):{success:!1}}strategyIsBlock(){return 3===this.storeOptions.strategy}async __submit__(t,e){var s,r,i;if(await this.yieldLoop(),null!=this.storeOptions.maxConcurrent&&e>this.storeOptions.maxConcurrent)throw new l(`Impossible to add a job having a weight of ${e} to a limiter having a maxConcurrent setting of ${this.storeOptions.maxConcurrent}`);return r=Date.now(),i=null!=this.storeOptions.highWater&&t===this.storeOptions.highWater&&!this.check(e,r),(s=this.strategyIsBlock()&&(i||this.isBlocked(r)))&&(this._unblockTime=r+this.computePenalty(),this._nextRequest=this._unblockTime+this.storeOptions.minTime,this.instance._dropAllQueued()),{reachedHWM:i,blocked:s,strategy:this.storeOptions.strategy}}async __free__(t,e){return await this.yieldLoop(),this._running-=e,this._done+=e,this.instance._drainAll(this.computeCapacity()),{running:this._running}}},T=()=>console.log("You must import the full version of Bottleneck in order to use this feature."),D=o,A=class{constructor(t){this.status=t,this._jobs={},this.counts=this.status.map((function(){return 0}))}next(t){var e,s;return s=(e=this._jobs[t])+1,null!=e&&s<this.status.length?(this.counts[e]--,this.counts[s]++,this._jobs[t]++):null!=e?(this.counts[e]--,delete this._jobs[t]):void 0}start(t){return 0,this._jobs[t]=0,this.counts[0]++}remove(t){var e;return null!=(e=this._jobs[t])&&(this.counts[e]--,delete this._jobs[t]),null!=e}jobStatus(t){var e;return null!=(e=this.status[this._jobs[t]])?e:null}statusJobs(t){var e,s,r,i;if(null!=t){if((s=this.status.indexOf(t))<0)throw new d(`status must be one of ${this.status.join(", ")}`);for(e in i=[],r=this._jobs)r[e]===s&&i.push(e);return i}return Object.keys(this._jobs)}statusCounts(){return this.counts.reduce(((t,e,s)=>(t[this.status[s]]=e,t)),{})}},L=class{constructor(t,e){this.schedule=this.schedule.bind(this),this.name=t,this.Promise=e,this._running=0,this._queue=new _}isEmpty(){return 0===this._queue.length}async _tryToRun(){var t,e,s,r,i,n,o;if(this._running<1&&this._queue.length>0)return this._running++,({task:o,args:t,resolve:i,reject:r}=this._queue.shift()),e=await async function(){try{return n=await o(...t),function(){return i(n)}}catch(t){return s=t,function(){return r(s)}}}(),this._running--,this._tryToRun(),e()}schedule(t,...e){var s,r,i;return i=r=null,s=new this.Promise((function(t,e){return i=t,r=e})),this._queue.push({task:t,args:e,resolve:i,reject:r}),this._tryToRun(),s}};var U=function(){class t{constructor(e={},...s){var r,i;this._addToQueue=this._addToQueue.bind(this),this._validateOptions(e,s),S.load(e,this.instanceDefaults,this),this._queues=new P(10),this._scheduled={},this._states=new A(["RECEIVED","QUEUED","RUNNING","EXECUTING"].concat(this.trackDoneStatus?["DONE"]:[])),this._limiter=null,this.Events=new D(this),this._submitLock=new L("submit",this.Promise),this._registerLock=new L("register",this.Promise),i=S.load(e,this.storeDefaults,{}),this._store=function(){if("redis"===this.datastore||"ioredis"===this.datastore||null!=this.connection)return r=S.load(e,this.redisStoreDefaults,{}),new T(this,i,r);if("local"===this.datastore)return r=S.load(e,this.localStoreDefaults,{}),new C(this,i,r);throw new t.prototype.BottleneckError(`Invalid datastore type: ${this.datastore}`)}.call(this),this._queues.on("leftzero",(()=>{var t;return null!=(t=this._store.heartbeat)&&"function"==typeof t.ref?t.ref():void 0})),this._queues.on("zero",(()=>{var t;return null!=(t=this._store.heartbeat)&&"function"==typeof t.unref?t.unref():void 0}))}_validateOptions(e,s){if(null==e||"object"!=typeof e||0!==s.length)throw new t.prototype.BottleneckError("Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you're upgrading from Bottleneck v1.")}ready(){return this._store.ready}clients(){return this._store.clients}channel(){return`b_${this.id}`}channel_client(){return`b_${this.id}_${this._store.clientId}`}publish(t){return this._store.__publish__(t)}disconnect(t=!0){return this._store.__disconnect__(t)}chain(t){return this._limiter=t,this}queued(t){return this._queues.queued(t)}clusterQueued(){return this._store.__queued__()}empty(){return 0===this.queued()&&this._submitLock.isEmpty()}running(){return this._store.__running__()}done(){return this._store.__done__()}jobStatus(t){return this._states.jobStatus(t)}jobs(t){return this._states.statusJobs(t)}counts(){return this._states.statusCounts()}_randomIndex(){return Math.random().toString(36).slice(2)}check(t=1){return this._store.__check__(t)}_clearGlobalState(t){return null!=this._scheduled[t]&&(clearTimeout(this._scheduled[t].expiration),delete this._scheduled[t],!0)}async _free(t,e,s,r){var i,n;try{if(({running:n}=await this._store.__free__(t,s.weight)),this.Events.trigger("debug",`Freed ${s.id}`,r),0===n&&this.empty())return this.Events.trigger("idle")}catch(t){return i=t,this.Events.trigger("error",i)}}_run(t,e,s){var r,i,n;return e.doRun(),r=this._clearGlobalState.bind(this,t),n=this._run.bind(this,t,e),i=this._free.bind(this,t,e),this._scheduled[t]={timeout:setTimeout((()=>e.doExecute(this._limiter,r,n,i)),s),expiration:null!=e.options.expiration?setTimeout((function(){return e.doExpire(r,n,i)}),s+e.options.expiration):void 0,job:e}}_drainOne(t){return this._registerLock.schedule((()=>{var e,s,r,i,n;return 0===this.queued()?this.Promise.resolve(null):(n=this._queues.getFirst(),({options:i,args:e}=r=n.first()),null!=t&&i.weight>t?this.Promise.resolve(null):(this.Events.trigger("debug",`Draining ${i.id}`,{args:e,options:i}),s=this._randomIndex(),this._store.__register__(s,i.weight,i.expiration).then((({success:t,wait:o,reservoir:a})=>{var h;return this.Events.trigger("debug",`Drained ${i.id}`,{success:t,args:e,options:i}),t?(n.shift(),(h=this.empty())&&this.Events.trigger("empty"),0===a&&this.Events.trigger("depleted",h),this._run(s,r,o),this.Promise.resolve(i.weight)):this.Promise.resolve(null)}))))}))}_drainAll(t,e=0){return this._drainOne(t).then((s=>{var r;return null!=s?(r=null!=t?t-s:t,this._drainAll(r,e+s)):this.Promise.resolve(e)})).catch((t=>this.Events.trigger("error",t)))}_dropAllQueued(t){return this._queues.shiftAll((function(e){return e.doDrop({message:t})}))}stop(e={}){var s,r;return e=S.load(e,this.stopDefaults),r=t=>{var e;return e=()=>{var e;return(e=this._states.counts)[0]+e[1]+e[2]+e[3]===t},new this.Promise(((t,s)=>e()?t():this.on("done",(()=>{if(e())return this.removeAllListeners("done"),t()}))))},s=e.dropWaitingJobs?(this._run=function(t,s){return s.doDrop({message:e.dropErrorMessage})},this._drainOne=()=>this.Promise.resolve(null),this._registerLock.schedule((()=>this._submitLock.schedule((()=>{var t,s,i;for(t in s=this._scheduled)i=s[t],"RUNNING"===this.jobStatus(i.job.options.id)&&(clearTimeout(i.timeout),clearTimeout(i.expiration),i.job.doDrop({message:e.dropErrorMessage}));return this._dropAllQueued(e.dropErrorMessage),r(0)}))))):this.schedule({priority:9,weight:0},(()=>r(1))),this._receive=function(s){return s._reject(new t.prototype.BottleneckError(e.enqueueErrorMessage))},this.stop=()=>this.Promise.reject(new t.prototype.BottleneckError("stop() has already been called")),s}async _addToQueue(e){var s,r,i,n,o,a,h;({args:s,options:n}=e);try{({reachedHWM:o,blocked:r,strategy:h}=await this._store.__submit__(this.queued(),n.weight))}catch(t){return i=t,this.Events.trigger("debug",`Could not queue ${n.id}`,{args:s,options:n,error:i}),e.doDrop({error:i}),!1}return r?(e.doDrop(),!0):o&&(null!=(a=h===t.prototype.strategy.LEAK?this._queues.shiftLastFrom(n.priority):h===t.prototype.strategy.OVERFLOW_PRIORITY?this._queues.shiftLastFrom(n.priority+1):h===t.prototype.strategy.OVERFLOW?e:void 0)&&a.doDrop(),null==a||h===t.prototype.strategy.OVERFLOW)?(null==a&&e.doDrop(),o):(e.doQueue(o,r),this._queues.push(e),await this._drainAll(),o)}_receive(e){return null!=this._states.jobStatus(e.options.id)?(e._reject(new t.prototype.BottleneckError(`A job with the same id already exists (id=${e.options.id})`)),!1):(e.doReceive(),this._submitLock.schedule(this._addToQueue,e))}submit(...t){var e,s,r,i,n,o,a;return"function"==typeof t[0]?(n=t,[s,...t]=n,[e]=N.call(t,-1),i=S.load({},this.jobDefaults)):(o=t,[i,s,...t]=o,[e]=N.call(t,-1),i=S.load(i,this.jobDefaults)),a=(...t)=>new this.Promise((function(e,r){return s(...t,(function(...t){return(null!=t[0]?r:e)(t)}))})),(r=new I(a,t,i,this.jobDefaults,this.rejectOnDrop,this.Events,this._states,this.Promise)).promise.then((function(t){return"function"==typeof e?e(...t):void 0})).catch((function(t){return Array.isArray(t)?"function"==typeof e?e(...t):void 0:"function"==typeof e?e(t):void 0})),this._receive(r)}schedule(...t){var e,s,r;return"function"==typeof t[0]?([r,...t]=t,s={}):[s,r,...t]=t,e=new I(r,t,s,this.jobDefaults,this.rejectOnDrop,this.Events,this._states,this.Promise),this._receive(e),e.promise}wrap(t){var e,s;return e=this.schedule.bind(this),(s=function(...s){return e(t.bind(this),...s)}).withOptions=function(s,...r){return e(s,t,...r)},s}async updateSettings(t={}){return await this._store.__updateSettings__(S.overwrite(t,this.storeDefaults)),S.overwrite(t,this.instanceDefaults,this),this}currentReservoir(){return this._store.__currentReservoir__()}incrementReservoir(t=0){return this._store.__incrementReservoir__(t)}}return t.default=t,t.Events=D,t.version=t.prototype.version=B.version,t.strategy=t.prototype.strategy={LEAK:1,OVERFLOW:2,OVERFLOW_PRIORITY:4,BLOCK:3},t.BottleneckError=t.prototype.BottleneckError=u,t.Group=t.prototype.Group=R,t.RedisConnection=t.prototype.RedisConnection=O,t.IORedisConnection=t.prototype.IORedisConnection=j,t.Batcher=t.prototype.Batcher=$,t.prototype.jobDefaults={priority:5,weight:1,expiration:null,id:"<no-id>"},t.prototype.storeDefaults={maxConcurrent:null,minTime:0,highWater:null,strategy:t.prototype.strategy.LEAK,penalty:null,reservoir:null,reservoirRefreshInterval:null,reservoirRefreshAmount:null,reservoirIncreaseInterval:null,reservoirIncreaseAmount:null,reservoirIncreaseMaximum:null},t.prototype.localStoreDefaults={Promise,timeout:null,heartbeatInterval:250},t.prototype.redisStoreDefaults={Promise,timeout:null,heartbeatInterval:5e3,clientTimeout:1e4,Redis:null,clientOptions:{},clusterNodes:null,clearDatastore:!1,connection:null},t.prototype.instanceDefaults={datastore:"local",connection:null,id:"<no-id>",rejectOnDrop:!0,trackDoneStatus:!1,Promise},t.prototype.stopDefaults={enqueueErrorMessage:"This limiter has been stopped and cannot accept new jobs.",dropWaitingJobs:!0,dropErrorMessage:"This limiter has been stopped."},t}.call(t);return U}()},310:t=>{"use strict";t.exports=t=>{if("[object Object]"!==Object.prototype.toString.call(t))return!1;const e=Object.getPrototypeOf(t);return null===e||e===Object.prototype}},942:function(t,e,s){"use strict";const r=s(310),{hasOwnProperty:i}=Object.prototype,{propertyIsEnumerable:n}=Object,o=(t,e,s)=>Object.defineProperty(t,e,{value:s,writable:!0,enumerable:!0,configurable:!0}),a=this,h={concatArrays:!1,ignoreUndefined:!1},u=t=>{const e=[];for(const s in t)i.call(t,s)&&e.push(s);if(Object.getOwnPropertySymbols){const s=Object.getOwnPropertySymbols(t);for(const r of s)n.call(t,r)&&e.push(r)}return e};function l(t){return Array.isArray(t)?function(t){const e=t.slice(0,0);return u(t).forEach((s=>{o(e,s,l(t[s]))})),e}(t):r(t)?function(t){const e=null===Object.getPrototypeOf(t)?Object.create(null):{};return u(t).forEach((s=>{o(e,s,l(t[s]))})),e}(t):t}const c=(t,e,s,r)=>(s.forEach((s=>{void 0===e[s]&&r.ignoreUndefined||(s in t&&t[s]!==Object.getPrototypeOf(t)?o(t,s,p(t[s],e[s],r)):o(t,s,l(e[s])))})),t);function p(t,e,s){return s.concatArrays&&Array.isArray(t)&&Array.isArray(e)?((t,e,s)=>{let r=t.slice(0,0),n=0;return[t,e].forEach((e=>{const a=[];for(let s=0;s<e.length;s++)i.call(e,s)&&(a.push(String(s)),o(r,n++,e===t?e[s]:l(e[s])));r=c(r,e,u(e).filter((t=>!a.includes(t))),s)})),r})(t,e,s):r(e)&&r(t)?c(t,e,u(e),s):l(e)}t.exports=function(...t){const e=p(l(h),this!==a&&this||{},h);let s={_:{}};for(const i of t)if(void 0!==i){if(!r(i))throw new TypeError("`"+i+"` is not an Option Object");s=p(s,{_:i},e)}return s._}},322:(t,e,s)=>{const r=s(427),i=s(942),n=s(526),o={jobOptions:{priority:0}};t.exports=async(t,e)=>{t=r(t,"children"),e=i(o,e);let s=await n(t,e),a=(await s.text()).match(/<url>.*?<\/url>/g).map((t=>{let e=t.match(/<loc>([^<]+)<\/loc>/),s=t.match(/<lastmod>([^<]+)<\/lastmod>/);return{path:r(e[1]),lastmod:s?Date.parse(s[1]):null}}));return a.length&&a[0].path===r(t)&&a.shift(),a}},565:(t,e,s)=>{const r=s(427),i=s(942),n=s(526),o={jobOptions:{priority:0}};t.exports=async(t,e)=>{t=r(t,"content"),e=i(o,e);let s=await n(t,e),a=s.headers.get("Content-Type");if(a.includes("/json"))return s.json();let h=await s.text();return a.includes("text/html")&&(h=h.replace(/\s+/g," ")),h}},526:(t,e,s)=>{const r=s(268),i=new(s(209))({reservoir:150,reservoirRefreshAmount:150,reservoirRefreshInterval:5e3,maxConcurrent:10,trackDoneStatus:!0}),n=(t,e)=>r(t,e);t.exports=e=async(t,e)=>{let s=await i.schedule(e?.jobOptions||{},n,t,e);if(!s.ok)throw new Error(s.statusText);if("string"==typeof t&&(t=new URL(t)),t.hostname!==new URL(s.url).hostname)throw new Error("Redirect to invalid host");return s},e.limiter=i},138:(t,e,s)=>{const r=s(526),i=s(427),n=s(322),o=s(565),a=s(873);t.exports={fetch:r,normalize:i,children:n,content:o,meta:a}},873:(t,e,s)=>{const r=s(427),i=s(942),n=s(526),o={jobOptions:{expiration:3e4}},a={Jan:"01",Feb:"02",Mar:"03",Apr:"04",May:"05",Jun:"06",Jul:"07",Aug:"08",Sep:"09",Oct:"10",Nov:"11",Dec:"12"};t.exports=async(t,e)=>{t=r(t,"meta"),e=i(o,e);let s=await n(t,e);if(!s.headers.get("content-type").includes("/json"))throw new Error("Unexpected response content-type");let h=await s.json();return Object.keys(h).forEach((t=>{"true"===h[t]?h[t]=!0:"false"===h[t]?h[t]=!1:t.endsWith("@TypeHint")?delete h[t]:"string"==typeof h[t]?h[t]=function(t){if(/^\d{4}-\d{2}-\d{2}$/.test(t))return Date.parse(t);let e=/^\w{3} (\w{3}) (\d{2}) (\d{4}) ([\d:]{8}) GMT([\-+]\d{4})$/.exec(t);return e?Date.parse(e[3]+"-"+a[e[1]]+"-"+e[2]+"T"+e[4]+e[5]):t}(h[t]):Array.isArray(h[t])&&0===h[t].length&&delete h[t]})),Object.keys(h).sort().reduce(((t,e)=>(t[e]=h[e],t)),{})}},427:(t,e)=>{const s="https://www.canada.ca/";t.exports=(t,e="path")=>{if("string"==typeof t)t=new URL(t,s);else if(!(t instanceof URL))throw new TypeError("string or URL object expected");if(t.protocol="https",!t.href.startsWith(s))throw new Error("URL must start with "+s);let r=t.pathname.startsWith("/content/dam");if(r||(t.pathname=t.pathname.replace(/^\/content\/canadasite\//,"")),!/^\/(en|fr|content\/dam)(\/|\.|$)/.test(t.pathname))throw new Error("Invalid root");return t.pathname=t.pathname.replace(/\/+$/,""),"path"!==e&&t.searchParams.set("_",Date.now()),t.pathname.includes("/_jcr_content/par")?function(t,e){if("path"===e)throw new Error("Cant determine path of a reference node directly");if("meta"===e)t.pathname=t.pathname.replace(/\/image\.img\.\w+\//,"/image.json/");else if("children"===e)throw new Error("Cant load children of a reference node");return t.href}(t,e):r?function(t,e){let s=/(\/|\/\w+)$/.test(t.pathname);if("meta"===e)t.pathname+=s?".json":"/_jcr_content.json";else{if("children"===e)throw new Error("Cant load children of an asset node");if("content"===e&&s)throw new Error("Cant load content of an asset node")}return"path"===e?t.pathname:t.href}(t,e):function(t,e){return t.pathname=t.pathname.replace(/\/?\.(sitemap\.xml|[^/.]+)$/,""),"meta"===e?t.pathname+="/_jcr_content.json":"children"===e?t.pathname+=".sitemap.xml":"content"===e&&(t.pathname+=".html"),"path"===e?t.pathname:t.href}(t,e)}},268:e=>{"use strict";e.exports=t}},s={};function r(t){var i=s[t];if(void 0!==i)return i.exports;var n=s[t]={exports:{}};return e[t].call(n.exports,n,n.exports,r),n.exports}return r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),r(138)})()));
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("cross-fetch")):"function"==typeof define&&define.amd?define("ca",["cross-fetch"],e):"object"==typeof exports?exports.ca=e(require("cross-fetch")):t.ca=e(t.fetch)}("undefined"!=typeof self?self:this,(t=>(()=>{var e={209:function(t,e,s){t.exports=function(){"use strict";var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==s.g?s.g:"undefined"!=typeof self?self:{};var e,r,i={load:function(t,e,s={}){var r,i,n;for(r in e)n=e[r],s[r]=null!=(i=t[r])?i:n;return s},overwrite:function(t,e,s={}){var r,i;for(r in t)i=t[r],void 0!==e[r]&&(s[r]=i);return s}},n=class{constructor(t,e){this.incr=t,this.decr=e,this._first=null,this._last=null,this.length=0}push(t){var e;this.length++,"function"==typeof this.incr&&this.incr(),e={value:t,prev:this._last,next:null},null!=this._last?(this._last.next=e,this._last=e):this._first=this._last=e}shift(){var t;if(null!=this._first)return this.length--,"function"==typeof this.decr&&this.decr(),t=this._first.value,null!=(this._first=this._first.next)?this._first.prev=null:this._last=null,t}first(){if(null!=this._first)return this._first.value}getArray(){var t,e,s;for(t=this._first,s=[];null!=t;)s.push((e=t,t=t.next,e.value));return s}forEachShift(t){var e;for(e=this.shift();null!=e;)t(e),e=this.shift()}debug(){var t,e,s,r,i;for(t=this._first,i=[];null!=t;)i.push((e=t,t=t.next,{value:e.value,prev:null!=(s=e.prev)?s.value:void 0,next:null!=(r=e.next)?r.value:void 0}));return i}},o=class{constructor(t){if(this.instance=t,this._events={},null!=this.instance.on||null!=this.instance.once||null!=this.instance.removeAllListeners)throw new Error("An Emitter already exists for this object");this.instance.on=(t,e)=>this._addListener(t,"many",e),this.instance.once=(t,e)=>this._addListener(t,"once",e),this.instance.removeAllListeners=(t=null)=>null!=t?delete this._events[t]:this._events={}}_addListener(t,e,s){var r;return null==(r=this._events)[t]&&(r[t]=[]),this._events[t].push({cb:s,status:e}),this.instance}listenerCount(t){return null!=this._events[t]?this._events[t].length:0}async trigger(t,...e){var s,r;try{if("debug"!==t&&this.trigger("debug",`Event triggered: ${t}`,e),null==this._events[t])return;return this._events[t]=this._events[t].filter((function(t){return"none"!==t.status})),r=this._events[t].map((async t=>{var s,r;if("none"!==t.status){"once"===t.status&&(t.status="none");try{return"function"==typeof(null!=(r="function"==typeof t.cb?t.cb(...e):void 0)?r.then:void 0)?await r:r}catch(t){return s=t,this.trigger("error",s),null}}})),(await Promise.all(r)).find((function(t){return null!=t}))}catch(t){return s=t,this.trigger("error",s),null}}};e=n,r=o;var a,h,u=class extends Error{};h=i,a=u;var l,c,p=class{constructor(t,e,s,r,i,n,o,a){this.task=t,this.args=e,this.rejectOnDrop=i,this.Events=n,this._states=o,this.Promise=a,this.options=h.load(s,r),this.options.priority=this._sanitizePriority(this.options.priority),this.options.id===r.id&&(this.options.id=`${this.options.id}-${this._randomIndex()}`),this.promise=new this.Promise(((t,e)=>{this._resolve=t,this._reject=e})),this.retryCount=0}_sanitizePriority(t){var e;return(e=~~t!==t?5:t)<0?0:e>9?9:e}_randomIndex(){return Math.random().toString(36).slice(2)}doDrop({error:t,message:e="This job has been dropped by Bottleneck"}={}){return!!this._states.remove(this.options.id)&&(this.rejectOnDrop&&this._reject(null!=t?t:new a(e)),this.Events.trigger("dropped",{args:this.args,options:this.options,task:this.task,promise:this.promise}),!0)}_assertStatus(t){var e;if((e=this._states.jobStatus(this.options.id))!==t&&("DONE"!==t||null!==e))throw new a(`Invalid job status ${e}, expected ${t}. Please open an issue at https://github.com/SGrondin/bottleneck/issues`)}doReceive(){return this._states.start(this.options.id),this.Events.trigger("received",{args:this.args,options:this.options})}doQueue(t,e){return this._assertStatus("RECEIVED"),this._states.next(this.options.id),this.Events.trigger("queued",{args:this.args,options:this.options,reachedHWM:t,blocked:e})}doRun(){return 0===this.retryCount?(this._assertStatus("QUEUED"),this._states.next(this.options.id)):this._assertStatus("EXECUTING"),this.Events.trigger("scheduled",{args:this.args,options:this.options})}async doExecute(t,e,s,r){var i,n,o;0===this.retryCount?(this._assertStatus("RUNNING"),this._states.next(this.options.id)):this._assertStatus("EXECUTING"),n={args:this.args,options:this.options,retryCount:this.retryCount},this.Events.trigger("executing",n);try{if(o=await(null!=t?t.schedule(this.options,this.task,...this.args):this.task(...this.args)),e())return this.doDone(n),await r(this.options,n),this._assertStatus("DONE"),this._resolve(o)}catch(t){return i=t,this._onFailure(i,n,e,s,r)}}doExpire(t,e,s){var r,i;return this._states.jobStatus("RUNNING"===this.options.id)&&this._states.next(this.options.id),this._assertStatus("EXECUTING"),i={args:this.args,options:this.options,retryCount:this.retryCount},r=new a(`This job timed out after ${this.options.expiration} ms.`),this._onFailure(r,i,t,e,s)}async _onFailure(t,e,s,r,i){var n,o;if(s())return null!=(n=await this.Events.trigger("failed",t,e))?(o=~~n,this.Events.trigger("retry",`Retrying ${this.options.id} after ${o} ms`,e),this.retryCount++,r(o)):(this.doDone(e),await i(this.options,e),this._assertStatus("DONE"),this._reject(t))}doDone(t){return this._assertStatus("EXECUTING"),this._states.next(this.options.id),this.Events.trigger("done",t)}};c=i,l=u;var d;d=u;var _;_=n;var f,v,m,g,y,w="2.19.5",b={version:w},E=Object.freeze({version:w,default:b}),O=()=>console.log("You must import the full version of Bottleneck in order to use this feature."),j=()=>console.log("You must import the full version of Bottleneck in order to use this feature.");y=i,f=o,m=O,v=j,g=()=>console.log("You must import the full version of Bottleneck in order to use this feature.");var x,k,R=function(){class t{constructor(t={}){this.deleteKey=this.deleteKey.bind(this),this.limiterOptions=t,y.load(this.limiterOptions,this.defaults,this),this.Events=new f(this),this.instances={},this.Bottleneck=U,this._startAutoCleanup(),this.sharedConnection=null!=this.connection,null==this.connection&&("redis"===this.limiterOptions.datastore?this.connection=new m(Object.assign({},this.limiterOptions,{Events:this.Events})):"ioredis"===this.limiterOptions.datastore&&(this.connection=new v(Object.assign({},this.limiterOptions,{Events:this.Events}))))}key(t=""){var e;return null!=(e=this.instances[t])?e:(()=>{var e;return e=this.instances[t]=new this.Bottleneck(Object.assign(this.limiterOptions,{id:`${this.id}-${t}`,timeout:this.timeout,connection:this.connection})),this.Events.trigger("created",e,t),e})()}async deleteKey(t=""){var e,s;return s=this.instances[t],this.connection&&(e=await this.connection.__runCommand__(["del",...g.allKeys(`${this.id}-${t}`)])),null!=s&&(delete this.instances[t],await s.disconnect()),null!=s||e>0}limiters(){var t,e,s,r;for(t in s=[],e=this.instances)r=e[t],s.push({key:t,limiter:r});return s}keys(){return Object.keys(this.instances)}async clusterKeys(){var t,e,s,r,i,n,o,a,h;if(null==this.connection)return this.Promise.resolve(this.keys());for(n=[],t=null,h=`b_${this.id}-`.length,e="_settings".length;0!==t;)for([a,s]=await this.connection.__runCommand__(["scan",null!=t?t:0,"match",`b_${this.id}-*_settings`,"count",1e4]),t=~~a,r=0,o=s.length;r<o;r++)i=s[r],n.push(i.slice(h,-e));return n}_startAutoCleanup(){var t;return clearInterval(this.interval),"function"==typeof(t=this.interval=setInterval((async()=>{var t,e,s,r,i,n;for(e in i=Date.now(),r=[],s=this.instances){n=s[e];try{await n._store.__groupCheck__(i)?r.push(this.deleteKey(e)):r.push(void 0)}catch(e){t=e,r.push(n.Events.trigger("error",t))}}return r}),this.timeout/2)).unref?t.unref():void 0}updateSettings(t={}){if(y.overwrite(t,this.defaults,this),y.overwrite(t,t,this.limiterOptions),null!=t.timeout)return this._startAutoCleanup()}disconnect(t=!0){var e;if(!this.sharedConnection)return null!=(e=this.connection)?e.disconnect(t):void 0}}return t.prototype.defaults={timeout:3e5,connection:null,Promise,id:"group-key"},t}.call(t);k=i,x=o;var C,I,D,P,T,A,L,S,q,$=function(){class t{constructor(t={}){this.options=t,k.load(this.options,this.defaults,this),this.Events=new x(this),this._arr=[],this._resetPromise(),this._lastFlush=Date.now()}_resetPromise(){return this._promise=new this.Promise(((t,e)=>this._resolve=t))}_flush(){return clearTimeout(this._timeout),this._lastFlush=Date.now(),this._resolve(),this.Events.trigger("batch",this._arr),this._arr=[],this._resetPromise()}add(t){var e;return this._arr.push(t),e=this._promise,this._arr.length===this.maxSize?this._flush():null!=this.maxTime&&1===this._arr.length&&(this._timeout=setTimeout((()=>this._flush()),this.maxTime)),e}}return t.prototype.defaults={maxTime:null,maxSize:null,Promise},t}.call(t),B=(q=E)&&q.default||q,N=[].splice;S=i,P=class{constructor(t){this.Events=new r(this),this._length=0,this._lists=function(){var s,r,i;for(i=[],s=1,r=t;1<=r?s<=r:s>=r;1<=r?++s:--s)i.push(new e((()=>this.incr()),(()=>this.decr())));return i}.call(this)}incr(){if(0==this._length++)return this.Events.trigger("leftzero")}decr(){if(0==--this._length)return this.Events.trigger("zero")}push(t){return this._lists[t.options.priority].push(t)}queued(t){return null!=t?this._lists[t].length:this._length}shiftAll(t){return this._lists.forEach((function(e){return e.forEachShift(t)}))}getFirst(t=this._lists){var e,s,r;for(e=0,s=t.length;e<s;e++)if((r=t[e]).length>0)return r;return[]}shiftLastFrom(t){return this.getFirst(this._lists.slice(t).reverse()).shift()}},I=p,D=class{constructor(t,e,s){this.instance=t,this.storeOptions=e,this.clientId=this.instance._randomIndex(),c.load(s,s,this),this._nextRequest=this._lastReservoirRefresh=this._lastReservoirIncrease=Date.now(),this._running=0,this._done=0,this._unblockTime=0,this.ready=this.Promise.resolve(),this.clients={},this._startHeartbeat()}_startHeartbeat(){var t;return null==this.heartbeat&&(null!=this.storeOptions.reservoirRefreshInterval&&null!=this.storeOptions.reservoirRefreshAmount||null!=this.storeOptions.reservoirIncreaseInterval&&null!=this.storeOptions.reservoirIncreaseAmount)?"function"==typeof(t=this.heartbeat=setInterval((()=>{var t,e,s,r,i;if(r=Date.now(),null!=this.storeOptions.reservoirRefreshInterval&&r>=this._lastReservoirRefresh+this.storeOptions.reservoirRefreshInterval&&(this._lastReservoirRefresh=r,this.storeOptions.reservoir=this.storeOptions.reservoirRefreshAmount,this.instance._drainAll(this.computeCapacity())),null!=this.storeOptions.reservoirIncreaseInterval&&r>=this._lastReservoirIncrease+this.storeOptions.reservoirIncreaseInterval&&(({reservoirIncreaseAmount:t,reservoirIncreaseMaximum:s,reservoir:i}=this.storeOptions),this._lastReservoirIncrease=r,(e=null!=s?Math.min(t,s-i):t)>0))return this.storeOptions.reservoir+=e,this.instance._drainAll(this.computeCapacity())}),this.heartbeatInterval)).unref?t.unref():void 0:clearInterval(this.heartbeat)}async __publish__(t){return await this.yieldLoop(),this.instance.Events.trigger("message",t.toString())}async __disconnect__(t){return await this.yieldLoop(),clearInterval(this.heartbeat),this.Promise.resolve()}yieldLoop(t=0){return new this.Promise((function(e,s){return setTimeout(e,t)}))}computePenalty(){var t;return null!=(t=this.storeOptions.penalty)?t:15*this.storeOptions.minTime||5e3}async __updateSettings__(t){return await this.yieldLoop(),c.overwrite(t,t,this.storeOptions),this._startHeartbeat(),this.instance._drainAll(this.computeCapacity()),!0}async __running__(){return await this.yieldLoop(),this._running}async __queued__(){return await this.yieldLoop(),this.instance.queued()}async __done__(){return await this.yieldLoop(),this._done}async __groupCheck__(t){return await this.yieldLoop(),this._nextRequest+this.timeout<t}computeCapacity(){var t,e;return({maxConcurrent:t,reservoir:e}=this.storeOptions),null!=t&&null!=e?Math.min(t-this._running,e):null!=t?t-this._running:null!=e?e:null}conditionsCheck(t){var e;return null==(e=this.computeCapacity())||t<=e}async __incrementReservoir__(t){var e;return await this.yieldLoop(),e=this.storeOptions.reservoir+=t,this.instance._drainAll(this.computeCapacity()),e}async __currentReservoir__(){return await this.yieldLoop(),this.storeOptions.reservoir}isBlocked(t){return this._unblockTime>=t}check(t,e){return this.conditionsCheck(t)&&this._nextRequest-e<=0}async __check__(t){var e;return await this.yieldLoop(),e=Date.now(),this.check(t,e)}async __register__(t,e,s){var r,i;return await this.yieldLoop(),r=Date.now(),this.conditionsCheck(e)?(this._running+=e,null!=this.storeOptions.reservoir&&(this.storeOptions.reservoir-=e),i=Math.max(this._nextRequest-r,0),this._nextRequest=r+i+this.storeOptions.minTime,{success:!0,wait:i,reservoir:this.storeOptions.reservoir}):{success:!1}}strategyIsBlock(){return 3===this.storeOptions.strategy}async __submit__(t,e){var s,r,i;if(await this.yieldLoop(),null!=this.storeOptions.maxConcurrent&&e>this.storeOptions.maxConcurrent)throw new l(`Impossible to add a job having a weight of ${e} to a limiter having a maxConcurrent setting of ${this.storeOptions.maxConcurrent}`);return r=Date.now(),i=null!=this.storeOptions.highWater&&t===this.storeOptions.highWater&&!this.check(e,r),(s=this.strategyIsBlock()&&(i||this.isBlocked(r)))&&(this._unblockTime=r+this.computePenalty(),this._nextRequest=this._unblockTime+this.storeOptions.minTime,this.instance._dropAllQueued()),{reachedHWM:i,blocked:s,strategy:this.storeOptions.strategy}}async __free__(t,e){return await this.yieldLoop(),this._running-=e,this._done+=e,this.instance._drainAll(this.computeCapacity()),{running:this._running}}},T=()=>console.log("You must import the full version of Bottleneck in order to use this feature."),C=o,A=class{constructor(t){this.status=t,this._jobs={},this.counts=this.status.map((function(){return 0}))}next(t){var e,s;return s=(e=this._jobs[t])+1,null!=e&&s<this.status.length?(this.counts[e]--,this.counts[s]++,this._jobs[t]++):null!=e?(this.counts[e]--,delete this._jobs[t]):void 0}start(t){return 0,this._jobs[t]=0,this.counts[0]++}remove(t){var e;return null!=(e=this._jobs[t])&&(this.counts[e]--,delete this._jobs[t]),null!=e}jobStatus(t){var e;return null!=(e=this.status[this._jobs[t]])?e:null}statusJobs(t){var e,s,r,i;if(null!=t){if((s=this.status.indexOf(t))<0)throw new d(`status must be one of ${this.status.join(", ")}`);for(e in i=[],r=this._jobs)r[e]===s&&i.push(e);return i}return Object.keys(this._jobs)}statusCounts(){return this.counts.reduce(((t,e,s)=>(t[this.status[s]]=e,t)),{})}},L=class{constructor(t,e){this.schedule=this.schedule.bind(this),this.name=t,this.Promise=e,this._running=0,this._queue=new _}isEmpty(){return 0===this._queue.length}async _tryToRun(){var t,e,s,r,i,n,o;if(this._running<1&&this._queue.length>0)return this._running++,({task:o,args:t,resolve:i,reject:r}=this._queue.shift()),e=await async function(){try{return n=await o(...t),function(){return i(n)}}catch(t){return s=t,function(){return r(s)}}}(),this._running--,this._tryToRun(),e()}schedule(t,...e){var s,r,i;return i=r=null,s=new this.Promise((function(t,e){return i=t,r=e})),this._queue.push({task:t,args:e,resolve:i,reject:r}),this._tryToRun(),s}};var U=function(){class t{constructor(e={},...s){var r,i;this._addToQueue=this._addToQueue.bind(this),this._validateOptions(e,s),S.load(e,this.instanceDefaults,this),this._queues=new P(10),this._scheduled={},this._states=new A(["RECEIVED","QUEUED","RUNNING","EXECUTING"].concat(this.trackDoneStatus?["DONE"]:[])),this._limiter=null,this.Events=new C(this),this._submitLock=new L("submit",this.Promise),this._registerLock=new L("register",this.Promise),i=S.load(e,this.storeDefaults,{}),this._store=function(){if("redis"===this.datastore||"ioredis"===this.datastore||null!=this.connection)return r=S.load(e,this.redisStoreDefaults,{}),new T(this,i,r);if("local"===this.datastore)return r=S.load(e,this.localStoreDefaults,{}),new D(this,i,r);throw new t.prototype.BottleneckError(`Invalid datastore type: ${this.datastore}`)}.call(this),this._queues.on("leftzero",(()=>{var t;return null!=(t=this._store.heartbeat)&&"function"==typeof t.ref?t.ref():void 0})),this._queues.on("zero",(()=>{var t;return null!=(t=this._store.heartbeat)&&"function"==typeof t.unref?t.unref():void 0}))}_validateOptions(e,s){if(null==e||"object"!=typeof e||0!==s.length)throw new t.prototype.BottleneckError("Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you're upgrading from Bottleneck v1.")}ready(){return this._store.ready}clients(){return this._store.clients}channel(){return`b_${this.id}`}channel_client(){return`b_${this.id}_${this._store.clientId}`}publish(t){return this._store.__publish__(t)}disconnect(t=!0){return this._store.__disconnect__(t)}chain(t){return this._limiter=t,this}queued(t){return this._queues.queued(t)}clusterQueued(){return this._store.__queued__()}empty(){return 0===this.queued()&&this._submitLock.isEmpty()}running(){return this._store.__running__()}done(){return this._store.__done__()}jobStatus(t){return this._states.jobStatus(t)}jobs(t){return this._states.statusJobs(t)}counts(){return this._states.statusCounts()}_randomIndex(){return Math.random().toString(36).slice(2)}check(t=1){return this._store.__check__(t)}_clearGlobalState(t){return null!=this._scheduled[t]&&(clearTimeout(this._scheduled[t].expiration),delete this._scheduled[t],!0)}async _free(t,e,s,r){var i,n;try{if(({running:n}=await this._store.__free__(t,s.weight)),this.Events.trigger("debug",`Freed ${s.id}`,r),0===n&&this.empty())return this.Events.trigger("idle")}catch(t){return i=t,this.Events.trigger("error",i)}}_run(t,e,s){var r,i,n;return e.doRun(),r=this._clearGlobalState.bind(this,t),n=this._run.bind(this,t,e),i=this._free.bind(this,t,e),this._scheduled[t]={timeout:setTimeout((()=>e.doExecute(this._limiter,r,n,i)),s),expiration:null!=e.options.expiration?setTimeout((function(){return e.doExpire(r,n,i)}),s+e.options.expiration):void 0,job:e}}_drainOne(t){return this._registerLock.schedule((()=>{var e,s,r,i,n;return 0===this.queued()?this.Promise.resolve(null):(n=this._queues.getFirst(),({options:i,args:e}=r=n.first()),null!=t&&i.weight>t?this.Promise.resolve(null):(this.Events.trigger("debug",`Draining ${i.id}`,{args:e,options:i}),s=this._randomIndex(),this._store.__register__(s,i.weight,i.expiration).then((({success:t,wait:o,reservoir:a})=>{var h;return this.Events.trigger("debug",`Drained ${i.id}`,{success:t,args:e,options:i}),t?(n.shift(),(h=this.empty())&&this.Events.trigger("empty"),0===a&&this.Events.trigger("depleted",h),this._run(s,r,o),this.Promise.resolve(i.weight)):this.Promise.resolve(null)}))))}))}_drainAll(t,e=0){return this._drainOne(t).then((s=>{var r;return null!=s?(r=null!=t?t-s:t,this._drainAll(r,e+s)):this.Promise.resolve(e)})).catch((t=>this.Events.trigger("error",t)))}_dropAllQueued(t){return this._queues.shiftAll((function(e){return e.doDrop({message:t})}))}stop(e={}){var s,r;return e=S.load(e,this.stopDefaults),r=t=>{var e;return e=()=>{var e;return(e=this._states.counts)[0]+e[1]+e[2]+e[3]===t},new this.Promise(((t,s)=>e()?t():this.on("done",(()=>{if(e())return this.removeAllListeners("done"),t()}))))},s=e.dropWaitingJobs?(this._run=function(t,s){return s.doDrop({message:e.dropErrorMessage})},this._drainOne=()=>this.Promise.resolve(null),this._registerLock.schedule((()=>this._submitLock.schedule((()=>{var t,s,i;for(t in s=this._scheduled)i=s[t],"RUNNING"===this.jobStatus(i.job.options.id)&&(clearTimeout(i.timeout),clearTimeout(i.expiration),i.job.doDrop({message:e.dropErrorMessage}));return this._dropAllQueued(e.dropErrorMessage),r(0)}))))):this.schedule({priority:9,weight:0},(()=>r(1))),this._receive=function(s){return s._reject(new t.prototype.BottleneckError(e.enqueueErrorMessage))},this.stop=()=>this.Promise.reject(new t.prototype.BottleneckError("stop() has already been called")),s}async _addToQueue(e){var s,r,i,n,o,a,h;({args:s,options:n}=e);try{({reachedHWM:o,blocked:r,strategy:h}=await this._store.__submit__(this.queued(),n.weight))}catch(t){return i=t,this.Events.trigger("debug",`Could not queue ${n.id}`,{args:s,options:n,error:i}),e.doDrop({error:i}),!1}return r?(e.doDrop(),!0):o&&(null!=(a=h===t.prototype.strategy.LEAK?this._queues.shiftLastFrom(n.priority):h===t.prototype.strategy.OVERFLOW_PRIORITY?this._queues.shiftLastFrom(n.priority+1):h===t.prototype.strategy.OVERFLOW?e:void 0)&&a.doDrop(),null==a||h===t.prototype.strategy.OVERFLOW)?(null==a&&e.doDrop(),o):(e.doQueue(o,r),this._queues.push(e),await this._drainAll(),o)}_receive(e){return null!=this._states.jobStatus(e.options.id)?(e._reject(new t.prototype.BottleneckError(`A job with the same id already exists (id=${e.options.id})`)),!1):(e.doReceive(),this._submitLock.schedule(this._addToQueue,e))}submit(...t){var e,s,r,i,n,o,a;return"function"==typeof t[0]?(n=t,[s,...t]=n,[e]=N.call(t,-1),i=S.load({},this.jobDefaults)):(o=t,[i,s,...t]=o,[e]=N.call(t,-1),i=S.load(i,this.jobDefaults)),a=(...t)=>new this.Promise((function(e,r){return s(...t,(function(...t){return(null!=t[0]?r:e)(t)}))})),(r=new I(a,t,i,this.jobDefaults,this.rejectOnDrop,this.Events,this._states,this.Promise)).promise.then((function(t){return"function"==typeof e?e(...t):void 0})).catch((function(t){return Array.isArray(t)?"function"==typeof e?e(...t):void 0:"function"==typeof e?e(t):void 0})),this._receive(r)}schedule(...t){var e,s,r;return"function"==typeof t[0]?([r,...t]=t,s={}):[s,r,...t]=t,e=new I(r,t,s,this.jobDefaults,this.rejectOnDrop,this.Events,this._states,this.Promise),this._receive(e),e.promise}wrap(t){var e,s;return e=this.schedule.bind(this),(s=function(...s){return e(t.bind(this),...s)}).withOptions=function(s,...r){return e(s,t,...r)},s}async updateSettings(t={}){return await this._store.__updateSettings__(S.overwrite(t,this.storeDefaults)),S.overwrite(t,this.instanceDefaults,this),this}currentReservoir(){return this._store.__currentReservoir__()}incrementReservoir(t=0){return this._store.__incrementReservoir__(t)}}return t.default=t,t.Events=C,t.version=t.prototype.version=B.version,t.strategy=t.prototype.strategy={LEAK:1,OVERFLOW:2,OVERFLOW_PRIORITY:4,BLOCK:3},t.BottleneckError=t.prototype.BottleneckError=u,t.Group=t.prototype.Group=R,t.RedisConnection=t.prototype.RedisConnection=O,t.IORedisConnection=t.prototype.IORedisConnection=j,t.Batcher=t.prototype.Batcher=$,t.prototype.jobDefaults={priority:5,weight:1,expiration:null,id:"<no-id>"},t.prototype.storeDefaults={maxConcurrent:null,minTime:0,highWater:null,strategy:t.prototype.strategy.LEAK,penalty:null,reservoir:null,reservoirRefreshInterval:null,reservoirRefreshAmount:null,reservoirIncreaseInterval:null,reservoirIncreaseAmount:null,reservoirIncreaseMaximum:null},t.prototype.localStoreDefaults={Promise,timeout:null,heartbeatInterval:250},t.prototype.redisStoreDefaults={Promise,timeout:null,heartbeatInterval:5e3,clientTimeout:1e4,Redis:null,clientOptions:{},clusterNodes:null,clearDatastore:!1,connection:null},t.prototype.instanceDefaults={datastore:"local",connection:null,id:"<no-id>",rejectOnDrop:!0,trackDoneStatus:!1,Promise},t.prototype.stopDefaults={enqueueErrorMessage:"This limiter has been stopped and cannot accept new jobs.",dropWaitingJobs:!0,dropErrorMessage:"This limiter has been stopped."},t}.call(t);return U}()},310:t=>{"use strict";t.exports=t=>{if("[object Object]"!==Object.prototype.toString.call(t))return!1;const e=Object.getPrototypeOf(t);return null===e||e===Object.prototype}},942:function(t,e,s){"use strict";const r=s(310),{hasOwnProperty:i}=Object.prototype,{propertyIsEnumerable:n}=Object,o=(t,e,s)=>Object.defineProperty(t,e,{value:s,writable:!0,enumerable:!0,configurable:!0}),a=this,h={concatArrays:!1,ignoreUndefined:!1},u=t=>{const e=[];for(const s in t)i.call(t,s)&&e.push(s);if(Object.getOwnPropertySymbols){const s=Object.getOwnPropertySymbols(t);for(const r of s)n.call(t,r)&&e.push(r)}return e};function l(t){return Array.isArray(t)?function(t){const e=t.slice(0,0);return u(t).forEach((s=>{o(e,s,l(t[s]))})),e}(t):r(t)?function(t){const e=null===Object.getPrototypeOf(t)?Object.create(null):{};return u(t).forEach((s=>{o(e,s,l(t[s]))})),e}(t):t}const c=(t,e,s,r)=>(s.forEach((s=>{void 0===e[s]&&r.ignoreUndefined||(s in t&&t[s]!==Object.getPrototypeOf(t)?o(t,s,p(t[s],e[s],r)):o(t,s,l(e[s])))})),t);function p(t,e,s){return s.concatArrays&&Array.isArray(t)&&Array.isArray(e)?((t,e,s)=>{let r=t.slice(0,0),n=0;return[t,e].forEach((e=>{const a=[];for(let s=0;s<e.length;s++)i.call(e,s)&&(a.push(String(s)),o(r,n++,e===t?e[s]:l(e[s])));r=c(r,e,u(e).filter((t=>!a.includes(t))),s)})),r})(t,e,s):r(e)&&r(t)?c(t,e,u(e),s):l(e)}t.exports=function(...t){const e=p(l(h),this!==a&&this||{},h);let s={_:{}};for(const i of t)if(void 0!==i){if(!r(i))throw new TypeError("`"+i+"` is not an Option Object");s=p(s,{_:i},e)}return s._}},322:(t,e,s)=>{const r=s(427),i=s(942),n=s(526),o={jobOptions:{priority:0},rawContent:!1};t.exports=async(t,e)=>{t=r(t,"children"),e=i(o,e);let s=await n(t,e),a=await s.text();if(e.rawContent)return a;let h=a.match(/<url>.*?<\/url>/g).map((t=>{let e=t.match(/<loc>([^<]+)<\/loc>/),s=t.match(/<lastmod>([^<]+)<\/lastmod>/);return{path:r(e[1]),lastmod:s?Date.parse(s[1]):null}}));return h.length&&h[0].path===r(t)&&h.shift(),h}},565:(t,e,s)=>{const r=s(427),i=s(942),n=s(526),o={rawContent:!1};t.exports=async(t,e={})=>{t=r(t,"content"),e=i(o,e);let s=await n(t,e);if(e.rawContent)return await s.text();let a=s.headers.get("Content-Type");if(a.includes("/json"))return s.json();let h=await s.text();return a.includes("text/html")&&(h=h.replace(/\s+/g," ")),h}},526:(t,e,s)=>{const r=s(427).baseURL,i=s(268),n=new(s(209))({reservoir:150,reservoirRefreshAmount:150,reservoirRefreshInterval:5e3,maxConcurrent:10,trackDoneStatus:!0}),o=(t,e)=>i(t,e);t.exports=e=async(t,e)=>{let s=e?.jobOptions||{},i=await n.schedule(s,o,t,e);if(!i.ok)throw new Error(i.statusText);if(!i.url.startsWith(r))throw new Error("Invalid destination URL");return i},e.limiter=n},138:(t,e,s)=>{const r=s(526),i=s(427),n=s(322),o=s(565),a=s(873);t.exports={fetch:r,normalize:i,children:n,content:o,meta:a}},873:(t,e,s)=>{const r=s(427),i=s(942),n=s(526),o={jobOptions:{expiration:3e4},rawContent:!1},a={Jan:"01",Feb:"02",Mar:"03",Apr:"04",May:"05",Jun:"06",Jul:"07",Aug:"08",Sep:"09",Oct:"10",Nov:"11",Dec:"12"};t.exports=async(t,e)=>{t=r(t,"meta"),e=i(o,e);let s=await n(t,e);if(e.rawContent)return await s.text();if(!s.headers.get("content-type").includes("application/json"))throw new Error("Unexpected response content-type");let h=await s.json();return Object.keys(h).forEach((t=>{"true"===h[t]?h[t]=!0:"false"===h[t]?h[t]=!1:t.endsWith("@TypeHint")?delete h[t]:"string"==typeof h[t]?h[t]=function(t){if(/^\d{4}-\d{2}-\d{2}$/.test(t))return Date.parse(t);let e=/^\w{3} (\w{3}) (\d{2}) (\d{4}) ([\d:]{8}) GMT([\-+]\d{4})$/.exec(t);return e?Date.parse(e[3]+"-"+a[e[1]]+"-"+e[2]+"T"+e[4]+e[5]):t}(h[t]):Array.isArray(h[t])&&0===h[t].length&&delete h[t]})),Object.keys(h).sort().reduce(((t,e)=>(t[e]=h[e],t)),{})}},427:(t,e)=>{const s="https://www.canada.ca/";t.exports=e=(t,e="path")=>{if("string"==typeof t)t=new URL(t,s);else if(!(t instanceof URL))throw new TypeError("string or URL object expected");if(t.protocol="https",!t.href.startsWith(s))throw new Error("URL must start with "+s);let r=t.pathname.startsWith("/content/dam");if(r||(t.pathname=t.pathname.replace(/^\/content\/canadasite\//,"")),!/^\/(en|fr|content\/dam)(\/|\.|$)/.test(t.pathname))throw new Error("Invalid root");return t.pathname=t.pathname.replace(/\/+$/,""),"path"!==e&&t.searchParams.set("_",Date.now()),t.pathname.includes("/_jcr_content/par")?function(t,e){if("path"===e)throw new Error("Cant determine path of a reference node directly");if("meta"===e)t.pathname=t.pathname.replace(/\/image\.img\.\w+\//,"/image.json/");else if("children"===e)throw new Error("Cant load children of a reference node");return t.href}(t,e):r?function(t,e){let s=/(\/|\/\w+)$/.test(t.pathname);if("meta"===e)t.pathname+=s?".json":"/_jcr_content.json";else{if("children"===e)throw new Error("Cant load children of an asset node");if("content"===e&&s)throw new Error("Cant load content of an asset node")}return"path"===e?t.pathname:t.href}(t,e):function(t,e){return t.pathname=t.pathname.replace(/\/?\.(sitemap\.xml|[^/.]+)$/,""),"meta"===e?t.pathname+="/_jcr_content.json":"children"===e?t.pathname+=".sitemap.xml":"content"===e&&(t.pathname+=".html"),"path"===e?t.pathname:t.href}(t,e)},e.baseURL=s},268:e=>{"use strict";e.exports=t}},s={};function r(t){var i=s[t];if(void 0!==i)return i.exports;var n=s[t]={exports:{}};return e[t].call(n.exports,n,n.exports,r),n.exports}return r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),r(138)})()));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canada-api",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "Cross platform API to fetch data from canada.ca",
5
5
  "browser": "dist/ca.js",
6
6
  "main": "src/index.js",
@@ -18,7 +18,7 @@
18
18
  "api",
19
19
  "fetch"
20
20
  ],
21
- "author": "Ben Soicher",
21
+ "author": "National Defence",
22
22
  "license": "MIT",
23
23
  "homepage": "https://github.com/dnd-mdn/canada-api#readme",
24
24
  "bugs": "https://github.com/dnd-mdn/canada-api/issues",
package/src/children.js CHANGED
@@ -5,11 +5,13 @@ const fetch = require('./fetch.js')
5
5
  /**
6
6
  * Default fetch options
7
7
  * @const {object}
8
+ * @private
8
9
  */
9
10
  const defaultOptions = {
10
11
  jobOptions: {
11
12
  priority: 0
12
13
  },
14
+ rawContent: false
13
15
  }
14
16
 
15
17
  /**
@@ -21,10 +23,15 @@ const defaultOptions = {
21
23
  const children = async (url, options) => {
22
24
  url = normalize(url, 'children')
23
25
  options = merge(defaultOptions, options)
24
-
26
+
25
27
  let response = await fetch(url, options)
26
28
  let xml = await response.text()
27
29
 
30
+ // Return raw text
31
+ if (options.rawContent) {
32
+ return xml
33
+ }
34
+
28
35
  // Parse XML sitemap
29
36
  let children = xml.match(/<url>.*?<\/url>/g).map(url => {
30
37
  let loc = url.match(/<loc>([^<]+)<\/loc>/)
@@ -44,4 +51,5 @@ const children = async (url, options) => {
44
51
  return children
45
52
  }
46
53
 
54
+ // Default export
47
55
  module.exports = exports = children
package/src/content.js CHANGED
@@ -5,26 +5,31 @@ const fetch = require('./fetch.js')
5
5
  /**
6
6
  * Default fetch options
7
7
  * @const {object}
8
+ * @private
8
9
  */
9
10
  const defaultOptions = {
10
- jobOptions: {
11
- priority: 0
12
- }
11
+ rawContent: false
13
12
  }
14
13
 
15
14
  /**
16
15
  * Get node content
17
- * @param {string} url node url
16
+ * @param {string} url node URL
18
17
  * @param {Object} [options] fetch options
19
18
  * @returns {Promise<any>}
20
19
  */
21
- const content = async (url, options) => {
20
+ const content = async (url, options = {}) => {
22
21
  url = normalize(url, 'content')
23
22
  options = merge(defaultOptions, options)
24
-
23
+
25
24
  let response = await fetch(url, options)
26
- let type = response.headers.get('Content-Type')
27
25
 
26
+ // Return raw text
27
+ if (options.rawContent) {
28
+ return await response.text()
29
+ }
30
+
31
+ let type = response.headers.get('Content-Type')
32
+
28
33
  if (type.includes('/json')) {
29
34
  return response.json()
30
35
  }
@@ -34,9 +39,10 @@ const content = async (url, options) => {
34
39
  // Compress whitespace in html
35
40
  if (type.includes('text/html')) {
36
41
  text = text.replace(/\s+/g, ' ')
37
- }
42
+ }
38
43
 
39
44
  return text
40
45
  }
41
46
 
47
+ // Default export
42
48
  module.exports = exports = content
package/src/fetch.js CHANGED
@@ -1,3 +1,4 @@
1
+ const baseURL = require('./normalize').baseURL
1
2
  const crossFetch = require('cross-fetch')
2
3
  const Bottleneck = require('bottleneck/light.js')
3
4
 
@@ -5,6 +6,7 @@ const Bottleneck = require('bottleneck/light.js')
5
6
  * Default limiter options
6
7
  * @see https://stackleap.io/js/bottleneck#user-content-constructor
7
8
  * @const {object}
9
+ * @private
8
10
  */
9
11
  const limiterOptions = {
10
12
  reservoir: 150,
@@ -16,15 +18,17 @@ const limiterOptions = {
16
18
 
17
19
  /**
18
20
  * Rate limiter
19
- * @type {Bottleneck}
21
+ * @const {Bottleneck}
20
22
  */
21
23
  const limiter = new Bottleneck(limiterOptions)
22
24
 
23
25
  /**
24
26
  * Passthrough arguments to prevent running method on non window object
25
- * @const {function}
27
+ * @param {string|URL} url
28
+ * @param {object} [options] Fetch options
29
+ * @private
26
30
  */
27
- const passthrough = (url, options) => crossFetch(url, options)
31
+ const pFetch = (url, options) => crossFetch(url, options)
28
32
 
29
33
  /**
30
34
  * Modified rate limited fetch
@@ -33,23 +37,19 @@ const passthrough = (url, options) => crossFetch(url, options)
33
37
  * @returns {Promise<Response>}
34
38
  */
35
39
  const fetch = async (url, options) => {
36
-
37
- let response = await limiter.schedule(options?.jobOptions || {}, passthrough, url, options)
40
+ let jobOptions = options?.jobOptions || {}
41
+ let response = await limiter.schedule(jobOptions, pFetch, url, options)
38
42
 
39
- // Verify response
43
+ // Verify response code
40
44
  if (!response.ok) {
41
45
  throw new Error(response.statusText)
42
46
  }
43
47
 
44
- if (typeof url === 'string') {
45
- url = new URL(url)
48
+ // Verify destination
49
+ if (!response.url.startsWith(baseURL)) {
50
+ throw new Error('Invalid destination URL')
46
51
  }
47
52
 
48
- // Prevent host redirect
49
- if (url.hostname !== new URL(response.url).hostname) {
50
- throw new Error('Redirect to invalid host')
51
- }
52
-
53
53
  return response
54
54
  }
55
55
 
package/src/index.js CHANGED
@@ -2,7 +2,7 @@ const fetch = require('./fetch.js')
2
2
  const normalize = require('./normalize.js')
3
3
  const children = require('./children.js')
4
4
  const content = require('./content.js')
5
- const meta = require ('./meta.js')
5
+ const meta = require('./meta.js')
6
6
 
7
7
  module.exports = exports = {
8
8
  // Core
package/src/meta.js CHANGED
@@ -5,11 +5,13 @@ const fetch = require('./fetch.js')
5
5
  /**
6
6
  * Default fetch options
7
7
  * @const {object}
8
+ * @private
8
9
  */
9
10
  const defaultOptions = {
10
11
  jobOptions: {
11
12
  expiration: 30000
12
- }
13
+ },
14
+ rawContent: false
13
15
  }
14
16
 
15
17
  /**
@@ -24,7 +26,13 @@ const meta = async (url, options) => {
24
26
 
25
27
  let response = await fetch(url, options)
26
28
 
27
- if (!response.headers.get('content-type').includes('/json')) {
29
+ // Return raw text
30
+ if (options.rawContent) {
31
+ return await response.text()
32
+ }
33
+
34
+ // Verify content-type
35
+ if (!response.headers.get('content-type').includes('application/json')) {
28
36
  throw new Error('Unexpected response content-type')
29
37
  }
30
38
 
@@ -55,6 +63,7 @@ const meta = async (url, options) => {
55
63
  /**
56
64
  * Map month name to number
57
65
  * @const {object}
66
+ * @private
58
67
  */
59
68
  const months = {
60
69
  'Jan': '01', 'Feb': '02', 'Mar': '03', 'Apr': '04', 'May': '05', 'Jun': '06',
@@ -65,6 +74,7 @@ const months = {
65
74
  * Try to parse a date
66
75
  * @param {string} date
67
76
  * @returns {number|string}
77
+ * @private
68
78
  */
69
79
  function maybeParseDate(date) {
70
80
  // Simple
@@ -81,4 +91,5 @@ function maybeParseDate(date) {
81
91
  return date
82
92
  }
83
93
 
94
+ // Default export
84
95
  module.exports = exports = meta
package/src/normalize.js CHANGED
@@ -2,6 +2,7 @@
2
2
  /**
3
3
  * Base URL
4
4
  * @const {string}
5
+ * @private
5
6
  */
6
7
  const baseURL = 'https://www.canada.ca/'
7
8
 
@@ -62,6 +63,7 @@ const normalize = (url, type = 'path') => {
62
63
  * @param {URL} url
63
64
  * @param {string} type
64
65
  * @returns {URL}
66
+ * @private
65
67
  */
66
68
  function normalizePage(url, type) {
67
69
  // Remove existing extension
@@ -83,6 +85,7 @@ function normalizePage(url, type) {
83
85
  * @param {URL} url
84
86
  * @param {string} type
85
87
  * @returns {URL}
88
+ * @private
86
89
  */
87
90
  function normalizeAsset(url, type) {
88
91
  let isDir = /(\/|\/\w+)$/.test(url.pathname)
@@ -103,6 +106,7 @@ function normalizeAsset(url, type) {
103
106
  * @param {URL} url
104
107
  * @param {string} type
105
108
  * @returns {URL}
109
+ * @private
106
110
  */
107
111
  function normalizeReference(url, type) {
108
112
 
@@ -117,4 +121,8 @@ function normalizeReference(url, type) {
117
121
  return url.href
118
122
  }
119
123
 
124
+ // Default export
120
125
  module.exports = exports = normalize
126
+
127
+ // Expose the baseURL
128
+ exports.baseURL = baseURL
package/test.html DELETED
@@ -1,8 +0,0 @@
1
- <html>
2
- <body>
3
- <script src="dist/ca.js"></script>
4
- <script>
5
- console.log(ca)
6
- </script>
7
- </body>
8
- </html>