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
13 | all 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
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Export for Todoist
2 |
3 | A Node.js application to backup Todoist data as JSON or CSV.
4 |
5 |
6 |
7 | 
8 |
9 | ✨ **[Live demo](https://darekkay.com/todoist-export/)** ✨
10 |
11 |
12 |
13 | ## Development
14 |
15 | ### Quick Start
16 |
17 | 1. Create a [Todoist App](https://developer.todoist.com/appconsole.html). On localhost use `http://localhost:3000/todoist-export/` for both "App Service URL" and "OAuth Redirect URL".
18 |
19 | 2. Copy `src/config.js.example` to `src/config.js` and fill in the id and secret from the created app.
20 |
21 | 3. Install required packages (you can use `npm` instead of `yarn`):
22 |
23 | ```
24 | yarn install
25 | ```
26 |
27 | 4. Start server:
28 |
29 | ```
30 | yarn start
31 | ```
32 |
33 | Refer to the [API](https://developer.todoist.com/) for more information.
34 |
35 | ### Configure SSL
36 |
37 | Todoist redirects to a HTTPS version of your OAuth Redirect URL, even if a HTTP URL is defined. To retrieve your Todoist backup, you can change the URL from HTTPS to HTTP in the browser address bar after authorization. You can also start the app as HTTPS server, after creating a self-signed SSL certificate and defining your certificate data in `config.js`:
38 |
39 | ```
40 | ssl: {
41 | cert: fs.readFileSync('./ssl/fullchain.pem'),
42 | key: fs.readFileSync('./ssl/privkey.pem'),
43 | passphrase: 'ssl certificate passphrase'
44 | }
45 | ```
46 |
47 | ## License
48 |
49 | Copyright 2014-2021 Darek Kay
50 |
51 | This project and its contents are open source under the [MIT license](LICENSE).
52 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "todoist-export",
3 | "version": "1.3.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "todoist-export",
9 | "version": "1.3.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "@darekkay/logger": "1.1.2",
13 | "axios": "0.19.2",
14 | "body-parser": "1.19.0",
15 | "cookie-parser": "1.4.4",
16 | "express": "4.17.1",
17 | "json-2-csv": "3.5.5",
18 | "morgan": "1.9.1",
19 | "pug": "2.0.4",
20 | "simple-oauth2": "2.2.1"
21 | },
22 | "devDependencies": {
23 | "prettier": "2.8.0"
24 | }
25 | },
26 | "node_modules/@darekkay/logger": {
27 | "version": "1.1.2",
28 | "resolved": "https://registry.npmjs.org/@darekkay/logger/-/logger-1.1.2.tgz",
29 | "integrity": "sha512-rECZz6Wh7qdA3G5SSvb+TR1GtjfQCxqG/Q0F6WE1cylf4UdQx7Nae9wGGiNCtg9j0APMyLwzM26cWFD8UpyVuA==",
30 | "dependencies": {
31 | "log-symbols": "4.0.0",
32 | "loglevel": "1.7.1"
33 | },
34 | "engines": {
35 | "node": ">=12.0.0"
36 | }
37 | },
38 | "node_modules/@types/babel-types": {
39 | "version": "7.0.15",
40 | "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.15.tgz",
41 | "integrity": "sha512-JUgfZHUOMbtjopxiOQaaF+Uovk5wpDqpXR+XLWiOivCWSy1FccO30lvNNpCt8geFwq8VmGT2y9OMkOpA0g5O5g=="
42 | },
43 | "node_modules/@types/babylon": {
44 | "version": "6.16.9",
45 | "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.9.tgz",
46 | "integrity": "sha512-sEKyxMVEowhcr8WLfN0jJYe4gS4Z9KC2DGz0vqfC7+MXFbmvOF7jSjALC77thvAO2TLgFUPa9vDeOak+AcUrZA==",
47 | "dependencies": {
48 | "@types/babel-types": "*"
49 | }
50 | },
51 | "node_modules/accepts": {
52 | "version": "1.3.8",
53 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
54 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
55 | "dependencies": {
56 | "mime-types": "~2.1.34",
57 | "negotiator": "0.6.3"
58 | },
59 | "engines": {
60 | "node": ">= 0.6"
61 | }
62 | },
63 | "node_modules/acorn": {
64 | "version": "4.0.13",
65 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
66 | "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==",
67 | "bin": {
68 | "acorn": "bin/acorn"
69 | },
70 | "engines": {
71 | "node": ">=0.4.0"
72 | }
73 | },
74 | "node_modules/acorn-globals": {
75 | "version": "3.1.0",
76 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
77 | "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==",
78 | "dependencies": {
79 | "acorn": "^4.0.4"
80 | }
81 | },
82 | "node_modules/align-text": {
83 | "version": "0.1.4",
84 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
85 | "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==",
86 | "dependencies": {
87 | "kind-of": "^3.0.2",
88 | "longest": "^1.0.1",
89 | "repeat-string": "^1.5.2"
90 | },
91 | "engines": {
92 | "node": ">=0.10.0"
93 | }
94 | },
95 | "node_modules/ansi-styles": {
96 | "version": "4.3.0",
97 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
98 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
99 | "dependencies": {
100 | "color-convert": "^2.0.1"
101 | },
102 | "engines": {
103 | "node": ">=8"
104 | },
105 | "funding": {
106 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
107 | }
108 | },
109 | "node_modules/array-flatten": {
110 | "version": "1.1.1",
111 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
112 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
113 | },
114 | "node_modules/asap": {
115 | "version": "2.0.6",
116 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
117 | "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
118 | },
119 | "node_modules/axios": {
120 | "version": "0.19.2",
121 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
122 | "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
123 | "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410",
124 | "dependencies": {
125 | "follow-redirects": "1.5.10"
126 | }
127 | },
128 | "node_modules/babel-runtime": {
129 | "version": "6.26.0",
130 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
131 | "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
132 | "dependencies": {
133 | "core-js": "^2.4.0",
134 | "regenerator-runtime": "^0.11.0"
135 | }
136 | },
137 | "node_modules/babel-types": {
138 | "version": "6.26.0",
139 | "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
140 | "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==",
141 | "dependencies": {
142 | "babel-runtime": "^6.26.0",
143 | "esutils": "^2.0.2",
144 | "lodash": "^4.17.4",
145 | "to-fast-properties": "^1.0.3"
146 | }
147 | },
148 | "node_modules/babylon": {
149 | "version": "6.18.0",
150 | "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
151 | "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
152 | "bin": {
153 | "babylon": "bin/babylon.js"
154 | }
155 | },
156 | "node_modules/basic-auth": {
157 | "version": "2.0.1",
158 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
159 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
160 | "dependencies": {
161 | "safe-buffer": "5.1.2"
162 | },
163 | "engines": {
164 | "node": ">= 0.8"
165 | }
166 | },
167 | "node_modules/body-parser": {
168 | "version": "1.19.0",
169 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
170 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
171 | "dependencies": {
172 | "bytes": "3.1.0",
173 | "content-type": "~1.0.4",
174 | "debug": "2.6.9",
175 | "depd": "~1.1.2",
176 | "http-errors": "1.7.2",
177 | "iconv-lite": "0.4.24",
178 | "on-finished": "~2.3.0",
179 | "qs": "6.7.0",
180 | "raw-body": "2.4.0",
181 | "type-is": "~1.6.17"
182 | },
183 | "engines": {
184 | "node": ">= 0.8"
185 | }
186 | },
187 | "node_modules/boom": {
188 | "version": "7.3.0",
189 | "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz",
190 | "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==",
191 | "deprecated": "This module has moved and is now available at @hapi/boom. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
192 | "dependencies": {
193 | "hoek": "6.x.x"
194 | }
195 | },
196 | "node_modules/boom/node_modules/hoek": {
197 | "version": "6.1.3",
198 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
199 | "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==",
200 | "deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues."
201 | },
202 | "node_modules/bourne": {
203 | "version": "1.3.3",
204 | "resolved": "https://registry.npmjs.org/bourne/-/bourne-1.3.3.tgz",
205 | "integrity": "sha512-6K4uuAlRGcorC6aV2Y1rypeQ17grx4XKyVyG6NA963PwRfxyievy0CDXtiSBPKvIc7OTpcJRT86X3mU7j5Zp9A==",
206 | "deprecated": "This module has moved and is now available at @hapi/bourne. Please update your dependencies as this version is no longer maintained and may contain bugs and security issues.",
207 | "engines": {
208 | "node": ">=6.0.0"
209 | }
210 | },
211 | "node_modules/bytes": {
212 | "version": "3.1.0",
213 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
214 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
215 | "engines": {
216 | "node": ">= 0.8"
217 | }
218 | },
219 | "node_modules/call-bind": {
220 | "version": "1.0.7",
221 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
222 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
223 | "dependencies": {
224 | "es-define-property": "^1.0.0",
225 | "es-errors": "^1.3.0",
226 | "function-bind": "^1.1.2",
227 | "get-intrinsic": "^1.2.4",
228 | "set-function-length": "^1.2.1"
229 | },
230 | "engines": {
231 | "node": ">= 0.4"
232 | },
233 | "funding": {
234 | "url": "https://github.com/sponsors/ljharb"
235 | }
236 | },
237 | "node_modules/camelcase": {
238 | "version": "1.2.1",
239 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
240 | "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==",
241 | "engines": {
242 | "node": ">=0.10.0"
243 | }
244 | },
245 | "node_modules/center-align": {
246 | "version": "0.1.3",
247 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
248 | "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==",
249 | "dependencies": {
250 | "align-text": "^0.1.3",
251 | "lazy-cache": "^1.0.3"
252 | },
253 | "engines": {
254 | "node": ">=0.10.0"
255 | }
256 | },
257 | "node_modules/chalk": {
258 | "version": "4.1.2",
259 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
260 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
261 | "dependencies": {
262 | "ansi-styles": "^4.1.0",
263 | "supports-color": "^7.1.0"
264 | },
265 | "engines": {
266 | "node": ">=10"
267 | },
268 | "funding": {
269 | "url": "https://github.com/chalk/chalk?sponsor=1"
270 | }
271 | },
272 | "node_modules/character-parser": {
273 | "version": "2.2.0",
274 | "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
275 | "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==",
276 | "dependencies": {
277 | "is-regex": "^1.0.3"
278 | }
279 | },
280 | "node_modules/clean-css": {
281 | "version": "4.2.4",
282 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
283 | "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
284 | "dependencies": {
285 | "source-map": "~0.6.0"
286 | },
287 | "engines": {
288 | "node": ">= 4.0"
289 | }
290 | },
291 | "node_modules/cliui": {
292 | "version": "2.1.0",
293 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
294 | "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==",
295 | "dependencies": {
296 | "center-align": "^0.1.1",
297 | "right-align": "^0.1.1",
298 | "wordwrap": "0.0.2"
299 | }
300 | },
301 | "node_modules/color-convert": {
302 | "version": "2.0.1",
303 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
304 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
305 | "dependencies": {
306 | "color-name": "~1.1.4"
307 | },
308 | "engines": {
309 | "node": ">=7.0.0"
310 | }
311 | },
312 | "node_modules/color-name": {
313 | "version": "1.1.4",
314 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
315 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
316 | },
317 | "node_modules/constantinople": {
318 | "version": "3.1.2",
319 | "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz",
320 | "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==",
321 | "dependencies": {
322 | "@types/babel-types": "^7.0.0",
323 | "@types/babylon": "^6.16.2",
324 | "babel-types": "^6.26.0",
325 | "babylon": "^6.18.0"
326 | }
327 | },
328 | "node_modules/content-disposition": {
329 | "version": "0.5.3",
330 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
331 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
332 | "dependencies": {
333 | "safe-buffer": "5.1.2"
334 | },
335 | "engines": {
336 | "node": ">= 0.6"
337 | }
338 | },
339 | "node_modules/content-type": {
340 | "version": "1.0.5",
341 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
342 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
343 | "engines": {
344 | "node": ">= 0.6"
345 | }
346 | },
347 | "node_modules/cookie": {
348 | "version": "0.3.1",
349 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
350 | "integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw==",
351 | "engines": {
352 | "node": ">= 0.6"
353 | }
354 | },
355 | "node_modules/cookie-parser": {
356 | "version": "1.4.4",
357 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.4.tgz",
358 | "integrity": "sha512-lo13tqF3JEtFO7FyA49CqbhaFkskRJ0u/UAiINgrIXeRCY41c88/zxtrECl8AKH3B0hj9q10+h3Kt8I7KlW4tw==",
359 | "dependencies": {
360 | "cookie": "0.3.1",
361 | "cookie-signature": "1.0.6"
362 | },
363 | "engines": {
364 | "node": ">= 0.8.0"
365 | }
366 | },
367 | "node_modules/cookie-signature": {
368 | "version": "1.0.6",
369 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
370 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
371 | },
372 | "node_modules/core-js": {
373 | "version": "2.6.12",
374 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
375 | "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
376 | "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
377 | "hasInstallScript": true
378 | },
379 | "node_modules/date-fns": {
380 | "version": "1.30.1",
381 | "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
382 | "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw=="
383 | },
384 | "node_modules/debug": {
385 | "version": "2.6.9",
386 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
387 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
388 | "dependencies": {
389 | "ms": "2.0.0"
390 | }
391 | },
392 | "node_modules/decamelize": {
393 | "version": "1.2.0",
394 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
395 | "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
396 | "engines": {
397 | "node": ">=0.10.0"
398 | }
399 | },
400 | "node_modules/deeks": {
401 | "version": "2.2.1",
402 | "resolved": "https://registry.npmjs.org/deeks/-/deeks-2.2.1.tgz",
403 | "integrity": "sha512-D2Qu3Fv5zBtBzXjXIUgWPRYn30d/IG6SCPOKIz42+LVTwhPeRI5+DAxdzap0vI2zYheiErIpVLwaUQBoA/iENw==",
404 | "dependencies": {
405 | "underscore": "1.9.1"
406 | },
407 | "engines": {
408 | "node": ">=6.0"
409 | }
410 | },
411 | "node_modules/define-data-property": {
412 | "version": "1.1.4",
413 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
414 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
415 | "dependencies": {
416 | "es-define-property": "^1.0.0",
417 | "es-errors": "^1.3.0",
418 | "gopd": "^1.0.1"
419 | },
420 | "engines": {
421 | "node": ">= 0.4"
422 | },
423 | "funding": {
424 | "url": "https://github.com/sponsors/ljharb"
425 | }
426 | },
427 | "node_modules/depd": {
428 | "version": "1.1.2",
429 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
430 | "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
431 | "engines": {
432 | "node": ">= 0.6"
433 | }
434 | },
435 | "node_modules/destroy": {
436 | "version": "1.0.4",
437 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
438 | "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg=="
439 | },
440 | "node_modules/doc-path": {
441 | "version": "2.0.1",
442 | "resolved": "https://registry.npmjs.org/doc-path/-/doc-path-2.0.1.tgz",
443 | "integrity": "sha512-/CCG157H//3l513omROUzaREChY/OYpxqYXvQcv7gsrwGfjVOh5d/1gJigHJ6iTnO77pA8rMLZ63CgEPEM6+9Q==",
444 | "deprecated": "critical issue fixed in 2.3.0",
445 | "engines": {
446 | "node": ">=6.0"
447 | }
448 | },
449 | "node_modules/doctypes": {
450 | "version": "1.1.0",
451 | "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
452 | "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ=="
453 | },
454 | "node_modules/ee-first": {
455 | "version": "1.1.1",
456 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
457 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
458 | },
459 | "node_modules/encodeurl": {
460 | "version": "1.0.2",
461 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
462 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
463 | "engines": {
464 | "node": ">= 0.8"
465 | }
466 | },
467 | "node_modules/es-define-property": {
468 | "version": "1.0.0",
469 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
470 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
471 | "dependencies": {
472 | "get-intrinsic": "^1.2.4"
473 | },
474 | "engines": {
475 | "node": ">= 0.4"
476 | }
477 | },
478 | "node_modules/es-errors": {
479 | "version": "1.3.0",
480 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
481 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
482 | "engines": {
483 | "node": ">= 0.4"
484 | }
485 | },
486 | "node_modules/escape-html": {
487 | "version": "1.0.3",
488 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
489 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
490 | },
491 | "node_modules/esutils": {
492 | "version": "2.0.3",
493 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
494 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
495 | "engines": {
496 | "node": ">=0.10.0"
497 | }
498 | },
499 | "node_modules/etag": {
500 | "version": "1.8.1",
501 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
502 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
503 | "engines": {
504 | "node": ">= 0.6"
505 | }
506 | },
507 | "node_modules/express": {
508 | "version": "4.17.1",
509 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
510 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
511 | "dependencies": {
512 | "accepts": "~1.3.7",
513 | "array-flatten": "1.1.1",
514 | "body-parser": "1.19.0",
515 | "content-disposition": "0.5.3",
516 | "content-type": "~1.0.4",
517 | "cookie": "0.4.0",
518 | "cookie-signature": "1.0.6",
519 | "debug": "2.6.9",
520 | "depd": "~1.1.2",
521 | "encodeurl": "~1.0.2",
522 | "escape-html": "~1.0.3",
523 | "etag": "~1.8.1",
524 | "finalhandler": "~1.1.2",
525 | "fresh": "0.5.2",
526 | "merge-descriptors": "1.0.1",
527 | "methods": "~1.1.2",
528 | "on-finished": "~2.3.0",
529 | "parseurl": "~1.3.3",
530 | "path-to-regexp": "0.1.7",
531 | "proxy-addr": "~2.0.5",
532 | "qs": "6.7.0",
533 | "range-parser": "~1.2.1",
534 | "safe-buffer": "5.1.2",
535 | "send": "0.17.1",
536 | "serve-static": "1.14.1",
537 | "setprototypeof": "1.1.1",
538 | "statuses": "~1.5.0",
539 | "type-is": "~1.6.18",
540 | "utils-merge": "1.0.1",
541 | "vary": "~1.1.2"
542 | },
543 | "engines": {
544 | "node": ">= 0.10.0"
545 | }
546 | },
547 | "node_modules/express/node_modules/cookie": {
548 | "version": "0.4.0",
549 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
550 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
551 | "engines": {
552 | "node": ">= 0.6"
553 | }
554 | },
555 | "node_modules/finalhandler": {
556 | "version": "1.1.2",
557 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
558 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
559 | "dependencies": {
560 | "debug": "2.6.9",
561 | "encodeurl": "~1.0.2",
562 | "escape-html": "~1.0.3",
563 | "on-finished": "~2.3.0",
564 | "parseurl": "~1.3.3",
565 | "statuses": "~1.5.0",
566 | "unpipe": "~1.0.0"
567 | },
568 | "engines": {
569 | "node": ">= 0.8"
570 | }
571 | },
572 | "node_modules/follow-redirects": {
573 | "version": "1.5.10",
574 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
575 | "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
576 | "dependencies": {
577 | "debug": "=3.1.0"
578 | },
579 | "engines": {
580 | "node": ">=4.0"
581 | }
582 | },
583 | "node_modules/follow-redirects/node_modules/debug": {
584 | "version": "3.1.0",
585 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
586 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
587 | "dependencies": {
588 | "ms": "2.0.0"
589 | }
590 | },
591 | "node_modules/forwarded": {
592 | "version": "0.2.0",
593 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
594 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
595 | "engines": {
596 | "node": ">= 0.6"
597 | }
598 | },
599 | "node_modules/fresh": {
600 | "version": "0.5.2",
601 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
602 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
603 | "engines": {
604 | "node": ">= 0.6"
605 | }
606 | },
607 | "node_modules/function-bind": {
608 | "version": "1.1.2",
609 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
610 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
611 | "funding": {
612 | "url": "https://github.com/sponsors/ljharb"
613 | }
614 | },
615 | "node_modules/get-intrinsic": {
616 | "version": "1.2.4",
617 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
618 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
619 | "dependencies": {
620 | "es-errors": "^1.3.0",
621 | "function-bind": "^1.1.2",
622 | "has-proto": "^1.0.1",
623 | "has-symbols": "^1.0.3",
624 | "hasown": "^2.0.0"
625 | },
626 | "engines": {
627 | "node": ">= 0.4"
628 | },
629 | "funding": {
630 | "url": "https://github.com/sponsors/ljharb"
631 | }
632 | },
633 | "node_modules/gopd": {
634 | "version": "1.0.1",
635 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
636 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
637 | "dependencies": {
638 | "get-intrinsic": "^1.1.3"
639 | },
640 | "funding": {
641 | "url": "https://github.com/sponsors/ljharb"
642 | }
643 | },
644 | "node_modules/has-flag": {
645 | "version": "4.0.0",
646 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
647 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
648 | "engines": {
649 | "node": ">=8"
650 | }
651 | },
652 | "node_modules/has-property-descriptors": {
653 | "version": "1.0.2",
654 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
655 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
656 | "dependencies": {
657 | "es-define-property": "^1.0.0"
658 | },
659 | "funding": {
660 | "url": "https://github.com/sponsors/ljharb"
661 | }
662 | },
663 | "node_modules/has-proto": {
664 | "version": "1.0.3",
665 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
666 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
667 | "engines": {
668 | "node": ">= 0.4"
669 | },
670 | "funding": {
671 | "url": "https://github.com/sponsors/ljharb"
672 | }
673 | },
674 | "node_modules/has-symbols": {
675 | "version": "1.0.3",
676 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
677 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
678 | "engines": {
679 | "node": ">= 0.4"
680 | },
681 | "funding": {
682 | "url": "https://github.com/sponsors/ljharb"
683 | }
684 | },
685 | "node_modules/has-tostringtag": {
686 | "version": "1.0.2",
687 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
688 | "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
689 | "dependencies": {
690 | "has-symbols": "^1.0.3"
691 | },
692 | "engines": {
693 | "node": ">= 0.4"
694 | },
695 | "funding": {
696 | "url": "https://github.com/sponsors/ljharb"
697 | }
698 | },
699 | "node_modules/hasown": {
700 | "version": "2.0.2",
701 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
702 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
703 | "dependencies": {
704 | "function-bind": "^1.1.2"
705 | },
706 | "engines": {
707 | "node": ">= 0.4"
708 | }
709 | },
710 | "node_modules/hoek": {
711 | "version": "5.0.4",
712 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.4.tgz",
713 | "integrity": "sha512-Alr4ZQgoMlnere5FZJsIyfIjORBqZll5POhDsF4q64dPuJR6rNxXdDxtHSQq8OXRurhmx+PWYEE8bXRROY8h0w==",
714 | "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).",
715 | "engines": {
716 | "node": ">=8.9.0"
717 | }
718 | },
719 | "node_modules/http-errors": {
720 | "version": "1.7.2",
721 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
722 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
723 | "dependencies": {
724 | "depd": "~1.1.2",
725 | "inherits": "2.0.3",
726 | "setprototypeof": "1.1.1",
727 | "statuses": ">= 1.5.0 < 2",
728 | "toidentifier": "1.0.0"
729 | },
730 | "engines": {
731 | "node": ">= 0.6"
732 | }
733 | },
734 | "node_modules/iconv-lite": {
735 | "version": "0.4.24",
736 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
737 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
738 | "dependencies": {
739 | "safer-buffer": ">= 2.1.2 < 3"
740 | },
741 | "engines": {
742 | "node": ">=0.10.0"
743 | }
744 | },
745 | "node_modules/inherits": {
746 | "version": "2.0.3",
747 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
748 | "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="
749 | },
750 | "node_modules/ipaddr.js": {
751 | "version": "1.9.1",
752 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
753 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
754 | "engines": {
755 | "node": ">= 0.10"
756 | }
757 | },
758 | "node_modules/is-buffer": {
759 | "version": "1.1.6",
760 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
761 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
762 | },
763 | "node_modules/is-core-module": {
764 | "version": "2.13.1",
765 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
766 | "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
767 | "dependencies": {
768 | "hasown": "^2.0.0"
769 | },
770 | "funding": {
771 | "url": "https://github.com/sponsors/ljharb"
772 | }
773 | },
774 | "node_modules/is-expression": {
775 | "version": "3.0.0",
776 | "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz",
777 | "integrity": "sha512-vyMeQMq+AiH5uUnoBfMTwf18tO3bM6k1QXBE9D6ueAAquEfCZe3AJPtud9g6qS0+4X8xA7ndpZiDyeb2l2qOBw==",
778 | "dependencies": {
779 | "acorn": "~4.0.2",
780 | "object-assign": "^4.0.1"
781 | }
782 | },
783 | "node_modules/is-promise": {
784 | "version": "2.2.2",
785 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
786 | "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
787 | },
788 | "node_modules/is-regex": {
789 | "version": "1.1.4",
790 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
791 | "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
792 | "dependencies": {
793 | "call-bind": "^1.0.2",
794 | "has-tostringtag": "^1.0.0"
795 | },
796 | "engines": {
797 | "node": ">= 0.4"
798 | },
799 | "funding": {
800 | "url": "https://github.com/sponsors/ljharb"
801 | }
802 | },
803 | "node_modules/isemail": {
804 | "version": "3.2.0",
805 | "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz",
806 | "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==",
807 | "dependencies": {
808 | "punycode": "2.x.x"
809 | },
810 | "engines": {
811 | "node": ">=4.0.0"
812 | }
813 | },
814 | "node_modules/joi": {
815 | "version": "13.7.0",
816 | "resolved": "https://registry.npmjs.org/joi/-/joi-13.7.0.tgz",
817 | "integrity": "sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q==",
818 | "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).",
819 | "dependencies": {
820 | "hoek": "5.x.x",
821 | "isemail": "3.x.x",
822 | "topo": "3.x.x"
823 | },
824 | "engines": {
825 | "node": ">=8.9.0"
826 | }
827 | },
828 | "node_modules/js-stringify": {
829 | "version": "1.0.2",
830 | "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
831 | "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g=="
832 | },
833 | "node_modules/json-2-csv": {
834 | "version": "3.5.5",
835 | "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-3.5.5.tgz",
836 | "integrity": "sha512-7BlKbejl42pmzoamfH+OFsNkVtPtWUuBJCCh/rhjf32fPTol5UwQGp051cf+qFfDHu0iQssBEzwRIDoTcD3MAw==",
837 | "dependencies": {
838 | "deeks": "2.2.1",
839 | "doc-path": "2.0.1",
840 | "underscore": "1.9.1"
841 | },
842 | "bin": {
843 | "csv2json": "bin/csv2json.js",
844 | "json2csv": "bin/json2csv.js"
845 | },
846 | "engines": {
847 | "node": ">= 6"
848 | }
849 | },
850 | "node_modules/jstransformer": {
851 | "version": "1.0.0",
852 | "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
853 | "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==",
854 | "dependencies": {
855 | "is-promise": "^2.0.0",
856 | "promise": "^7.0.1"
857 | }
858 | },
859 | "node_modules/kind-of": {
860 | "version": "3.2.2",
861 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
862 | "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
863 | "dependencies": {
864 | "is-buffer": "^1.1.5"
865 | },
866 | "engines": {
867 | "node": ">=0.10.0"
868 | }
869 | },
870 | "node_modules/lazy-cache": {
871 | "version": "1.0.4",
872 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
873 | "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==",
874 | "engines": {
875 | "node": ">=0.10.0"
876 | }
877 | },
878 | "node_modules/lodash": {
879 | "version": "4.17.21",
880 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
881 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
882 | },
883 | "node_modules/log-symbols": {
884 | "version": "4.0.0",
885 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
886 | "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
887 | "dependencies": {
888 | "chalk": "^4.0.0"
889 | },
890 | "engines": {
891 | "node": ">=10"
892 | }
893 | },
894 | "node_modules/loglevel": {
895 | "version": "1.7.1",
896 | "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
897 | "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==",
898 | "engines": {
899 | "node": ">= 0.6.0"
900 | },
901 | "funding": {
902 | "type": "tidelift",
903 | "url": "https://tidelift.com/funding/github/npm/loglevel"
904 | }
905 | },
906 | "node_modules/longest": {
907 | "version": "1.0.1",
908 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
909 | "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==",
910 | "engines": {
911 | "node": ">=0.10.0"
912 | }
913 | },
914 | "node_modules/media-typer": {
915 | "version": "0.3.0",
916 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
917 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
918 | "engines": {
919 | "node": ">= 0.6"
920 | }
921 | },
922 | "node_modules/merge-descriptors": {
923 | "version": "1.0.1",
924 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
925 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
926 | },
927 | "node_modules/methods": {
928 | "version": "1.1.2",
929 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
930 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
931 | "engines": {
932 | "node": ">= 0.6"
933 | }
934 | },
935 | "node_modules/mime": {
936 | "version": "1.6.0",
937 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
938 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
939 | "bin": {
940 | "mime": "cli.js"
941 | },
942 | "engines": {
943 | "node": ">=4"
944 | }
945 | },
946 | "node_modules/mime-db": {
947 | "version": "1.52.0",
948 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
949 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
950 | "engines": {
951 | "node": ">= 0.6"
952 | }
953 | },
954 | "node_modules/mime-types": {
955 | "version": "2.1.35",
956 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
957 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
958 | "dependencies": {
959 | "mime-db": "1.52.0"
960 | },
961 | "engines": {
962 | "node": ">= 0.6"
963 | }
964 | },
965 | "node_modules/morgan": {
966 | "version": "1.9.1",
967 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
968 | "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
969 | "dependencies": {
970 | "basic-auth": "~2.0.0",
971 | "debug": "2.6.9",
972 | "depd": "~1.1.2",
973 | "on-finished": "~2.3.0",
974 | "on-headers": "~1.0.1"
975 | },
976 | "engines": {
977 | "node": ">= 0.8.0"
978 | }
979 | },
980 | "node_modules/ms": {
981 | "version": "2.0.0",
982 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
983 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
984 | },
985 | "node_modules/negotiator": {
986 | "version": "0.6.3",
987 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
988 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
989 | "engines": {
990 | "node": ">= 0.6"
991 | }
992 | },
993 | "node_modules/object-assign": {
994 | "version": "4.1.1",
995 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
996 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
997 | "engines": {
998 | "node": ">=0.10.0"
999 | }
1000 | },
1001 | "node_modules/on-finished": {
1002 | "version": "2.3.0",
1003 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
1004 | "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
1005 | "dependencies": {
1006 | "ee-first": "1.1.1"
1007 | },
1008 | "engines": {
1009 | "node": ">= 0.8"
1010 | }
1011 | },
1012 | "node_modules/on-headers": {
1013 | "version": "1.0.2",
1014 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
1015 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
1016 | "engines": {
1017 | "node": ">= 0.8"
1018 | }
1019 | },
1020 | "node_modules/parseurl": {
1021 | "version": "1.3.3",
1022 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1023 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
1024 | "engines": {
1025 | "node": ">= 0.8"
1026 | }
1027 | },
1028 | "node_modules/path-parse": {
1029 | "version": "1.0.7",
1030 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
1031 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
1032 | },
1033 | "node_modules/path-to-regexp": {
1034 | "version": "0.1.7",
1035 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
1036 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
1037 | },
1038 | "node_modules/prettier": {
1039 | "version": "2.8.0",
1040 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz",
1041 | "integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==",
1042 | "dev": true,
1043 | "bin": {
1044 | "prettier": "bin-prettier.js"
1045 | },
1046 | "engines": {
1047 | "node": ">=10.13.0"
1048 | },
1049 | "funding": {
1050 | "url": "https://github.com/prettier/prettier?sponsor=1"
1051 | }
1052 | },
1053 | "node_modules/promise": {
1054 | "version": "7.3.1",
1055 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
1056 | "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
1057 | "dependencies": {
1058 | "asap": "~2.0.3"
1059 | }
1060 | },
1061 | "node_modules/proxy-addr": {
1062 | "version": "2.0.7",
1063 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
1064 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
1065 | "dependencies": {
1066 | "forwarded": "0.2.0",
1067 | "ipaddr.js": "1.9.1"
1068 | },
1069 | "engines": {
1070 | "node": ">= 0.10"
1071 | }
1072 | },
1073 | "node_modules/pug": {
1074 | "version": "2.0.4",
1075 | "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.4.tgz",
1076 | "integrity": "sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw==",
1077 | "dependencies": {
1078 | "pug-code-gen": "^2.0.2",
1079 | "pug-filters": "^3.1.1",
1080 | "pug-lexer": "^4.1.0",
1081 | "pug-linker": "^3.0.6",
1082 | "pug-load": "^2.0.12",
1083 | "pug-parser": "^5.0.1",
1084 | "pug-runtime": "^2.0.5",
1085 | "pug-strip-comments": "^1.0.4"
1086 | }
1087 | },
1088 | "node_modules/pug-attrs": {
1089 | "version": "2.0.4",
1090 | "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz",
1091 | "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==",
1092 | "dependencies": {
1093 | "constantinople": "^3.0.1",
1094 | "js-stringify": "^1.0.1",
1095 | "pug-runtime": "^2.0.5"
1096 | }
1097 | },
1098 | "node_modules/pug-code-gen": {
1099 | "version": "2.0.3",
1100 | "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.3.tgz",
1101 | "integrity": "sha512-r9sezXdDuZJfW9J91TN/2LFbiqDhmltTFmGpHTsGdrNGp3p4SxAjjXEfnuK2e4ywYsRIVP0NeLbSAMHUcaX1EA==",
1102 | "dependencies": {
1103 | "constantinople": "^3.1.2",
1104 | "doctypes": "^1.1.0",
1105 | "js-stringify": "^1.0.1",
1106 | "pug-attrs": "^2.0.4",
1107 | "pug-error": "^1.3.3",
1108 | "pug-runtime": "^2.0.5",
1109 | "void-elements": "^2.0.1",
1110 | "with": "^5.0.0"
1111 | }
1112 | },
1113 | "node_modules/pug-error": {
1114 | "version": "1.3.3",
1115 | "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz",
1116 | "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ=="
1117 | },
1118 | "node_modules/pug-filters": {
1119 | "version": "3.1.1",
1120 | "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.1.tgz",
1121 | "integrity": "sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg==",
1122 | "dependencies": {
1123 | "clean-css": "^4.1.11",
1124 | "constantinople": "^3.0.1",
1125 | "jstransformer": "1.0.0",
1126 | "pug-error": "^1.3.3",
1127 | "pug-walk": "^1.1.8",
1128 | "resolve": "^1.1.6",
1129 | "uglify-js": "^2.6.1"
1130 | }
1131 | },
1132 | "node_modules/pug-lexer": {
1133 | "version": "4.1.0",
1134 | "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.1.0.tgz",
1135 | "integrity": "sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA==",
1136 | "dependencies": {
1137 | "character-parser": "^2.1.1",
1138 | "is-expression": "^3.0.0",
1139 | "pug-error": "^1.3.3"
1140 | }
1141 | },
1142 | "node_modules/pug-linker": {
1143 | "version": "3.0.6",
1144 | "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz",
1145 | "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==",
1146 | "dependencies": {
1147 | "pug-error": "^1.3.3",
1148 | "pug-walk": "^1.1.8"
1149 | }
1150 | },
1151 | "node_modules/pug-load": {
1152 | "version": "2.0.12",
1153 | "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz",
1154 | "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==",
1155 | "dependencies": {
1156 | "object-assign": "^4.1.0",
1157 | "pug-walk": "^1.1.8"
1158 | }
1159 | },
1160 | "node_modules/pug-parser": {
1161 | "version": "5.0.1",
1162 | "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.1.tgz",
1163 | "integrity": "sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA==",
1164 | "dependencies": {
1165 | "pug-error": "^1.3.3",
1166 | "token-stream": "0.0.1"
1167 | }
1168 | },
1169 | "node_modules/pug-runtime": {
1170 | "version": "2.0.5",
1171 | "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz",
1172 | "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw=="
1173 | },
1174 | "node_modules/pug-strip-comments": {
1175 | "version": "1.0.4",
1176 | "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz",
1177 | "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==",
1178 | "dependencies": {
1179 | "pug-error": "^1.3.3"
1180 | }
1181 | },
1182 | "node_modules/pug-walk": {
1183 | "version": "1.1.8",
1184 | "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz",
1185 | "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA=="
1186 | },
1187 | "node_modules/punycode": {
1188 | "version": "2.3.1",
1189 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
1190 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
1191 | "engines": {
1192 | "node": ">=6"
1193 | }
1194 | },
1195 | "node_modules/qs": {
1196 | "version": "6.7.0",
1197 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
1198 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
1199 | "engines": {
1200 | "node": ">=0.6"
1201 | }
1202 | },
1203 | "node_modules/range-parser": {
1204 | "version": "1.2.1",
1205 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1206 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
1207 | "engines": {
1208 | "node": ">= 0.6"
1209 | }
1210 | },
1211 | "node_modules/raw-body": {
1212 | "version": "2.4.0",
1213 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
1214 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
1215 | "dependencies": {
1216 | "bytes": "3.1.0",
1217 | "http-errors": "1.7.2",
1218 | "iconv-lite": "0.4.24",
1219 | "unpipe": "1.0.0"
1220 | },
1221 | "engines": {
1222 | "node": ">= 0.8"
1223 | }
1224 | },
1225 | "node_modules/regenerator-runtime": {
1226 | "version": "0.11.1",
1227 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
1228 | "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
1229 | },
1230 | "node_modules/repeat-string": {
1231 | "version": "1.6.1",
1232 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
1233 | "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
1234 | "engines": {
1235 | "node": ">=0.10"
1236 | }
1237 | },
1238 | "node_modules/resolve": {
1239 | "version": "1.22.8",
1240 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
1241 | "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
1242 | "dependencies": {
1243 | "is-core-module": "^2.13.0",
1244 | "path-parse": "^1.0.7",
1245 | "supports-preserve-symlinks-flag": "^1.0.0"
1246 | },
1247 | "bin": {
1248 | "resolve": "bin/resolve"
1249 | },
1250 | "funding": {
1251 | "url": "https://github.com/sponsors/ljharb"
1252 | }
1253 | },
1254 | "node_modules/right-align": {
1255 | "version": "0.1.3",
1256 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
1257 | "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==",
1258 | "dependencies": {
1259 | "align-text": "^0.1.1"
1260 | },
1261 | "engines": {
1262 | "node": ">=0.10.0"
1263 | }
1264 | },
1265 | "node_modules/safe-buffer": {
1266 | "version": "5.1.2",
1267 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
1268 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
1269 | },
1270 | "node_modules/safer-buffer": {
1271 | "version": "2.1.2",
1272 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1273 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1274 | },
1275 | "node_modules/send": {
1276 | "version": "0.17.1",
1277 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
1278 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
1279 | "dependencies": {
1280 | "debug": "2.6.9",
1281 | "depd": "~1.1.2",
1282 | "destroy": "~1.0.4",
1283 | "encodeurl": "~1.0.2",
1284 | "escape-html": "~1.0.3",
1285 | "etag": "~1.8.1",
1286 | "fresh": "0.5.2",
1287 | "http-errors": "~1.7.2",
1288 | "mime": "1.6.0",
1289 | "ms": "2.1.1",
1290 | "on-finished": "~2.3.0",
1291 | "range-parser": "~1.2.1",
1292 | "statuses": "~1.5.0"
1293 | },
1294 | "engines": {
1295 | "node": ">= 0.8.0"
1296 | }
1297 | },
1298 | "node_modules/send/node_modules/ms": {
1299 | "version": "2.1.1",
1300 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
1301 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
1302 | },
1303 | "node_modules/serve-static": {
1304 | "version": "1.14.1",
1305 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
1306 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
1307 | "dependencies": {
1308 | "encodeurl": "~1.0.2",
1309 | "escape-html": "~1.0.3",
1310 | "parseurl": "~1.3.3",
1311 | "send": "0.17.1"
1312 | },
1313 | "engines": {
1314 | "node": ">= 0.8.0"
1315 | }
1316 | },
1317 | "node_modules/set-function-length": {
1318 | "version": "1.2.2",
1319 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
1320 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
1321 | "dependencies": {
1322 | "define-data-property": "^1.1.4",
1323 | "es-errors": "^1.3.0",
1324 | "function-bind": "^1.1.2",
1325 | "get-intrinsic": "^1.2.4",
1326 | "gopd": "^1.0.1",
1327 | "has-property-descriptors": "^1.0.2"
1328 | },
1329 | "engines": {
1330 | "node": ">= 0.4"
1331 | }
1332 | },
1333 | "node_modules/setprototypeof": {
1334 | "version": "1.1.1",
1335 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
1336 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
1337 | },
1338 | "node_modules/simple-oauth2": {
1339 | "version": "2.2.1",
1340 | "resolved": "https://registry.npmjs.org/simple-oauth2/-/simple-oauth2-2.2.1.tgz",
1341 | "integrity": "sha512-Ujn8tU9Nl4CLy5L6ksSL+kJ6eI61NyhLCUZPris6aHMGxnfAnqrYdmTN16VSEl9m5W9WPj1sXJvhoi6kihsaSA==",
1342 | "deprecated": "simple-oauth2 v2 is no longer supported. Please upgrade to v3 for further support",
1343 | "dependencies": {
1344 | "date-fns": "^1.3.0",
1345 | "debug": "^3.1.0",
1346 | "joi": "^13.0.2",
1347 | "wreck": "^14.0.2"
1348 | }
1349 | },
1350 | "node_modules/simple-oauth2/node_modules/debug": {
1351 | "version": "3.2.7",
1352 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
1353 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
1354 | "dependencies": {
1355 | "ms": "^2.1.1"
1356 | }
1357 | },
1358 | "node_modules/simple-oauth2/node_modules/ms": {
1359 | "version": "2.1.3",
1360 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1361 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1362 | },
1363 | "node_modules/source-map": {
1364 | "version": "0.6.1",
1365 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
1366 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
1367 | "engines": {
1368 | "node": ">=0.10.0"
1369 | }
1370 | },
1371 | "node_modules/statuses": {
1372 | "version": "1.5.0",
1373 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
1374 | "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
1375 | "engines": {
1376 | "node": ">= 0.6"
1377 | }
1378 | },
1379 | "node_modules/supports-color": {
1380 | "version": "7.2.0",
1381 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1382 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1383 | "dependencies": {
1384 | "has-flag": "^4.0.0"
1385 | },
1386 | "engines": {
1387 | "node": ">=8"
1388 | }
1389 | },
1390 | "node_modules/supports-preserve-symlinks-flag": {
1391 | "version": "1.0.0",
1392 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1393 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1394 | "engines": {
1395 | "node": ">= 0.4"
1396 | },
1397 | "funding": {
1398 | "url": "https://github.com/sponsors/ljharb"
1399 | }
1400 | },
1401 | "node_modules/to-fast-properties": {
1402 | "version": "1.0.3",
1403 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
1404 | "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==",
1405 | "engines": {
1406 | "node": ">=0.10.0"
1407 | }
1408 | },
1409 | "node_modules/toidentifier": {
1410 | "version": "1.0.0",
1411 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
1412 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
1413 | "engines": {
1414 | "node": ">=0.6"
1415 | }
1416 | },
1417 | "node_modules/token-stream": {
1418 | "version": "0.0.1",
1419 | "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz",
1420 | "integrity": "sha512-nfjOAu/zAWmX9tgwi5NRp7O7zTDUD1miHiB40klUnAh9qnL1iXdgzcz/i5dMaL5jahcBAaSfmNOBBJBLJW8TEg=="
1421 | },
1422 | "node_modules/topo": {
1423 | "version": "3.0.3",
1424 | "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz",
1425 | "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==",
1426 | "deprecated": "This module has moved and is now available at @hapi/topo. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
1427 | "dependencies": {
1428 | "hoek": "6.x.x"
1429 | }
1430 | },
1431 | "node_modules/topo/node_modules/hoek": {
1432 | "version": "6.1.3",
1433 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
1434 | "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==",
1435 | "deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues."
1436 | },
1437 | "node_modules/type-is": {
1438 | "version": "1.6.18",
1439 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1440 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1441 | "dependencies": {
1442 | "media-typer": "0.3.0",
1443 | "mime-types": "~2.1.24"
1444 | },
1445 | "engines": {
1446 | "node": ">= 0.6"
1447 | }
1448 | },
1449 | "node_modules/uglify-js": {
1450 | "version": "2.8.29",
1451 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
1452 | "integrity": "sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==",
1453 | "dependencies": {
1454 | "source-map": "~0.5.1",
1455 | "yargs": "~3.10.0"
1456 | },
1457 | "bin": {
1458 | "uglifyjs": "bin/uglifyjs"
1459 | },
1460 | "engines": {
1461 | "node": ">=0.8.0"
1462 | },
1463 | "optionalDependencies": {
1464 | "uglify-to-browserify": "~1.0.0"
1465 | }
1466 | },
1467 | "node_modules/uglify-js/node_modules/source-map": {
1468 | "version": "0.5.7",
1469 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
1470 | "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
1471 | "engines": {
1472 | "node": ">=0.10.0"
1473 | }
1474 | },
1475 | "node_modules/uglify-to-browserify": {
1476 | "version": "1.0.2",
1477 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
1478 | "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==",
1479 | "optional": true
1480 | },
1481 | "node_modules/underscore": {
1482 | "version": "1.9.1",
1483 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
1484 | "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
1485 | },
1486 | "node_modules/unpipe": {
1487 | "version": "1.0.0",
1488 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1489 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
1490 | "engines": {
1491 | "node": ">= 0.8"
1492 | }
1493 | },
1494 | "node_modules/utils-merge": {
1495 | "version": "1.0.1",
1496 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1497 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
1498 | "engines": {
1499 | "node": ">= 0.4.0"
1500 | }
1501 | },
1502 | "node_modules/vary": {
1503 | "version": "1.1.2",
1504 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1505 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
1506 | "engines": {
1507 | "node": ">= 0.8"
1508 | }
1509 | },
1510 | "node_modules/void-elements": {
1511 | "version": "2.0.1",
1512 | "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
1513 | "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==",
1514 | "engines": {
1515 | "node": ">=0.10.0"
1516 | }
1517 | },
1518 | "node_modules/window-size": {
1519 | "version": "0.1.0",
1520 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
1521 | "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==",
1522 | "engines": {
1523 | "node": ">= 0.8.0"
1524 | }
1525 | },
1526 | "node_modules/with": {
1527 | "version": "5.1.1",
1528 | "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz",
1529 | "integrity": "sha512-uAnSsFGfSpF6DNhBXStvlZILfHJfJu4eUkfbRGk94kGO1Ta7bg6FwfvoOhhyHAJuFbCw+0xk4uJ3u57jLvlCJg==",
1530 | "dependencies": {
1531 | "acorn": "^3.1.0",
1532 | "acorn-globals": "^3.0.0"
1533 | }
1534 | },
1535 | "node_modules/with/node_modules/acorn": {
1536 | "version": "3.3.0",
1537 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
1538 | "integrity": "sha512-OLUyIIZ7mF5oaAUT1w0TFqQS81q3saT46x8t7ukpPjMNk+nbs4ZHhs7ToV8EWnLYLepjETXd4XaCE4uxkMeqUw==",
1539 | "bin": {
1540 | "acorn": "bin/acorn"
1541 | },
1542 | "engines": {
1543 | "node": ">=0.4.0"
1544 | }
1545 | },
1546 | "node_modules/wordwrap": {
1547 | "version": "0.0.2",
1548 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
1549 | "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==",
1550 | "engines": {
1551 | "node": ">=0.4.0"
1552 | }
1553 | },
1554 | "node_modules/wreck": {
1555 | "version": "14.2.0",
1556 | "resolved": "https://registry.npmjs.org/wreck/-/wreck-14.2.0.tgz",
1557 | "integrity": "sha512-NFFft3SMgqrJbXEVfYifh+QDWFxni+98/I7ut7rLbz3F0XOypluHsdo3mdEYssGSirMobM3fGlqhyikbWKDn2Q==",
1558 | "deprecated": "This module has moved and is now available at @hapi/wreck. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
1559 | "dependencies": {
1560 | "boom": "7.x.x",
1561 | "bourne": "1.x.x",
1562 | "hoek": "6.x.x"
1563 | }
1564 | },
1565 | "node_modules/wreck/node_modules/hoek": {
1566 | "version": "6.1.3",
1567 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
1568 | "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==",
1569 | "deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues."
1570 | },
1571 | "node_modules/yargs": {
1572 | "version": "3.10.0",
1573 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
1574 | "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==",
1575 | "dependencies": {
1576 | "camelcase": "^1.0.2",
1577 | "cliui": "^2.1.0",
1578 | "decamelize": "^1.0.0",
1579 | "window-size": "0.1.0"
1580 | }
1581 | }
1582 | }
1583 | }
1584 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "todoist-export",
3 | "description": "Backup Todoist data as JSON or CSV",
4 | "version": "1.3.0",
5 | "author": "Darek Kay (https://darekkay.com/)",
6 | "dependencies": {
7 | "@darekkay/logger": "1.1.2",
8 | "axios": "0.19.2",
9 | "body-parser": "1.19.0",
10 | "cookie-parser": "1.4.4",
11 | "express": "4.17.1",
12 | "json-2-csv": "3.5.5",
13 | "morgan": "1.9.1",
14 | "pug": "2.0.4",
15 | "simple-oauth2": "2.2.1"
16 | },
17 | "devDependencies": {
18 | "prettier": "2.8.0"
19 | },
20 | "homepage": "https://darekkay.com/todoist-export/",
21 | "license": "MIT",
22 | "private": true,
23 | "repository": {
24 | "type": "git",
25 | "url": "https://github.com/darekkay/todoist-export.git"
26 | },
27 | "scripts": {
28 | "format": "prettier --write -- \"{src,bin,public}/**/*.{js,jsx,json,css,scss,md}\"",
29 | "start": "node src/index.js"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/public/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darekkay/todoist-export/02f7e6a4fb169129e778b3478656ef51c78e0605/public/cover.png
--------------------------------------------------------------------------------
/public/favicon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darekkay/todoist-export/02f7e6a4fb169129e778b3478656ef51c78e0605/public/favicon-192.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darekkay/todoist-export/02f7e6a4fb169129e778b3478656ef51c78e0605/public/favicon.ico
--------------------------------------------------------------------------------
/public/js/client.js:
--------------------------------------------------------------------------------
1 | window.onload = function () {
2 | var params = new URLSearchParams(location.search)
3 |
4 | if (params.has("code")) {
5 | window.location.replace(
6 | "/todoist-export/export?code=" + params.get("code") + "&format=" + params.get("state")
7 | );
8 | } else if (params.has("token")) {
9 | document.querySelector("#persistentBackup").style.display = "block";
10 | var persistentBackupUrl =
11 | window.location.href.split("?")[0] +
12 | "download?token=" +
13 | params.get("token") +
14 | "&format=" +
15 | params.get("format");
16 | document.querySelector("#persistentBackupUrl").href = persistentBackupUrl;
17 | document.querySelector("#persistentBackupUrl").innerText =
18 | persistentBackupUrl;
19 | window.location.replace(persistentBackupUrl);
20 | }
21 |
22 | updateArchived(this);
23 | };
24 |
25 | function updateArchived(sender) {
26 | var archived = document.getElementById("archivedCbox");
27 | if (document.getElementById("formatJSON").checked) {
28 | archived.disabled = false;
29 | } else {
30 | archived.disabled = true;
31 | archived.checked = false;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Export for Todoist",
3 | "name": "Export for Todoist",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "48x48 32x32 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "/todoist-export/favicon-192.png",
12 | "sizes": "192x192",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#2196f3",
17 | "background_color": "#ffffff",
18 | "display": "fullscreen"
19 | }
20 |
--------------------------------------------------------------------------------
/public/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: 62.5%;
3 |
4 | box-sizing: border-box;
5 | background-repeat: no-repeat;
6 | }
7 |
8 | *,
9 | ::before,
10 | ::after {
11 | box-sizing: inherit;
12 | background-repeat: inherit;
13 | }
14 |
15 | html,
16 | body {
17 | height: 100%;
18 | }
19 |
20 | body {
21 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
22 | "Noto Sans", "Helvetica Neue", Arial, sans-serif;
23 | font-size: 1.8rem;
24 | line-height: 1.5;
25 | margin: 0;
26 | padding: 0;
27 | display: flex;
28 | flex-direction: column;
29 | color: #1f303e;
30 | }
31 |
32 | a,
33 | a:hover,
34 | a:visited {
35 | color: #005aff;
36 | }
37 |
38 | h1 {
39 | font-size: 3.2rem;
40 | padding-bottom: 0.3rem;
41 | border-bottom: 1px solid #eaecef;
42 | margin-bottom: 2rem;
43 | text-align: center;
44 | }
45 |
46 | h1,
47 | h2 {
48 | font-weight: 600;
49 | }
50 |
51 | h2 {
52 | font-size: 2.4rem;
53 | margin-top: 4rem;
54 | }
55 |
56 | h1 a {
57 | text-decoration: none;
58 | }
59 |
60 | hr {
61 | border: none;
62 | border-top: 1px solid #ccc;
63 | }
64 |
65 | main {
66 | flex: 1 0 auto;
67 | width: 100%;
68 | max-width: 800px;
69 | margin: 5rem auto;
70 | padding: 0 2.5rem;
71 | }
72 |
73 | header,
74 | footer {
75 | flex: none;
76 | display: flex;
77 | justify-content: center;
78 | align-items: center;
79 | text-align: center;
80 | padding: 4rem 1rem;
81 | }
82 |
83 | header h1 {
84 | max-width: 800px;
85 | margin: 0;
86 | padding: 0;
87 | border: none;
88 | }
89 |
90 | footer {
91 | flex-direction: column;
92 | font-size: 1.6rem;
93 | }
94 |
95 | footer > * {
96 | margin: 0.6rem;
97 | }
98 |
99 | .inverted {
100 | background: #233c51;
101 | color: #fff;
102 | }
103 |
104 | .inverted a,
105 | .inverted a:hover,
106 | .inverted a:visited {
107 | color: #face00;
108 | }
109 |
110 | .inverted a:focus {
111 | box-shadow: 0 0 0 0.2rem hsla(49, 100%, 49%, 0.5);
112 | }
113 |
114 | a.unstyled,
115 | a.unstyled:hover,
116 | a.unstyled:visited {
117 | color: inherit;
118 | }
119 |
120 | .form-wrapper {
121 | display: flex;
122 | justify-content: center;
123 | }
124 |
125 | .form-group {
126 | display: flex;
127 | margin-bottom: 1rem;
128 | }
129 |
130 | form {
131 | margin: 3rem 0 3rem 0;
132 | padding: 0 2rem;
133 | }
134 |
135 | label {
136 | display: block;
137 | margin: 0.9rem;
138 | }
139 |
140 | button {
141 | display: inline-block;
142 | padding: 6px 12px;
143 | margin-bottom: 0;
144 | font-size: 1.8rem;
145 | font-weight: 400;
146 | line-height: 1.5;
147 | text-align: center;
148 | white-space: nowrap;
149 | vertical-align: middle;
150 | touch-action: manipulation;
151 | cursor: pointer;
152 | user-select: none;
153 | background-image: none;
154 | border: 1px solid #2e6da4;
155 | border-radius: 4px;
156 |
157 | color: #fff;
158 | background-color: #337ab7;
159 | }
160 |
161 | button:focus,
162 | button:hover {
163 | color: #fff;
164 | background-color: #286090;
165 | border-color: #122b40;
166 | }
167 |
168 | #persistentBackup {
169 | overflow: hidden;
170 | text-overflow: ellipsis;
171 | }
172 |
173 | .text-center {
174 | text-align: center;
175 | }
176 |
177 | :focus {
178 | box-shadow: 0 0 0 0.2rem hsla(219, 100%, 50%, 0.5);
179 | outline: transparent solid 0.2rem;
180 | }
181 |
182 | ::-moz-focus-inner {
183 | border: 0;
184 | padding: 0;
185 | }
186 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darekkay/todoist-export/02f7e6a4fb169129e778b3478656ef51c78e0605/screenshot.png
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const express = require("express");
4 | const cookieParser = require("cookie-parser");
5 | const bodyParser = require("body-parser");
6 | const morgan = require("morgan");
7 | const logger = require("@darekkay/logger");
8 | const axios = require("axios");
9 | const csvParser = require("json-2-csv");
10 |
11 | const config = require("./config");
12 |
13 | const oauth2 = require("simple-oauth2").create({
14 | client: {
15 | id: config.client_id,
16 | secret: config.client_secret,
17 | },
18 | auth: {
19 | tokenHost: "https://todoist.com",
20 | tokenPath: "/oauth/access_token",
21 | authorizePath: "/oauth/authorize",
22 | },
23 | options: {
24 | authorizationMethod: "body",
25 | },
26 | });
27 |
28 | const IS_PRODUCTION = process.env.NODE_ENV === "production";
29 | const COMPL_MAX_PAGE_SIZE = 200;
30 | const FORMAT_SUFFIX_INCLUDE_ARCHIVED = "_all";
31 |
32 | // Enable to debug Todoist API calls
33 | const IS_AXIOS_TRACING_ACTIVE = false;
34 |
35 | if (IS_AXIOS_TRACING_ACTIVE) {
36 | // Log axios requests
37 | axios.interceptors.request.use(function (config) {
38 | logger.log({
39 | url: config.url,
40 | method: config.method,
41 | data: config.data,
42 | });
43 | return config;
44 | });
45 |
46 | // Log axios response errors
47 | axios.interceptors.response.use(undefined, function (error) {
48 | logger.error({
49 | status: error.response?.status,
50 | statusText: error.response?.statusText,
51 | config: error.response?.config,
52 | data: error.response?.data,
53 | });
54 | return Promise.reject(error);
55 | });
56 | }
57 |
58 | const app = express();
59 | const subdirectory = "/todoist-export";
60 |
61 | app.set("views", path.join(__dirname, "views"));
62 | app.set("view engine", "pug");
63 | app.set("json spaces", 2); // prettify json output
64 |
65 | const skipLogsFor = [
66 | "/js/",
67 | "/stylesheets/",
68 | "favicon.ico",
69 | "favicon-192.png",
70 | "manifest.json",
71 | ];
72 |
73 | app.use(
74 | morgan(":method :url :status", {
75 | skip: function (request) {
76 | return skipLogsFor.some(
77 | (part) => request.originalUrl.indexOf(part) !== -1
78 | );
79 | },
80 | })
81 | );
82 | app.use(bodyParser.json());
83 | app.use(bodyParser.urlencoded({ extended: true }));
84 | app.use(cookieParser());
85 | app.use(subdirectory, express.static(path.join(__dirname, "..", "public")));
86 |
87 | app.get(`${subdirectory}/`, (req, res) => {
88 | res.render("index", {});
89 | });
90 |
91 | const callApi = async (api, parameters) => {
92 | const response = await axios({
93 | method: "post",
94 | headers: {
95 | Authorization: "Bearer " + parameters.token,
96 | },
97 | url: `https://todoist.com/sync/v9/${api}`,
98 | data: parameters,
99 | });
100 | return response.data;
101 | };
102 |
103 | const renderErrorPage = (res, message, error) => {
104 | logger.error((error && error.message ? error.message : error) || message);
105 | res.status((error && error.status) || 500);
106 | res.render("error", {
107 | message,
108 | error: IS_PRODUCTION ? undefined : error,
109 | });
110 | };
111 |
112 | app.post(`${subdirectory}/auth`, (req, res) => {
113 | var format = req.body.format || "json"; // csv vs. json
114 | if (req.body.archived) {
115 | format += FORMAT_SUFFIX_INCLUDE_ARCHIVED;
116 | }
117 |
118 | res.redirect(
119 | oauth2.authorizationCode.authorizeURL({
120 | scope: "data:read",
121 | state: format,
122 | })
123 | );
124 | });
125 |
126 | app.get(`${subdirectory}/export`, async (req, res) => {
127 | if (!req.query.code) {
128 | return renderErrorPage(res, "Parameter missing: code", { status: 400 });
129 | }
130 |
131 | try {
132 | const authResponse = await oauth2.authorizationCode.getToken({
133 | code: req.query.code,
134 | });
135 |
136 | const token = authResponse["access_token"];
137 | const format = req.query.format || "json";
138 |
139 | res.redirect(`${subdirectory}?token=${token}&format=${format}`);
140 | } catch (error) {
141 | renderErrorPage(res, error);
142 | }
143 | });
144 |
145 | const escapeCommas = (syncData) =>
146 | syncData.items.map((item) => ({
147 | ...item,
148 | labels: item.labels?.length > 0 ? `"${item.labels.join(",")}"` : null,
149 | content: `"${item.content.toString()}"`,
150 | }));
151 |
152 | /* Convert project IDs into their corresponding names */
153 | const convertProjectNames = (syncData) => {
154 | const projectNames = syncData.projects.reduce(
155 | (acc, project) => ({ ...acc, [project.id]: project.name }),
156 | {}
157 | );
158 |
159 | return syncData.items.map((item) => ({
160 | ...item,
161 | project_id: projectNames[item.project_id],
162 | }));
163 | };
164 |
165 | /* Convert user IDs into their corresponding names */
166 | const convertUserNames = (syncData) => {
167 | const userNames = syncData.collaborators.reduce(
168 | (acc, collaborator) => ({
169 | ...acc,
170 | [collaborator.id]: collaborator.full_name,
171 | }),
172 | {}
173 | );
174 |
175 | return syncData.items.map((item) => ({
176 | ...item,
177 | assigned_by_uid: userNames[item.assigned_by_uid] || null,
178 | added_by_uid: userNames[item.added_by_uid] || null,
179 | user_id: userNames[item.user_id] || null,
180 | }));
181 | };
182 |
183 | const fetchCompleted = async function (token, offset = 0) {
184 | let page;
185 | try {
186 | page = await callApi("completed/get_all", {
187 | token: token,
188 | limit: COMPL_MAX_PAGE_SIZE,
189 | offset: offset,
190 | annotate_notes: true,
191 | annotate_items: true,
192 | });
193 | } catch (error) {
194 | if (error.response) {
195 | logger.error({
196 | status: error.response.status,
197 | statusText: error.response.statusText,
198 | config: error.response.config,
199 | data: error.response.data,
200 | });
201 | } else {
202 | logger.error(error);
203 | }
204 |
205 | // Independent of the error, we return a fallback so the overall export doesn't fail.
206 | return { items: [], projects: [], sections: [] };
207 | }
208 | if (page.items.length > 0) {
209 | const remainder = await fetchCompleted(token, offset + COMPL_MAX_PAGE_SIZE);
210 | return {
211 | items: page.items.concat(remainder.items),
212 | projects: Object.assign({}, page.projects, remainder.projects),
213 | sections: Object.assign({}, page.sections, remainder.sections),
214 | };
215 | } else {
216 | return page;
217 | }
218 | };
219 |
220 | const exportData = async (res, token, format = "csv") => {
221 | const syncData = await callApi("sync", {
222 | token: token,
223 | sync_token: "*",
224 | resource_types: '["all"]',
225 | });
226 |
227 | if (syncData === undefined) {
228 | return renderErrorPage(res, "Could not fetch data from Todoist.");
229 | }
230 |
231 | // Fetch completed tasks (premium-only)
232 | if (format.includes(FORMAT_SUFFIX_INCLUDE_ARCHIVED)) {
233 | if (!syncData.user.is_premium) {
234 | return renderErrorPage(
235 | res,
236 | "Must be Todoist Premium to export archived items."
237 | );
238 | }
239 | format = format.replace(FORMAT_SUFFIX_INCLUDE_ARCHIVED, "");
240 | syncData.completed = await fetchCompleted(token);
241 | }
242 |
243 | if (format === "json") {
244 | res.attachment("todoist.json");
245 | await res.json(syncData);
246 | } else if (format === "csv") {
247 | syncData.items = convertProjectNames(syncData);
248 | syncData.items = convertUserNames(syncData);
249 | syncData.items = escapeCommas(syncData);
250 |
251 | try {
252 | csvParser.json2csv(syncData.items, (error, csv) => {
253 | if (error) {
254 | return renderErrorPage(res, "CSV export error.", error);
255 | }
256 | res.attachment("todoist.csv");
257 | res.send(csv);
258 | });
259 | } catch (error) {
260 | return renderErrorPage(res, "CSV export error.", error);
261 | }
262 | }
263 | };
264 |
265 | app.get(`${subdirectory}/download`, async (req, res) => {
266 | try {
267 | await exportData(res, req.query.token, req.query.format);
268 | } catch (error) {
269 | return renderErrorPage(res, error.message || "Unexpected error.", error);
270 | }
271 | });
272 |
273 | app.get("*", (req, res) => {
274 | res.redirect(subdirectory);
275 | });
276 |
277 | /* Override default express error handling*/
278 | app.use((error, req, res, next) => {
279 | renderErrorPage(res, error.message, error);
280 | });
281 |
282 | module.exports = app;
283 |
--------------------------------------------------------------------------------
/src/config.js.example:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 |
5 | module.exports = {
6 | port: process.env['PORT'] || 3000,
7 | client_id: 'CLIENT_ID',
8 | client_secret: 'CLIENT_SECRET',
9 |
10 | // Run as HTTPS server
11 | /*
12 | ssl: {
13 | cert: fs.readFileSync('./ssl/fullchain.pem'),
14 | key: fs.readFileSync('./ssl/privkey.pem'),
15 | passphrase: 'ssl certificate passphrase'
16 | }
17 | */
18 | };
19 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | const app = require("./app");
3 | const config = require("./config");
4 |
5 | app.set("port", config.port);
6 |
7 | if (config.ssl) {
8 | // Run HTTPS server
9 | require("https")
10 | .createServer(config.ssl, app)
11 | .listen(config.port, function () {
12 | console.info("Server running at https://localhost:" + config.port);
13 | });
14 | } else {
15 | // Run HTTP server
16 | app.listen(app.get("port"), function () {
17 | console.info("Server running at http://localhost:" + config.port);
18 | });
19 | }
20 |
--------------------------------------------------------------------------------
/src/views/error.pug:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | main
5 | h2= message
6 | if error
7 | pre #{error.stack}
8 | a(href="/todoist-export/") Please try again
9 |
--------------------------------------------------------------------------------
/src/views/footer.pug:
--------------------------------------------------------------------------------
1 | footer.inverted
2 | div Handmade with ♥ by Darek Kay
3 | div Fork me on GitHub
4 |
--------------------------------------------------------------------------------
/src/views/header.pug:
--------------------------------------------------------------------------------
1 | header.inverted
2 | h1
3 | a(href="/todoist-export/", class="unstyled") Export for Todoist
4 |
--------------------------------------------------------------------------------
/src/views/index.pug:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | main
5 | p
6 | | This is an open source tool to backup
7 | | Todoist data as JSON or CSV.
8 | p
9 | | Disclaimer: Export for Todoist is not created by, affiliated with, or supported by Doist. I do not take any responsibility and I'm not liable for any damage caused through use of this service.
10 |
11 | div.form-wrapper
12 | form(action="/todoist-export/auth", method="post")
13 |
14 | div.form-group#format
15 | label(for="format")
16 | strong Export as:
17 | div.radios
18 | div.radio
19 | label
20 | input(type="radio", name="format", id="formatCSV", value="csv", checked="checked" onchange="updateArchived(this)")
21 | | CSV (only tasks)
22 | div.radio
23 | label
24 | input(type="radio", name="format", id="formatJSON", value="json", onchange="updateArchived(this)")
25 | | JSON (all data)
26 | div.form-group#archived
27 | label(for="archived")
28 | strong Archived:
29 | div.checkbox
30 | label
31 | input(type="checkbox", name="archived", id="archivedCbox")
32 | | Export all
33 | | (requires Todoist Premium and may take several minutes)
34 |
35 | div.text-center
36 | button#submit(type="submit")
37 | | Authorize & Backup
38 |
39 |
40 | div.text-center(id="persistentBackup", style="display: none;")
41 | p
42 | | To automate your backups (e.g. via a cron job), use the following link:
43 | a(id="persistentBackupUrl")
44 |
45 | hr
46 |
47 | h2 Changelog
48 |
49 | ul
50 | li 2022-12-06: Updated to API v9.
51 | li 2021-02-15: Option to export all archived tasks and projects.
52 | li 2020-02-02: The CSV format contains translated label, project and user names (instead of ID numbers).
53 | li 2019-06-18: Updated to API v8. The output file schema has changed a little bit.
54 | li 2016-09-01: Updated to API v7.
55 | li 2014-12-11: Released this project.
56 |
57 | script(src='js/client.js')
58 |
--------------------------------------------------------------------------------
/src/views/layout.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | head
4 | block head
5 | block title
6 | title Export for Todoist
7 | block meta
8 | meta(name='description', content='Export and backup all your Todoist tasks and data.')
9 | meta(name='keywords', content='')
10 | meta(name='charset', content='utf-8')
11 | meta(name='viewport', content='width=device-width, initial-scale=1')
12 | meta(property='og:image', content='https://darekkay.com/todoist-export/cover.png')
13 | meta(property='og:title', content='Export for Todoist')
14 | meta(name='twitter:site', content='@darek_kay')
15 | meta(name='twitter:card', content='summary_large_image')
16 | link(rel='stylesheet', href='stylesheets/style.css?ver=3')
17 | link(rel='icon', href='/todoist-export/favicon.ico')
18 | link(rel='icon', href='/todoist-export/favicon-192.png', sizes='192x192', type='image/png')
19 | link(rel='manifest', href='/todoist-export/manifest.json')
20 | body
21 | include header
22 | block content
23 | include footer
24 |
--------------------------------------------------------------------------------