canada-api 2.0.5 → 3.0.0
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 → LICENSE} +1 -1
- package/README.md +97 -56
- package/dist/ca.js +1 -1
- package/package.json +1 -1
- package/src/basic/children.js +9 -31
- package/src/basic/content.js +3 -38
- package/src/basic/meta.js +17 -43
- package/src/core/normalize.js +3 -8
- package/src/core/request.js +90 -0
- package/src/index.js +2 -2
- package/src/core/fetch.js +0 -60
package/{LICENSE.md → LICENSE}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) His Majesty the King in Right of Canada, as represented by the Minister of National Defence, 2022.
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -4,51 +4,61 @@
|
|
|
4
4
|
|
|
5
5
|
Cross platform API for fetching public data from [canada.ca](https://www.canada.ca).
|
|
6
6
|
|
|
7
|
-
## Install
|
|
8
|
-
### Browsers
|
|
9
7
|
|
|
8
|
+
## Browser
|
|
10
9
|
```html
|
|
11
|
-
<script src="https://cdn.jsdelivr.net/npm/canada-api@
|
|
12
|
-
<script>
|
|
13
|
-
ca.meta("en/department-national-defence").then(meta => {
|
|
14
|
-
console.log(meta)
|
|
15
|
-
})
|
|
16
|
-
</script>
|
|
10
|
+
<script src="https://cdn.jsdelivr.net/npm/canada-api@3.0.0"></script>
|
|
17
11
|
```
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
## Node 10+
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
### Install
|
|
16
|
+
|
|
17
|
+
```shell
|
|
18
|
+
npm install canada-api
|
|
24
19
|
```
|
|
25
20
|
|
|
21
|
+
### Usage
|
|
26
22
|
|
|
23
|
+
```js
|
|
24
|
+
const ca = require('canada-api')
|
|
25
|
+
```
|
|
27
26
|
|
|
28
27
|
## Core API
|
|
29
28
|
|
|
30
|
-
### `ca.
|
|
29
|
+
### `ca.request(url)`
|
|
30
|
+
|
|
31
|
+
- `url` {string|URL} relative or absolute URL on [canada.ca](https://www.canada.ca)
|
|
32
|
+
- Returns: {Promise} Fulfills with {Object} upon success
|
|
33
|
+
|
|
34
|
+
Throws {Error} if the request does not complete successfully or if the destination URL is not on [canada.ca](https://www.canada.ca).
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
- `
|
|
34
|
-
|
|
35
|
-
-
|
|
36
|
+
The properties included on each object:
|
|
37
|
+
- `url` {string} destination URL
|
|
38
|
+
- `redirected` {boolean} If the destination path is different from the request
|
|
39
|
+
- `data` {string|Object} Document content as string or json data
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"url": "https://www.canada.ca/en/department-national-defence.html",
|
|
44
|
+
"redirected": false,
|
|
45
|
+
"data": "<!DOCTYPE html>\r\n...."
|
|
46
|
+
}
|
|
47
|
+
```
|
|
38
48
|
|
|
39
49
|
|
|
40
|
-
### `ca.
|
|
50
|
+
### `ca.request.limiter`
|
|
41
51
|
|
|
42
52
|
- {Bottleneck}
|
|
43
53
|
|
|
44
|
-
The [Rate limiter](https://github.com/SGrondin/bottleneck#readme) used in `ca.
|
|
54
|
+
The [Rate limiter](https://github.com/SGrondin/bottleneck#readme) used in `ca.request()`.
|
|
45
55
|
|
|
46
56
|
|
|
47
57
|
### `ca.normalize(url[, type])`
|
|
48
58
|
|
|
49
59
|
- `url` {string|URL} node URL
|
|
50
60
|
- `type` {string} Possible values `'path'`, `'children'`, `'content'` or `'meta'`. **Default**: `'path'`
|
|
51
|
-
- Returns: {
|
|
61
|
+
- Returns: {URL} Normalized URL
|
|
52
62
|
|
|
53
63
|
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
64
|
|
|
@@ -63,58 +73,89 @@ Base URL used for resolving relative URLs as well as URL validation. Value is `'
|
|
|
63
73
|
|
|
64
74
|
## Basic API
|
|
65
75
|
|
|
66
|
-
### `ca.children(url
|
|
76
|
+
### `ca.children(url)`
|
|
67
77
|
|
|
68
78
|
- `url` {string|URL} absolute or relative URL
|
|
69
|
-
-
|
|
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
|
|
79
|
+
- Returns: {Promise} Fulfills with {Object} containing child nodes
|
|
73
80
|
|
|
74
81
|
Parses sitemaps to get a list of child nodes.
|
|
75
82
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
-
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"url": "https://www.canada.ca/en/department-national-defence.sitemap.xml",
|
|
86
|
+
"redirected": false,
|
|
87
|
+
"data": [
|
|
88
|
+
{
|
|
89
|
+
"url": "https://www.canada.ca/en/department-national-defence/...",
|
|
90
|
+
"lastmod": "2022-09-20T00:00:00.000Z"
|
|
91
|
+
},
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
```
|
|
79
95
|
|
|
80
|
-
|
|
96
|
+
Getting children of DAM folders/assets is not available.
|
|
81
97
|
|
|
82
|
-
### `ca.content(url
|
|
98
|
+
### `ca.content(url)`
|
|
83
99
|
|
|
84
100
|
- `url` {string|URL} absolute or relative URL
|
|
85
|
-
-
|
|
86
|
-
- `jobOptions` {Object} rate limiter [job options](https://github.com/SGrondin/bottleneck#job-options)
|
|
87
|
-
- `rawContent` {boolean} Fulfills with unmodified {string} **Default:** `false`
|
|
88
|
-
- Returns: {Promise} Fulfills with {string|Object}
|
|
101
|
+
- Returns: {Promise} Fulfills with {Object} containing document contents
|
|
89
102
|
|
|
90
|
-
Retrieves the document contents.
|
|
91
|
-
- `'application/json'` parses response and fulfills with {Object}
|
|
92
|
-
- `'text/html'` compresses whitespace and fulfills with {string}
|
|
93
|
-
- Other types are fulfilled as {string} with no modification
|
|
103
|
+
Retrieves the document contents.
|
|
94
104
|
|
|
95
|
-
|
|
105
|
+
The properties included on each object:
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"url": "https://www.canada.ca/en/department-national-defence.html",
|
|
109
|
+
"redirected": false,
|
|
110
|
+
"data": "<!DOCTYPE html>\r\n...."
|
|
111
|
+
}
|
|
112
|
+
```
|
|
96
113
|
|
|
97
|
-
|
|
114
|
+
Can also be used for DAM assets:
|
|
98
115
|
|
|
99
|
-
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"url": "https://www.canada.ca/content/dam/dnd-mdn/documents/json/maple-en.json",
|
|
119
|
+
"redirected": false,
|
|
120
|
+
"data": {
|
|
121
|
+
"data": []
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
100
125
|
|
|
101
|
-
### `ca.meta(url
|
|
126
|
+
### `ca.meta(url)`
|
|
102
127
|
|
|
103
128
|
- `url` {string|URL} absolute or relative URL
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
129
|
+
- Returns: {Promise} Fulfills with {Object} containing metadata properties
|
|
130
|
+
|
|
131
|
+
Nodes contain a variety of metadata properties that can be accessed through a public API. Some properties such as date formats are reformatted for consistency.
|
|
132
|
+
|
|
133
|
+
The properties included on each object:
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"url": "https://www.canada.ca/en/department-national-defence/_jcr_content.json",
|
|
137
|
+
"redirected": false,
|
|
138
|
+
"data": {
|
|
139
|
+
"cq:lastModified": "2022-10-25T19:16:28.000Z",
|
|
140
|
+
"fluidWidth": false,
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
116
144
|
|
|
145
|
+
Can also be used for DAM assets:
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"url": "https://www.canada.ca/content/dam/dnd-mdn/documents/json/maple-en.json/_jcr_content.json",
|
|
150
|
+
"redirected": false,
|
|
151
|
+
"data": {
|
|
152
|
+
"dam:assetState": "processed",
|
|
153
|
+
"jcr:lastModified": "2022-10-26T19:39:54.000Z",
|
|
154
|
+
"jcr:primaryType": "dam:AssetContent"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
117
158
|
|
|
118
159
|
## Extended API
|
|
119
160
|
|
|
120
|
-
TBD
|
|
161
|
+
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 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._}},920:(t,e,s)=>{const r=s(797),i=s(942),n=s(322);let o={jobOptions:{priority:0},rawContent:!1};t.exports=e=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},e.defaultOptions=o},420:(t,e,s)=>{const r=s(797),i=s(942),n=s(322);let o={rawContent:!1};t.exports=e=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},e.defaultOptions=o},30:(t,e,s)=>{const r=s(797),i=s(942),n=s(322);let o={jobOptions:{expiration:3e4},rawContent:!1};const 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=e=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)),{})},e.defaultOptions=o},322:(t,e,s)=>{const r=s(797).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},797:(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},138:(t,e,s)=>{const r=s(322),i=s(797),n=s(920),o=s(420),a=s(30);t.exports={fetch:r,normalize:i,children:n,content:o,meta:a}},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,d=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 p;p=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."),x=()=>console.log("You must import the full version of Bottleneck in order to use this feature.");y=i,f=o,m=O,v=x,g=()=>console.log("You must import the full version of Bottleneck in order to use this feature.");var j,R,k=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);R=i,j=o;var I,D,C,L,T,S,P,A,q,$=function(){class t{constructor(t={}){this.options=t,R.load(this.options,this.defaults,this),this.Events=new j(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;A=i,L=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()}},D=d,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."),I=o,S=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 p(`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)),{})}},P=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),A.load(e,this.instanceDefaults,this),this._queues=new L(10),this._scheduled={},this._states=new S(["RECEIVED","QUEUED","RUNNING","EXECUTING"].concat(this.trackDoneStatus?["DONE"]:[])),this._limiter=null,this.Events=new I(this),this._submitLock=new P("submit",this.Promise),this._registerLock=new P("register",this.Promise),i=A.load(e,this.storeDefaults,{}),this._store=function(){if("redis"===this.datastore||"ioredis"===this.datastore||null!=this.connection)return r=A.load(e,this.redisStoreDefaults,{}),new T(this,i,r);if("local"===this.datastore)return r=A.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=A.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=A.load({},this.jobDefaults)):(o=t,[i,s,...t]=o,[e]=N.call(t,-1),i=A.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 D(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 D(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__(A.overwrite(t,this.storeDefaults)),A.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=I,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=k,t.RedisConnection=t.prototype.RedisConnection=O,t.IORedisConnection=t.prototype.IORedisConnection=x,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}()},920:(t,e,s)=>{const r=s(797),i=s(36);t.exports=async t=>{t=r(t,"children");let e=await i(t),s=e.data.match(/<url>.*?<\/url>/g).map((t=>{let e=t.match(/<loc>([^<]+)<\/loc>/),s=t.match(/<lastmod>([^<]+)<\/lastmod>/);return{url:r(e[1]).pathname,lastmod:s?new Date(s[1]).toISOString():null}}));return s.length&&s[0].url===r(t).pathname&&s.shift(),e.data=s,e}},420:(t,e,s)=>{const r=s(797),i=s(36);t.exports=async t=>(t=r(t,"content"),i(t))},30:(t,e,s)=>{const r=s(797),i=s(36),n={Jan:"01",Feb:"02",Mar:"03",Apr:"04",May:"05",Jun:"06",Jul:"07",Aug:"08",Sep:"09",Oct:"10",Nov:"11",Dec:"12"};function o(t){if(/^\d{4}-\d{2}-\d{2}$/.test(t))return new Date(t).toISOString();let e=/^\w{3} (\w{3}) (\d{2}) (\d{4}) ([\d:]{8}) GMT([\-+]\d{4})$/.exec(t);return e?new Date(e[3]+"-"+n[e[1]]+"-"+e[2]+"T"+e[4]+e[5]).toISOString():t}t.exports=async t=>{t=r(t,"meta");let e=await i(t),s=e.data;for(const[t,e]of Object.entries(s))"true"===e?s[t]=!0:"false"===e?s[t]=!1:t.endsWith("@TypeHint")?delete s[t]:"string"==typeof e?s[t]=o(s[t].trim()):Array.isArray(e)&&0===e.length&&delete s[t];return e.data=Object.keys(e.data).sort().reduce(((t,e)=>(t[e]=s[e],t)),{}),e}},797:(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(/\/+$/,""),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}(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 t}(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"),t}(t,e)},e.baseURL=s},36:(t,e,s)=>{const r=s(797),i=s(268),n=new(s(209))({reservoir:150,reservoirRefreshAmount:150,reservoirRefreshInterval:5e3,maxConcurrent:10,trackDoneStatus:!0}),o=t=>i(t);async function a(t){return t.headers.get("content-type").includes("application/json")?t.json():t.text()}t.exports=e=async function(t){"string"==typeof t&&(t=new URL(t,r.baseURL)),t.searchParams.set("_",Date.now());let e=await n.schedule(o,t);if(!e.ok)throw new Error(e.statusText);if(!e.url.startsWith(r.baseURL))throw new Error("Invalid destination URL");let s=r(t).pathname!==r(e.url).pathname;return{url:e.url,redirected:s,data:await a(e)}},e.limiter=n},138:(t,e,s)=>{const r=s(36),i=s(797),n=s(920),o=s(420),a=s(30);t.exports={request:r,normalize:i,children:n,content:o,meta:a}},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
package/src/basic/children.js
CHANGED
|
@@ -1,57 +1,35 @@
|
|
|
1
1
|
const normalize = require('../core/normalize.js')
|
|
2
|
-
const
|
|
3
|
-
const fetch = require('../core/fetch.js')
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Default fetch options
|
|
7
|
-
* @type {object}
|
|
8
|
-
*/
|
|
9
|
-
let defaultOptions = {
|
|
10
|
-
jobOptions: {
|
|
11
|
-
priority: 0
|
|
12
|
-
},
|
|
13
|
-
rawContent: false
|
|
14
|
-
}
|
|
2
|
+
const request = require('../core/request.js')
|
|
15
3
|
|
|
16
4
|
/**
|
|
17
5
|
* Get list of child nodes from sitemap
|
|
18
6
|
* @param {string} url node url
|
|
19
|
-
* @param {Object} [options] fetch options
|
|
20
7
|
* @returns {Promise<Array>}
|
|
21
8
|
*/
|
|
22
|
-
const children = async
|
|
9
|
+
const children = async url => {
|
|
23
10
|
url = normalize(url, 'children')
|
|
24
|
-
options = merge(defaultOptions, options)
|
|
25
11
|
|
|
26
|
-
let response = await
|
|
27
|
-
let xml = await response.text()
|
|
28
|
-
|
|
29
|
-
// Return raw text
|
|
30
|
-
if (options.rawContent) {
|
|
31
|
-
return xml
|
|
32
|
-
}
|
|
12
|
+
let response = await request(url)
|
|
33
13
|
|
|
34
14
|
// Parse XML sitemap
|
|
35
|
-
let children =
|
|
15
|
+
let children = response.data.match(/<url>.*?<\/url>/g).map(url => {
|
|
36
16
|
let loc = url.match(/<loc>([^<]+)<\/loc>/)
|
|
37
17
|
let mod = url.match(/<lastmod>([^<]+)<\/lastmod>/)
|
|
38
18
|
|
|
39
19
|
return {
|
|
40
|
-
|
|
41
|
-
lastmod: mod ? Date
|
|
20
|
+
url: normalize(loc[1]).pathname,
|
|
21
|
+
lastmod: mod ? new Date(mod[1]).toISOString() : null
|
|
42
22
|
}
|
|
43
23
|
})
|
|
44
24
|
|
|
45
25
|
// First entry may be the parent
|
|
46
|
-
if (children.length && children[0].
|
|
26
|
+
if (children.length && children[0].url === normalize(url).pathname) {
|
|
47
27
|
children.shift()
|
|
48
28
|
}
|
|
49
29
|
|
|
50
|
-
|
|
30
|
+
response.data = children
|
|
31
|
+
return response
|
|
51
32
|
}
|
|
52
33
|
|
|
53
34
|
// Default export
|
|
54
35
|
module.exports = exports = children
|
|
55
|
-
|
|
56
|
-
// Expose default options
|
|
57
|
-
exports.defaultOptions = defaultOptions
|
package/src/basic/content.js
CHANGED
|
@@ -1,50 +1,15 @@
|
|
|
1
1
|
const normalize = require('../core/normalize.js')
|
|
2
|
-
const
|
|
3
|
-
const fetch = require('../core/fetch.js')
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Default fetch options
|
|
7
|
-
* @type {object}
|
|
8
|
-
*/
|
|
9
|
-
let defaultOptions = {
|
|
10
|
-
rawContent: false
|
|
11
|
-
}
|
|
2
|
+
const request = require('../core/request.js')
|
|
12
3
|
|
|
13
4
|
/**
|
|
14
5
|
* Get node content
|
|
15
6
|
* @param {string} url node URL
|
|
16
|
-
* @param {Object} [options] fetch options
|
|
17
7
|
* @returns {Promise<any>}
|
|
18
8
|
*/
|
|
19
|
-
const content = async
|
|
9
|
+
const content = async url => {
|
|
20
10
|
url = normalize(url, 'content')
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
let response = await fetch(url, options)
|
|
24
|
-
|
|
25
|
-
// Return raw text
|
|
26
|
-
if (options.rawContent) {
|
|
27
|
-
return await response.text()
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
let type = response.headers.get('Content-Type')
|
|
31
|
-
|
|
32
|
-
if (type.includes('/json')) {
|
|
33
|
-
return response.json()
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let text = await response.text()
|
|
37
|
-
|
|
38
|
-
// Compress whitespace in html
|
|
39
|
-
if (type.includes('text/html')) {
|
|
40
|
-
text = text.replace(/\s+/g, ' ')
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return text
|
|
11
|
+
return request(url)
|
|
44
12
|
}
|
|
45
13
|
|
|
46
14
|
// Default export
|
|
47
15
|
module.exports = exports = content
|
|
48
|
-
|
|
49
|
-
// Expose default options
|
|
50
|
-
exports.defaultOptions = defaultOptions
|
package/src/basic/meta.js
CHANGED
|
@@ -1,62 +1,39 @@
|
|
|
1
1
|
const normalize = require('../core/normalize.js')
|
|
2
|
-
const
|
|
3
|
-
const fetch = require('../core/fetch.js')
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Default fetch options
|
|
7
|
-
* @type {object}
|
|
8
|
-
*/
|
|
9
|
-
let defaultOptions = {
|
|
10
|
-
jobOptions: {
|
|
11
|
-
expiration: 30000
|
|
12
|
-
},
|
|
13
|
-
rawContent: false
|
|
14
|
-
}
|
|
2
|
+
const request = require('../core/request.js')
|
|
15
3
|
|
|
16
4
|
/**
|
|
17
5
|
* Get node metadata from jcr content
|
|
18
6
|
* @param {string} url node path
|
|
19
|
-
* @param {Object} [options] fetch options
|
|
20
7
|
* @returns {Promise<Object>}
|
|
21
8
|
*/
|
|
22
|
-
const meta = async
|
|
9
|
+
const meta = async url => {
|
|
23
10
|
url = normalize(url, 'meta')
|
|
24
|
-
options = merge(defaultOptions, options)
|
|
25
|
-
|
|
26
|
-
let response = await fetch(url, options)
|
|
27
|
-
|
|
28
|
-
// Return raw text
|
|
29
|
-
if (options.rawContent) {
|
|
30
|
-
return await response.text()
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Verify content-type
|
|
34
|
-
if (!response.headers.get('content-type').includes('application/json')) {
|
|
35
|
-
throw new Error('Unexpected response content-type')
|
|
36
|
-
}
|
|
37
11
|
|
|
38
|
-
let
|
|
12
|
+
let response = await request(url)
|
|
13
|
+
let json = response.data
|
|
39
14
|
|
|
40
|
-
// Format
|
|
41
|
-
Object.
|
|
42
|
-
if (
|
|
15
|
+
// Format some properties for consistency
|
|
16
|
+
for (const [key, value] of Object.entries(json)) {
|
|
17
|
+
if (value === 'true') {
|
|
43
18
|
json[key] = true
|
|
44
|
-
} else if (
|
|
19
|
+
} else if (value === 'false') {
|
|
45
20
|
json[key] = false
|
|
46
21
|
} else if (key.endsWith('@TypeHint')) {
|
|
47
22
|
delete json[key]
|
|
48
|
-
} else if (typeof
|
|
49
|
-
json[key] = maybeParseDate(json[key])
|
|
50
|
-
} else if (Array.isArray(
|
|
23
|
+
} else if (typeof value === 'string') {
|
|
24
|
+
json[key] = maybeParseDate(json[key].trim())
|
|
25
|
+
} else if (Array.isArray(value) && value.length === 0) {
|
|
51
26
|
delete json[key]
|
|
52
27
|
}
|
|
53
|
-
}
|
|
28
|
+
}
|
|
54
29
|
|
|
55
30
|
// Sort object keys alphabetically for readability
|
|
56
|
-
|
|
31
|
+
response.data = Object.keys(response.data).sort().reduce((obj, key) => {
|
|
57
32
|
obj[key] = json[key]
|
|
58
33
|
return obj
|
|
59
34
|
}, {})
|
|
35
|
+
|
|
36
|
+
return response
|
|
60
37
|
}
|
|
61
38
|
|
|
62
39
|
/**
|
|
@@ -78,13 +55,13 @@ const months = {
|
|
|
78
55
|
function maybeParseDate(date) {
|
|
79
56
|
// Simple
|
|
80
57
|
if (/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
81
|
-
return Date
|
|
58
|
+
return new Date(date).toISOString()
|
|
82
59
|
}
|
|
83
60
|
|
|
84
61
|
// RFC1123
|
|
85
62
|
let m = /^\w{3} (\w{3}) (\d{2}) (\d{4}) ([\d:]{8}) GMT([\-+]\d{4})$/.exec(date)
|
|
86
63
|
if (m) {
|
|
87
|
-
return Date
|
|
64
|
+
return new Date(m[3] + '-' + months[m[1]] + '-' + m[2] + 'T' + m[4] + m[5]).toISOString()
|
|
88
65
|
}
|
|
89
66
|
|
|
90
67
|
return date
|
|
@@ -92,6 +69,3 @@ function maybeParseDate(date) {
|
|
|
92
69
|
|
|
93
70
|
// Default export
|
|
94
71
|
module.exports = exports = meta
|
|
95
|
-
|
|
96
|
-
// Expose default options
|
|
97
|
-
exports.defaultOptions = defaultOptions
|
package/src/core/normalize.js
CHANGED
|
@@ -43,11 +43,6 @@ const normalize = (url, type = 'path') => {
|
|
|
43
43
|
// Strip Trailing slashes
|
|
44
44
|
url.pathname = url.pathname.replace(/\/+$/, '')
|
|
45
45
|
|
|
46
|
-
// Cache busting
|
|
47
|
-
if (type !== 'path') {
|
|
48
|
-
url.searchParams.set('_', Date.now())
|
|
49
|
-
}
|
|
50
|
-
|
|
51
46
|
// Handle other URL types
|
|
52
47
|
if (url.pathname.includes('/_jcr_content/par')) {
|
|
53
48
|
return normalizeReference(url, type)
|
|
@@ -77,7 +72,7 @@ function normalizePage(url, type) {
|
|
|
77
72
|
url.pathname += '.html'
|
|
78
73
|
}
|
|
79
74
|
|
|
80
|
-
return
|
|
75
|
+
return url
|
|
81
76
|
}
|
|
82
77
|
|
|
83
78
|
/**
|
|
@@ -98,7 +93,7 @@ function normalizeAsset(url, type) {
|
|
|
98
93
|
throw new Error('Cant load content of an asset node')
|
|
99
94
|
}
|
|
100
95
|
|
|
101
|
-
return
|
|
96
|
+
return url
|
|
102
97
|
}
|
|
103
98
|
|
|
104
99
|
/**
|
|
@@ -118,7 +113,7 @@ function normalizeReference(url, type) {
|
|
|
118
113
|
throw new Error('Cant load children of a reference node')
|
|
119
114
|
}
|
|
120
115
|
|
|
121
|
-
return url
|
|
116
|
+
return url
|
|
122
117
|
}
|
|
123
118
|
|
|
124
119
|
// Default export
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const normalize = require('./normalize')
|
|
2
|
+
const crossFetch = require('cross-fetch')
|
|
3
|
+
const Bottleneck = require('bottleneck/light.js')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Default limiter options
|
|
7
|
+
* @see https://stackleap.io/js/bottleneck#user-content-constructor
|
|
8
|
+
* @const {object}
|
|
9
|
+
* @private
|
|
10
|
+
*/
|
|
11
|
+
const limiterOptions = {
|
|
12
|
+
reservoir: 150,
|
|
13
|
+
reservoirRefreshAmount: 150,
|
|
14
|
+
reservoirRefreshInterval: 5000,
|
|
15
|
+
maxConcurrent: 10,
|
|
16
|
+
trackDoneStatus: true
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Rate limiter
|
|
21
|
+
* @const {Bottleneck}
|
|
22
|
+
*/
|
|
23
|
+
const limiter = new Bottleneck(limiterOptions)
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Passthrough to prevent running method on non window object
|
|
27
|
+
* @param {string|URL} url
|
|
28
|
+
* @private
|
|
29
|
+
*/
|
|
30
|
+
const pFetch = url => crossFetch(url)
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Modified rate limited fetch
|
|
34
|
+
* @param {string|URL} url
|
|
35
|
+
* @param {object} [options] Fetch options
|
|
36
|
+
* @returns {Promise<Object>}
|
|
37
|
+
*/
|
|
38
|
+
async function request(url) {
|
|
39
|
+
|
|
40
|
+
// Handle relative URLs
|
|
41
|
+
if (typeof url === 'string') {
|
|
42
|
+
url = new URL(url, normalize.baseURL)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Set cache busting param
|
|
46
|
+
url.searchParams.set('_', Date.now())
|
|
47
|
+
|
|
48
|
+
let response = await limiter.schedule(pFetch, url)
|
|
49
|
+
|
|
50
|
+
// Verify response code
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new Error(response.statusText)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Verify destination
|
|
56
|
+
if (!response.url.startsWith(normalize.baseURL)) {
|
|
57
|
+
throw new Error('Invalid destination URL')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Determine if path changed
|
|
61
|
+
let redirected = normalize(url).pathname !== normalize(response.url).pathname
|
|
62
|
+
|
|
63
|
+
// Format result
|
|
64
|
+
return {
|
|
65
|
+
url: response.url,
|
|
66
|
+
redirected: redirected,
|
|
67
|
+
data: await responseData(response),
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get data of the response by type
|
|
73
|
+
* @param {Response} response
|
|
74
|
+
* @returns {Promise<any>}
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
async function responseData(response) {
|
|
78
|
+
const contentType = response.headers.get('content-type')
|
|
79
|
+
|
|
80
|
+
// Parse JSON
|
|
81
|
+
if (contentType.includes('application/json')) {
|
|
82
|
+
return response.json()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return response.text()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Exports
|
|
89
|
+
module.exports = exports = request
|
|
90
|
+
exports.limiter = limiter
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const request = require('./core/request.js')
|
|
2
2
|
const normalize = require('./core/normalize.js')
|
|
3
3
|
const children = require('./basic/children.js')
|
|
4
4
|
const content = require('./basic/content.js')
|
|
@@ -6,7 +6,7 @@ const meta = require('./basic/meta.js')
|
|
|
6
6
|
|
|
7
7
|
module.exports = exports = {
|
|
8
8
|
// Core
|
|
9
|
-
|
|
9
|
+
request,
|
|
10
10
|
normalize,
|
|
11
11
|
|
|
12
12
|
// Basic API
|
package/src/core/fetch.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
const baseURL = require('./normalize').baseURL
|
|
2
|
-
const crossFetch = require('cross-fetch')
|
|
3
|
-
const Bottleneck = require('bottleneck/light.js')
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Default limiter options
|
|
7
|
-
* @see https://stackleap.io/js/bottleneck#user-content-constructor
|
|
8
|
-
* @const {object}
|
|
9
|
-
* @private
|
|
10
|
-
*/
|
|
11
|
-
const limiterOptions = {
|
|
12
|
-
reservoir: 150,
|
|
13
|
-
reservoirRefreshAmount: 150,
|
|
14
|
-
reservoirRefreshInterval: 5000,
|
|
15
|
-
maxConcurrent: 10,
|
|
16
|
-
trackDoneStatus: true
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Rate limiter
|
|
21
|
-
* @const {Bottleneck}
|
|
22
|
-
*/
|
|
23
|
-
const limiter = new Bottleneck(limiterOptions)
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Passthrough arguments to prevent running method on non window object
|
|
27
|
-
* @param {string|URL} url
|
|
28
|
-
* @param {object} [options] Fetch options
|
|
29
|
-
* @private
|
|
30
|
-
*/
|
|
31
|
-
const pFetch = (url, options) => crossFetch(url, options)
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Modified rate limited fetch
|
|
35
|
-
* @param {string|URL} url
|
|
36
|
-
* @param {object} [options] Fetch options
|
|
37
|
-
* @returns {Promise<Response>}
|
|
38
|
-
*/
|
|
39
|
-
const fetch = async (url, options) => {
|
|
40
|
-
let jobOptions = options?.jobOptions || {}
|
|
41
|
-
let response = await limiter.schedule(jobOptions, pFetch, url, options)
|
|
42
|
-
|
|
43
|
-
// Verify response code
|
|
44
|
-
if (!response.ok) {
|
|
45
|
-
throw new Error(response.statusText)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Verify destination
|
|
49
|
-
if (!response.url.startsWith(baseURL)) {
|
|
50
|
-
throw new Error('Invalid destination URL')
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return response
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Default export
|
|
57
|
-
module.exports = exports = fetch
|
|
58
|
-
|
|
59
|
-
// Expose the limiter
|
|
60
|
-
exports.limiter = limiter
|