├── .gitignore
├── README.md
├── index.js
├── package-lock.json
├── package.json
└── stocks.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This contains the API service for Angular 2 in Action. This is just a sample service, it no longer uses real live data since that adds a lot of complexity to setup and run.
2 |
3 | You will need to run this locally to get some of the examples to work from the book. It is pretty simple as long as you have a recent version of Node installed.
4 |
5 | ```
6 | git clone https://github.com/angular-in-action/api.git
7 | cd api
8 | npm install
9 | node index.js
10 | ```
11 |
12 | ## APIs
13 |
14 | ### `/stocks/snapshot?symbols=aapl,goog,fb`
15 |
16 | This API returns a snapshot of the stocks passed as a symbol parameter. It uses Yahoo! Finance to lookup the snapshot data.
17 |
18 | ### `/stocks/historical/{symbol}`
19 |
20 | This API looks up an individual stock's historical data based on the symbol in the path. It uses Yahoo! Finance to lookup the historical data.
21 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var cors = require('cors');
4 | var express = require('express');
5 |
6 | var app = express();
7 | var stocks = require('./stocks.json');
8 |
9 | // Enable CORS
10 | app.use(cors());
11 |
12 | app.set('port', (process.env.PORT || 3000));
13 |
14 | function getRandomInt(min, max) {
15 | return (Math.floor(Math.random() * (max - min + 1)) + min);
16 | }
17 |
18 | // Endpoint to load snapshot data from yahoo finance
19 | app.get('/stocks/snapshot', function(req, res) {
20 | if (req.query.symbols) {
21 | var symbols = req.query.symbols.split(',');
22 | symbols.map(function(symbol) {
23 | return symbol.toUpperCase();
24 | });
25 |
26 | const items = stocks.filter(stock => symbols.indexOf(stock.symbol) > -1);
27 |
28 | // Add any new items someone might add
29 | const missing = symbols.filter(symbol => !stocks.find(stock => stock.symbol === symbol));
30 | missing.forEach(symbol => {
31 | const lastTradePriceOnly = getRandomInt(0, 100);
32 | const change = getRandomInt(0, 2);
33 | const changeInPercent = change / lastTradePriceOnly;
34 | stocks.push({symbol, lastTradePriceOnly, change, changeInPercent});
35 | });
36 |
37 | res.status(200).send(items);
38 |
39 | } else {
40 | res.status(400).send({message: `The request requires at least one symbol. Try adding '?symbols=appl' to the request.`});
41 | }
42 | });
43 |
44 | // Endpoint to load historical data from yahoo finance.
45 | app.get('/stocks/historical/:symbol', function(req, res) {
46 | var today = new Date();
47 | var yearAgo = new Date(today.getTime() - 1000 * 60 * 60 * 24 * 365);
48 | yahooFinance.historical({
49 | symbol: req.params.symbol,
50 | from: yearAgo.toString(),
51 | to: today.toString()
52 | }, function(err, quotes) {
53 | if (err) {
54 | res.status(500).send(err);
55 | }
56 |
57 | res.status(200).send(quotes);
58 | });
59 | });
60 |
61 | app.get('/', function(req, res) {
62 | res.status(200).contentType('text/html').send(`Welcome to the Angular in Action API. See https://github.com/angular-in-action/api#readme for details.`);
63 | });
64 |
65 | app.listen(app.get('port'), function() {
66 | console.log('App is running on port ', app.get('port'));
67 | });
68 |
69 | // Every 10 seconds, change data values
70 | setInterval(() => {
71 | let start = Date.now();
72 | let changes = [0, 0, 0, 1, 1, 1, 1, 1, -1 -1 -1 -1 -1, 2, 2, 2, -2, -2, -2, 3, -3, 4, -4];
73 | stocks = stocks
74 | .map(stock => {
75 | let index = getRandomInt(0, changes.length - 1);
76 | let change = changes[index];
77 | if (stock.lastTradePriceOnly > 1000) {
78 | change = -1;
79 | }
80 | if (stock.lastTradePriceOnly <= 1) {
81 | change = 1;
82 | }
83 | // Force it to be 2 decimals, cuz in JS floating point math can be lolz
84 | stock.change = parseInt((stock.change * 100) + change) / 100;
85 | stock.changeInPercent = parseInt((stock.changeInPercent * 100) + change) / 100;
86 | stock.changeInPercent = parseInt((stock.change * 100) / (stock.lastTradePriceOnly * 100) * 10000) / 10000;
87 | return stock;
88 | });
89 |
90 | console.log('new stocks %s ms', Date.now() - start);
91 |
92 | }, 10000);
93 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "api",
3 | "version": "1.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "api",
9 | "version": "1.0.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "cors": "2.7.1",
13 | "dotenv": "^4.0.0",
14 | "express": "^4.18.2"
15 | }
16 | },
17 | "node_modules/accepts": {
18 | "version": "1.3.8",
19 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
20 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
21 | "dependencies": {
22 | "mime-types": "~2.1.34",
23 | "negotiator": "0.6.3"
24 | },
25 | "engines": {
26 | "node": ">= 0.6"
27 | }
28 | },
29 | "node_modules/array-flatten": {
30 | "version": "1.1.1",
31 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
32 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
33 | },
34 | "node_modules/body-parser": {
35 | "version": "1.20.1",
36 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
37 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
38 | "dependencies": {
39 | "bytes": "3.1.2",
40 | "content-type": "~1.0.4",
41 | "debug": "2.6.9",
42 | "depd": "2.0.0",
43 | "destroy": "1.2.0",
44 | "http-errors": "2.0.0",
45 | "iconv-lite": "0.4.24",
46 | "on-finished": "2.4.1",
47 | "qs": "6.11.0",
48 | "raw-body": "2.5.1",
49 | "type-is": "~1.6.18",
50 | "unpipe": "1.0.0"
51 | },
52 | "engines": {
53 | "node": ">= 0.8",
54 | "npm": "1.2.8000 || >= 1.4.16"
55 | }
56 | },
57 | "node_modules/bytes": {
58 | "version": "3.1.2",
59 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
60 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
61 | "engines": {
62 | "node": ">= 0.8"
63 | }
64 | },
65 | "node_modules/call-bind": {
66 | "version": "1.0.2",
67 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
68 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
69 | "dependencies": {
70 | "function-bind": "^1.1.1",
71 | "get-intrinsic": "^1.0.2"
72 | },
73 | "funding": {
74 | "url": "https://github.com/sponsors/ljharb"
75 | }
76 | },
77 | "node_modules/content-disposition": {
78 | "version": "0.5.4",
79 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
80 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
81 | "dependencies": {
82 | "safe-buffer": "5.2.1"
83 | },
84 | "engines": {
85 | "node": ">= 0.6"
86 | }
87 | },
88 | "node_modules/content-type": {
89 | "version": "1.0.4",
90 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
91 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
92 | "engines": {
93 | "node": ">= 0.6"
94 | }
95 | },
96 | "node_modules/cookie": {
97 | "version": "0.5.0",
98 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
99 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
100 | "engines": {
101 | "node": ">= 0.6"
102 | }
103 | },
104 | "node_modules/cookie-signature": {
105 | "version": "1.0.6",
106 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
107 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
108 | },
109 | "node_modules/cors": {
110 | "version": "2.7.1",
111 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.7.1.tgz",
112 | "integrity": "sha512-s8O0W7pnSUNauMz02MUIFjRCfM9Cq1q2Dgcz6Lg+zMMPK79RrWj6VggI3E1eKpKrcickW2MbItQF+Vg1ApNnOA==",
113 | "dependencies": {
114 | "vary": "^1"
115 | },
116 | "engines": {
117 | "node": ">=0.10.0"
118 | }
119 | },
120 | "node_modules/debug": {
121 | "version": "2.6.9",
122 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
123 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
124 | "dependencies": {
125 | "ms": "2.0.0"
126 | }
127 | },
128 | "node_modules/depd": {
129 | "version": "2.0.0",
130 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
131 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
132 | "engines": {
133 | "node": ">= 0.8"
134 | }
135 | },
136 | "node_modules/destroy": {
137 | "version": "1.2.0",
138 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
139 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
140 | "engines": {
141 | "node": ">= 0.8",
142 | "npm": "1.2.8000 || >= 1.4.16"
143 | }
144 | },
145 | "node_modules/dotenv": {
146 | "version": "4.0.0",
147 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz",
148 | "integrity": "sha512-XcaMACOr3JMVcEv0Y/iUM2XaOsATRZ3U1In41/1jjK6vJZ2PZbQ1bzCG8uvaByfaBpl9gqc9QWJovpUGBXLLYQ==",
149 | "engines": {
150 | "node": ">=4.6.0"
151 | }
152 | },
153 | "node_modules/ee-first": {
154 | "version": "1.1.1",
155 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
156 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
157 | },
158 | "node_modules/encodeurl": {
159 | "version": "1.0.2",
160 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
161 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
162 | "engines": {
163 | "node": ">= 0.8"
164 | }
165 | },
166 | "node_modules/escape-html": {
167 | "version": "1.0.3",
168 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
169 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
170 | },
171 | "node_modules/etag": {
172 | "version": "1.8.1",
173 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
174 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
175 | "engines": {
176 | "node": ">= 0.6"
177 | }
178 | },
179 | "node_modules/express": {
180 | "version": "4.18.2",
181 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
182 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
183 | "dependencies": {
184 | "accepts": "~1.3.8",
185 | "array-flatten": "1.1.1",
186 | "body-parser": "1.20.1",
187 | "content-disposition": "0.5.4",
188 | "content-type": "~1.0.4",
189 | "cookie": "0.5.0",
190 | "cookie-signature": "1.0.6",
191 | "debug": "2.6.9",
192 | "depd": "2.0.0",
193 | "encodeurl": "~1.0.2",
194 | "escape-html": "~1.0.3",
195 | "etag": "~1.8.1",
196 | "finalhandler": "1.2.0",
197 | "fresh": "0.5.2",
198 | "http-errors": "2.0.0",
199 | "merge-descriptors": "1.0.1",
200 | "methods": "~1.1.2",
201 | "on-finished": "2.4.1",
202 | "parseurl": "~1.3.3",
203 | "path-to-regexp": "0.1.7",
204 | "proxy-addr": "~2.0.7",
205 | "qs": "6.11.0",
206 | "range-parser": "~1.2.1",
207 | "safe-buffer": "5.2.1",
208 | "send": "0.18.0",
209 | "serve-static": "1.15.0",
210 | "setprototypeof": "1.2.0",
211 | "statuses": "2.0.1",
212 | "type-is": "~1.6.18",
213 | "utils-merge": "1.0.1",
214 | "vary": "~1.1.2"
215 | },
216 | "engines": {
217 | "node": ">= 0.10.0"
218 | }
219 | },
220 | "node_modules/finalhandler": {
221 | "version": "1.2.0",
222 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
223 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
224 | "dependencies": {
225 | "debug": "2.6.9",
226 | "encodeurl": "~1.0.2",
227 | "escape-html": "~1.0.3",
228 | "on-finished": "2.4.1",
229 | "parseurl": "~1.3.3",
230 | "statuses": "2.0.1",
231 | "unpipe": "~1.0.0"
232 | },
233 | "engines": {
234 | "node": ">= 0.8"
235 | }
236 | },
237 | "node_modules/forwarded": {
238 | "version": "0.2.0",
239 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
240 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
241 | "engines": {
242 | "node": ">= 0.6"
243 | }
244 | },
245 | "node_modules/fresh": {
246 | "version": "0.5.2",
247 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
248 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
249 | "engines": {
250 | "node": ">= 0.6"
251 | }
252 | },
253 | "node_modules/function-bind": {
254 | "version": "1.1.1",
255 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
256 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
257 | },
258 | "node_modules/get-intrinsic": {
259 | "version": "1.1.3",
260 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
261 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
262 | "dependencies": {
263 | "function-bind": "^1.1.1",
264 | "has": "^1.0.3",
265 | "has-symbols": "^1.0.3"
266 | },
267 | "funding": {
268 | "url": "https://github.com/sponsors/ljharb"
269 | }
270 | },
271 | "node_modules/has": {
272 | "version": "1.0.3",
273 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
274 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
275 | "dependencies": {
276 | "function-bind": "^1.1.1"
277 | },
278 | "engines": {
279 | "node": ">= 0.4.0"
280 | }
281 | },
282 | "node_modules/has-symbols": {
283 | "version": "1.0.3",
284 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
285 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
286 | "engines": {
287 | "node": ">= 0.4"
288 | },
289 | "funding": {
290 | "url": "https://github.com/sponsors/ljharb"
291 | }
292 | },
293 | "node_modules/http-errors": {
294 | "version": "2.0.0",
295 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
296 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
297 | "dependencies": {
298 | "depd": "2.0.0",
299 | "inherits": "2.0.4",
300 | "setprototypeof": "1.2.0",
301 | "statuses": "2.0.1",
302 | "toidentifier": "1.0.1"
303 | },
304 | "engines": {
305 | "node": ">= 0.8"
306 | }
307 | },
308 | "node_modules/iconv-lite": {
309 | "version": "0.4.24",
310 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
311 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
312 | "dependencies": {
313 | "safer-buffer": ">= 2.1.2 < 3"
314 | },
315 | "engines": {
316 | "node": ">=0.10.0"
317 | }
318 | },
319 | "node_modules/inherits": {
320 | "version": "2.0.4",
321 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
322 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
323 | },
324 | "node_modules/ipaddr.js": {
325 | "version": "1.9.1",
326 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
327 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
328 | "engines": {
329 | "node": ">= 0.10"
330 | }
331 | },
332 | "node_modules/media-typer": {
333 | "version": "0.3.0",
334 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
335 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
336 | "engines": {
337 | "node": ">= 0.6"
338 | }
339 | },
340 | "node_modules/merge-descriptors": {
341 | "version": "1.0.1",
342 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
343 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
344 | },
345 | "node_modules/methods": {
346 | "version": "1.1.2",
347 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
348 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
349 | "engines": {
350 | "node": ">= 0.6"
351 | }
352 | },
353 | "node_modules/mime": {
354 | "version": "1.6.0",
355 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
356 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
357 | "bin": {
358 | "mime": "cli.js"
359 | },
360 | "engines": {
361 | "node": ">=4"
362 | }
363 | },
364 | "node_modules/mime-db": {
365 | "version": "1.52.0",
366 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
367 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
368 | "engines": {
369 | "node": ">= 0.6"
370 | }
371 | },
372 | "node_modules/mime-types": {
373 | "version": "2.1.35",
374 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
375 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
376 | "dependencies": {
377 | "mime-db": "1.52.0"
378 | },
379 | "engines": {
380 | "node": ">= 0.6"
381 | }
382 | },
383 | "node_modules/ms": {
384 | "version": "2.0.0",
385 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
386 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
387 | },
388 | "node_modules/negotiator": {
389 | "version": "0.6.3",
390 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
391 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
392 | "engines": {
393 | "node": ">= 0.6"
394 | }
395 | },
396 | "node_modules/object-inspect": {
397 | "version": "1.12.2",
398 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
399 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
400 | "funding": {
401 | "url": "https://github.com/sponsors/ljharb"
402 | }
403 | },
404 | "node_modules/on-finished": {
405 | "version": "2.4.1",
406 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
407 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
408 | "dependencies": {
409 | "ee-first": "1.1.1"
410 | },
411 | "engines": {
412 | "node": ">= 0.8"
413 | }
414 | },
415 | "node_modules/parseurl": {
416 | "version": "1.3.3",
417 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
418 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
419 | "engines": {
420 | "node": ">= 0.8"
421 | }
422 | },
423 | "node_modules/path-to-regexp": {
424 | "version": "0.1.7",
425 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
426 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
427 | },
428 | "node_modules/proxy-addr": {
429 | "version": "2.0.7",
430 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
431 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
432 | "dependencies": {
433 | "forwarded": "0.2.0",
434 | "ipaddr.js": "1.9.1"
435 | },
436 | "engines": {
437 | "node": ">= 0.10"
438 | }
439 | },
440 | "node_modules/qs": {
441 | "version": "6.11.0",
442 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
443 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
444 | "dependencies": {
445 | "side-channel": "^1.0.4"
446 | },
447 | "engines": {
448 | "node": ">=0.6"
449 | },
450 | "funding": {
451 | "url": "https://github.com/sponsors/ljharb"
452 | }
453 | },
454 | "node_modules/range-parser": {
455 | "version": "1.2.1",
456 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
457 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
458 | "engines": {
459 | "node": ">= 0.6"
460 | }
461 | },
462 | "node_modules/raw-body": {
463 | "version": "2.5.1",
464 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
465 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
466 | "dependencies": {
467 | "bytes": "3.1.2",
468 | "http-errors": "2.0.0",
469 | "iconv-lite": "0.4.24",
470 | "unpipe": "1.0.0"
471 | },
472 | "engines": {
473 | "node": ">= 0.8"
474 | }
475 | },
476 | "node_modules/safe-buffer": {
477 | "version": "5.2.1",
478 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
479 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
480 | "funding": [
481 | {
482 | "type": "github",
483 | "url": "https://github.com/sponsors/feross"
484 | },
485 | {
486 | "type": "patreon",
487 | "url": "https://www.patreon.com/feross"
488 | },
489 | {
490 | "type": "consulting",
491 | "url": "https://feross.org/support"
492 | }
493 | ]
494 | },
495 | "node_modules/safer-buffer": {
496 | "version": "2.1.2",
497 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
498 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
499 | },
500 | "node_modules/send": {
501 | "version": "0.18.0",
502 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
503 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
504 | "dependencies": {
505 | "debug": "2.6.9",
506 | "depd": "2.0.0",
507 | "destroy": "1.2.0",
508 | "encodeurl": "~1.0.2",
509 | "escape-html": "~1.0.3",
510 | "etag": "~1.8.1",
511 | "fresh": "0.5.2",
512 | "http-errors": "2.0.0",
513 | "mime": "1.6.0",
514 | "ms": "2.1.3",
515 | "on-finished": "2.4.1",
516 | "range-parser": "~1.2.1",
517 | "statuses": "2.0.1"
518 | },
519 | "engines": {
520 | "node": ">= 0.8.0"
521 | }
522 | },
523 | "node_modules/send/node_modules/ms": {
524 | "version": "2.1.3",
525 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
526 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
527 | },
528 | "node_modules/serve-static": {
529 | "version": "1.15.0",
530 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
531 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
532 | "dependencies": {
533 | "encodeurl": "~1.0.2",
534 | "escape-html": "~1.0.3",
535 | "parseurl": "~1.3.3",
536 | "send": "0.18.0"
537 | },
538 | "engines": {
539 | "node": ">= 0.8.0"
540 | }
541 | },
542 | "node_modules/setprototypeof": {
543 | "version": "1.2.0",
544 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
545 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
546 | },
547 | "node_modules/side-channel": {
548 | "version": "1.0.4",
549 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
550 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
551 | "dependencies": {
552 | "call-bind": "^1.0.0",
553 | "get-intrinsic": "^1.0.2",
554 | "object-inspect": "^1.9.0"
555 | },
556 | "funding": {
557 | "url": "https://github.com/sponsors/ljharb"
558 | }
559 | },
560 | "node_modules/statuses": {
561 | "version": "2.0.1",
562 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
563 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
564 | "engines": {
565 | "node": ">= 0.8"
566 | }
567 | },
568 | "node_modules/toidentifier": {
569 | "version": "1.0.1",
570 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
571 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
572 | "engines": {
573 | "node": ">=0.6"
574 | }
575 | },
576 | "node_modules/type-is": {
577 | "version": "1.6.18",
578 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
579 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
580 | "dependencies": {
581 | "media-typer": "0.3.0",
582 | "mime-types": "~2.1.24"
583 | },
584 | "engines": {
585 | "node": ">= 0.6"
586 | }
587 | },
588 | "node_modules/unpipe": {
589 | "version": "1.0.0",
590 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
591 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
592 | "engines": {
593 | "node": ">= 0.8"
594 | }
595 | },
596 | "node_modules/utils-merge": {
597 | "version": "1.0.1",
598 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
599 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
600 | "engines": {
601 | "node": ">= 0.4.0"
602 | }
603 | },
604 | "node_modules/vary": {
605 | "version": "1.1.2",
606 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
607 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
608 | "engines": {
609 | "node": ">= 0.8"
610 | }
611 | }
612 | },
613 | "dependencies": {
614 | "accepts": {
615 | "version": "1.3.8",
616 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
617 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
618 | "requires": {
619 | "mime-types": "~2.1.34",
620 | "negotiator": "0.6.3"
621 | }
622 | },
623 | "array-flatten": {
624 | "version": "1.1.1",
625 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
626 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
627 | },
628 | "body-parser": {
629 | "version": "1.20.1",
630 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
631 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
632 | "requires": {
633 | "bytes": "3.1.2",
634 | "content-type": "~1.0.4",
635 | "debug": "2.6.9",
636 | "depd": "2.0.0",
637 | "destroy": "1.2.0",
638 | "http-errors": "2.0.0",
639 | "iconv-lite": "0.4.24",
640 | "on-finished": "2.4.1",
641 | "qs": "6.11.0",
642 | "raw-body": "2.5.1",
643 | "type-is": "~1.6.18",
644 | "unpipe": "1.0.0"
645 | }
646 | },
647 | "bytes": {
648 | "version": "3.1.2",
649 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
650 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
651 | },
652 | "call-bind": {
653 | "version": "1.0.2",
654 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
655 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
656 | "requires": {
657 | "function-bind": "^1.1.1",
658 | "get-intrinsic": "^1.0.2"
659 | }
660 | },
661 | "content-disposition": {
662 | "version": "0.5.4",
663 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
664 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
665 | "requires": {
666 | "safe-buffer": "5.2.1"
667 | }
668 | },
669 | "content-type": {
670 | "version": "1.0.4",
671 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
672 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
673 | },
674 | "cookie": {
675 | "version": "0.5.0",
676 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
677 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
678 | },
679 | "cookie-signature": {
680 | "version": "1.0.6",
681 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
682 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
683 | },
684 | "cors": {
685 | "version": "2.7.1",
686 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.7.1.tgz",
687 | "integrity": "sha512-s8O0W7pnSUNauMz02MUIFjRCfM9Cq1q2Dgcz6Lg+zMMPK79RrWj6VggI3E1eKpKrcickW2MbItQF+Vg1ApNnOA==",
688 | "requires": {
689 | "vary": "^1"
690 | }
691 | },
692 | "debug": {
693 | "version": "2.6.9",
694 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
695 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
696 | "requires": {
697 | "ms": "2.0.0"
698 | }
699 | },
700 | "depd": {
701 | "version": "2.0.0",
702 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
703 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
704 | },
705 | "destroy": {
706 | "version": "1.2.0",
707 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
708 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
709 | },
710 | "dotenv": {
711 | "version": "4.0.0",
712 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz",
713 | "integrity": "sha512-XcaMACOr3JMVcEv0Y/iUM2XaOsATRZ3U1In41/1jjK6vJZ2PZbQ1bzCG8uvaByfaBpl9gqc9QWJovpUGBXLLYQ=="
714 | },
715 | "ee-first": {
716 | "version": "1.1.1",
717 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
718 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
719 | },
720 | "encodeurl": {
721 | "version": "1.0.2",
722 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
723 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
724 | },
725 | "escape-html": {
726 | "version": "1.0.3",
727 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
728 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
729 | },
730 | "etag": {
731 | "version": "1.8.1",
732 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
733 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
734 | },
735 | "express": {
736 | "version": "4.18.2",
737 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
738 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
739 | "requires": {
740 | "accepts": "~1.3.8",
741 | "array-flatten": "1.1.1",
742 | "body-parser": "1.20.1",
743 | "content-disposition": "0.5.4",
744 | "content-type": "~1.0.4",
745 | "cookie": "0.5.0",
746 | "cookie-signature": "1.0.6",
747 | "debug": "2.6.9",
748 | "depd": "2.0.0",
749 | "encodeurl": "~1.0.2",
750 | "escape-html": "~1.0.3",
751 | "etag": "~1.8.1",
752 | "finalhandler": "1.2.0",
753 | "fresh": "0.5.2",
754 | "http-errors": "2.0.0",
755 | "merge-descriptors": "1.0.1",
756 | "methods": "~1.1.2",
757 | "on-finished": "2.4.1",
758 | "parseurl": "~1.3.3",
759 | "path-to-regexp": "0.1.7",
760 | "proxy-addr": "~2.0.7",
761 | "qs": "6.11.0",
762 | "range-parser": "~1.2.1",
763 | "safe-buffer": "5.2.1",
764 | "send": "0.18.0",
765 | "serve-static": "1.15.0",
766 | "setprototypeof": "1.2.0",
767 | "statuses": "2.0.1",
768 | "type-is": "~1.6.18",
769 | "utils-merge": "1.0.1",
770 | "vary": "~1.1.2"
771 | }
772 | },
773 | "finalhandler": {
774 | "version": "1.2.0",
775 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
776 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
777 | "requires": {
778 | "debug": "2.6.9",
779 | "encodeurl": "~1.0.2",
780 | "escape-html": "~1.0.3",
781 | "on-finished": "2.4.1",
782 | "parseurl": "~1.3.3",
783 | "statuses": "2.0.1",
784 | "unpipe": "~1.0.0"
785 | }
786 | },
787 | "forwarded": {
788 | "version": "0.2.0",
789 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
790 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
791 | },
792 | "fresh": {
793 | "version": "0.5.2",
794 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
795 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
796 | },
797 | "function-bind": {
798 | "version": "1.1.1",
799 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
800 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
801 | },
802 | "get-intrinsic": {
803 | "version": "1.1.3",
804 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
805 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
806 | "requires": {
807 | "function-bind": "^1.1.1",
808 | "has": "^1.0.3",
809 | "has-symbols": "^1.0.3"
810 | }
811 | },
812 | "has": {
813 | "version": "1.0.3",
814 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
815 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
816 | "requires": {
817 | "function-bind": "^1.1.1"
818 | }
819 | },
820 | "has-symbols": {
821 | "version": "1.0.3",
822 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
823 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
824 | },
825 | "http-errors": {
826 | "version": "2.0.0",
827 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
828 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
829 | "requires": {
830 | "depd": "2.0.0",
831 | "inherits": "2.0.4",
832 | "setprototypeof": "1.2.0",
833 | "statuses": "2.0.1",
834 | "toidentifier": "1.0.1"
835 | }
836 | },
837 | "iconv-lite": {
838 | "version": "0.4.24",
839 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
840 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
841 | "requires": {
842 | "safer-buffer": ">= 2.1.2 < 3"
843 | }
844 | },
845 | "inherits": {
846 | "version": "2.0.4",
847 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
848 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
849 | },
850 | "ipaddr.js": {
851 | "version": "1.9.1",
852 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
853 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
854 | },
855 | "media-typer": {
856 | "version": "0.3.0",
857 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
858 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
859 | },
860 | "merge-descriptors": {
861 | "version": "1.0.1",
862 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
863 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
864 | },
865 | "methods": {
866 | "version": "1.1.2",
867 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
868 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
869 | },
870 | "mime": {
871 | "version": "1.6.0",
872 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
873 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
874 | },
875 | "mime-db": {
876 | "version": "1.52.0",
877 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
878 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
879 | },
880 | "mime-types": {
881 | "version": "2.1.35",
882 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
883 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
884 | "requires": {
885 | "mime-db": "1.52.0"
886 | }
887 | },
888 | "ms": {
889 | "version": "2.0.0",
890 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
891 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
892 | },
893 | "negotiator": {
894 | "version": "0.6.3",
895 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
896 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
897 | },
898 | "object-inspect": {
899 | "version": "1.12.2",
900 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
901 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
902 | },
903 | "on-finished": {
904 | "version": "2.4.1",
905 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
906 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
907 | "requires": {
908 | "ee-first": "1.1.1"
909 | }
910 | },
911 | "parseurl": {
912 | "version": "1.3.3",
913 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
914 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
915 | },
916 | "path-to-regexp": {
917 | "version": "0.1.7",
918 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
919 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
920 | },
921 | "proxy-addr": {
922 | "version": "2.0.7",
923 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
924 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
925 | "requires": {
926 | "forwarded": "0.2.0",
927 | "ipaddr.js": "1.9.1"
928 | }
929 | },
930 | "qs": {
931 | "version": "6.11.0",
932 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
933 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
934 | "requires": {
935 | "side-channel": "^1.0.4"
936 | }
937 | },
938 | "range-parser": {
939 | "version": "1.2.1",
940 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
941 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
942 | },
943 | "raw-body": {
944 | "version": "2.5.1",
945 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
946 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
947 | "requires": {
948 | "bytes": "3.1.2",
949 | "http-errors": "2.0.0",
950 | "iconv-lite": "0.4.24",
951 | "unpipe": "1.0.0"
952 | }
953 | },
954 | "safe-buffer": {
955 | "version": "5.2.1",
956 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
957 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
958 | },
959 | "safer-buffer": {
960 | "version": "2.1.2",
961 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
962 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
963 | },
964 | "send": {
965 | "version": "0.18.0",
966 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
967 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
968 | "requires": {
969 | "debug": "2.6.9",
970 | "depd": "2.0.0",
971 | "destroy": "1.2.0",
972 | "encodeurl": "~1.0.2",
973 | "escape-html": "~1.0.3",
974 | "etag": "~1.8.1",
975 | "fresh": "0.5.2",
976 | "http-errors": "2.0.0",
977 | "mime": "1.6.0",
978 | "ms": "2.1.3",
979 | "on-finished": "2.4.1",
980 | "range-parser": "~1.2.1",
981 | "statuses": "2.0.1"
982 | },
983 | "dependencies": {
984 | "ms": {
985 | "version": "2.1.3",
986 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
987 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
988 | }
989 | }
990 | },
991 | "serve-static": {
992 | "version": "1.15.0",
993 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
994 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
995 | "requires": {
996 | "encodeurl": "~1.0.2",
997 | "escape-html": "~1.0.3",
998 | "parseurl": "~1.3.3",
999 | "send": "0.18.0"
1000 | }
1001 | },
1002 | "setprototypeof": {
1003 | "version": "1.2.0",
1004 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
1005 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
1006 | },
1007 | "side-channel": {
1008 | "version": "1.0.4",
1009 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
1010 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
1011 | "requires": {
1012 | "call-bind": "^1.0.0",
1013 | "get-intrinsic": "^1.0.2",
1014 | "object-inspect": "^1.9.0"
1015 | }
1016 | },
1017 | "statuses": {
1018 | "version": "2.0.1",
1019 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
1020 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
1021 | },
1022 | "toidentifier": {
1023 | "version": "1.0.1",
1024 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
1025 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
1026 | },
1027 | "type-is": {
1028 | "version": "1.6.18",
1029 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1030 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1031 | "requires": {
1032 | "media-typer": "0.3.0",
1033 | "mime-types": "~2.1.24"
1034 | }
1035 | },
1036 | "unpipe": {
1037 | "version": "1.0.0",
1038 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1039 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
1040 | },
1041 | "utils-merge": {
1042 | "version": "1.0.1",
1043 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1044 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
1045 | },
1046 | "vary": {
1047 | "version": "1.1.2",
1048 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1049 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
1050 | }
1051 | }
1052 | }
1053 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "api",
3 | "version": "1.0.0",
4 | "description": "Angular 2 in Action API",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/angular-in-action/api.git"
9 | },
10 | "keywords": [
11 | "angular2"
12 | ],
13 | "author": "Jeremy Wilken ",
14 | "license": "MIT",
15 | "bugs": {
16 | "url": "https://github.com/angular-in-action/api/issues"
17 | },
18 | "homepage": "https://github.com/angular-in-action/api#readme",
19 | "dependencies": {
20 | "cors": "2.7.1",
21 | "dotenv": "^4.0.0",
22 | "express": "^4.18.2"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/stocks.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "symbol": "AAPL",
4 | "lastTradePriceOnly": 152.63,
5 | "change": -3.08,
6 | "changeInPercent": -0.0198
7 | },
8 | {
9 | "symbol": "TWTR",
10 | "lastTradePriceOnly": 53.70,
11 | "change": 1.20,
12 | "changeInPercent": 0.0223
13 | },
14 | {
15 | "symbol": "GOOG",
16 | "lastTradePriceOnly": 86.70,
17 | "change": 3.21,
18 | "changeInPercent": 0.0384
19 | },
20 | {
21 | "symbol": "FB",
22 | "lastTradePriceOnly": 90.79,
23 | "change": 1.88,
24 | "changeInPercent": 0.0207
25 | },
26 | {
27 | "symbol": "AMZN",
28 | "lastTradePriceOnly": 90.98,
29 | "change": 1.68,
30 | "changeInPercent": 0.0188
31 | }
32 | ]
--------------------------------------------------------------------------------