add http-server part 7.8
This commit is contained in:
parent
acdeb23c92
commit
69bd8bef0f
15 changed files with 902 additions and 0 deletions
|
@ -9,6 +9,9 @@ COPY tsconfig.backend.json ./
|
||||||
COPY tsconfig.broker.json ./
|
COPY tsconfig.broker.json ./
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
### NEW ###
|
||||||
|
RUN npm install cors
|
||||||
|
|
||||||
RUN npm install -g npm@11.2.0
|
RUN npm install -g npm@11.2.0
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
import cors from 'cors'; // <--- hinzufügen
|
||||||
import { executeCommand } from './broker.js';
|
import { executeCommand } from './broker.js';
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const port = 8090; //TODO: OR 8080
|
const port = 8090; //TODO: OR 8080
|
||||||
|
|
||||||
|
//CORS aktivieren
|
||||||
|
app.use(cors());
|
||||||
|
|
||||||
app.post('/api/command', (req, res) => {
|
app.post('/api/command', (req, res) => {
|
||||||
executeCommand();
|
executeCommand();
|
||||||
res.status(200).send('Command executed');
|
res.status(200).send('Command executed');
|
||||||
|
|
22
node_modules/.package-lock.json
generated
vendored
22
node_modules/.package-lock.json
generated
vendored
|
@ -1855,6 +1855,19 @@
|
||||||
"node": ">=6.6.0"
|
"node": ">=6.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cors": {
|
||||||
|
"version": "2.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||||
|
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"object-assign": "^4",
|
||||||
|
"vary": "^1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/corser": {
|
"node_modules/corser": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
|
||||||
|
@ -3843,6 +3856,15 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/object-assign": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-inspect": {
|
"node_modules/object-inspect": {
|
||||||
"version": "1.13.4",
|
"version": "1.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||||
|
|
33
node_modules/cors/CONTRIBUTING.md
generated
vendored
Normal file
33
node_modules/cors/CONTRIBUTING.md
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# contributing to `cors`
|
||||||
|
|
||||||
|
CORS is a node.js package for providing a [connect](http://www.senchalabs.org/connect/)/[express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options. Learn more about the project in [the README](README.md).
|
||||||
|
|
||||||
|
## The CORS Spec
|
||||||
|
|
||||||
|
[http://www.w3.org/TR/cors/](http://www.w3.org/TR/cors/)
|
||||||
|
|
||||||
|
## Pull Requests Welcome
|
||||||
|
|
||||||
|
* Include `'use strict';` in every javascript file.
|
||||||
|
* 2 space indentation.
|
||||||
|
* Please run the testing steps below before submitting.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install
|
||||||
|
$ npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Interactive Testing Harness
|
||||||
|
|
||||||
|
[http://node-cors-client.herokuapp.com](http://node-cors-client.herokuapp.com)
|
||||||
|
|
||||||
|
Related git repositories:
|
||||||
|
|
||||||
|
* [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server)
|
||||||
|
* [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT License](http://www.opensource.org/licenses/mit-license.php)
|
58
node_modules/cors/HISTORY.md
generated
vendored
Normal file
58
node_modules/cors/HISTORY.md
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
2.8.5 / 2018-11-04
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix setting `maxAge` option to `0`
|
||||||
|
|
||||||
|
2.8.4 / 2017-07-12
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Work-around Safari bug in default pre-flight response
|
||||||
|
|
||||||
|
2.8.3 / 2017-03-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix error when options delegate missing `methods` option
|
||||||
|
|
||||||
|
2.8.2 / 2017-03-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix error when frozen options are passed
|
||||||
|
* Send "Vary: Origin" when using regular expressions
|
||||||
|
* Send "Vary: Access-Control-Request-Headers" when dynamic `allowedHeaders`
|
||||||
|
|
||||||
|
2.8.1 / 2016-09-08
|
||||||
|
==================
|
||||||
|
|
||||||
|
This release only changed documentation.
|
||||||
|
|
||||||
|
2.8.0 / 2016-08-23
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Add `optionsSuccessStatus` option
|
||||||
|
|
||||||
|
2.7.2 / 2016-08-23
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix error when Node.js running in strict mode
|
||||||
|
|
||||||
|
2.7.1 / 2015-05-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Move module into expressjs organization
|
||||||
|
|
||||||
|
2.7.0 / 2015-05-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Allow array of matching condition as `origin` option
|
||||||
|
* Allow regular expression as `origin` option
|
||||||
|
|
||||||
|
2.6.1 / 2015-05-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Update `license` in package.json
|
||||||
|
|
||||||
|
2.6.0 / 2015-04-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Add `preflightContinue` option
|
||||||
|
* Fix "Vary: Origin" header added for "*"
|
22
node_modules/cors/LICENSE
generated
vendored
Normal file
22
node_modules/cors/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2013 Troy Goode <troygoode@gmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
243
node_modules/cors/README.md
generated
vendored
Normal file
243
node_modules/cors/README.md
generated
vendored
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
# cors
|
||||||
|
|
||||||
|
[![NPM Version][npm-image]][npm-url]
|
||||||
|
[![NPM Downloads][downloads-image]][downloads-url]
|
||||||
|
[![Build Status][travis-image]][travis-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
|
CORS is a node.js package for providing a [Connect](http://www.senchalabs.org/connect/)/[Express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options.
|
||||||
|
|
||||||
|
**[Follow me (@troygoode) on Twitter!](https://twitter.com/intent/user?screen_name=troygoode)**
|
||||||
|
|
||||||
|
* [Installation](#installation)
|
||||||
|
* [Usage](#usage)
|
||||||
|
* [Simple Usage](#simple-usage-enable-all-cors-requests)
|
||||||
|
* [Enable CORS for a Single Route](#enable-cors-for-a-single-route)
|
||||||
|
* [Configuring CORS](#configuring-cors)
|
||||||
|
* [Configuring CORS Asynchronously](#configuring-cors-asynchronously)
|
||||||
|
* [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)
|
||||||
|
* [Configuration Options](#configuration-options)
|
||||||
|
* [Demo](#demo)
|
||||||
|
* [License](#license)
|
||||||
|
* [Author](#author)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install cors
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Simple Usage (Enable *All* CORS Requests)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
app.use(cors())
|
||||||
|
|
||||||
|
app.get('/products/:id', function (req, res, next) {
|
||||||
|
res.json({msg: 'This is CORS-enabled for all origins!'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('CORS-enabled web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enable CORS for a Single Route
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
app.get('/products/:id', cors(), function (req, res, next) {
|
||||||
|
res.json({msg: 'This is CORS-enabled for a Single Route'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('CORS-enabled web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuring CORS
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
var corsOptions = {
|
||||||
|
origin: 'http://example.com',
|
||||||
|
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
|
||||||
|
}
|
||||||
|
|
||||||
|
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
|
||||||
|
res.json({msg: 'This is CORS-enabled for only example.com.'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('CORS-enabled web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuring CORS w/ Dynamic Origin
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
var whitelist = ['http://example1.com', 'http://example2.com']
|
||||||
|
var corsOptions = {
|
||||||
|
origin: function (origin, callback) {
|
||||||
|
if (whitelist.indexOf(origin) !== -1) {
|
||||||
|
callback(null, true)
|
||||||
|
} else {
|
||||||
|
callback(new Error('Not allowed by CORS'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
|
||||||
|
res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('CORS-enabled web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
If you do not want to block REST tools or server-to-server requests,
|
||||||
|
add a `!origin` check in the origin function like so:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var corsOptions = {
|
||||||
|
origin: function (origin, callback) {
|
||||||
|
if (whitelist.indexOf(origin) !== -1 || !origin) {
|
||||||
|
callback(null, true)
|
||||||
|
} else {
|
||||||
|
callback(new Error('Not allowed by CORS'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enabling CORS Pre-Flight
|
||||||
|
|
||||||
|
Certain CORS requests are considered 'complex' and require an initial
|
||||||
|
`OPTIONS` request (called the "pre-flight request"). An example of a
|
||||||
|
'complex' CORS request is one that uses an HTTP verb other than
|
||||||
|
GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable
|
||||||
|
pre-flighting, you must add a new OPTIONS handler for the route you want
|
||||||
|
to support:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
app.options('/products/:id', cors()) // enable pre-flight request for DELETE request
|
||||||
|
app.del('/products/:id', cors(), function (req, res, next) {
|
||||||
|
res.json({msg: 'This is CORS-enabled for all origins!'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('CORS-enabled web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also enable pre-flight across-the-board like so:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
app.options('*', cors()) // include before other routes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuring CORS Asynchronously
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
var whitelist = ['http://example1.com', 'http://example2.com']
|
||||||
|
var corsOptionsDelegate = function (req, callback) {
|
||||||
|
var corsOptions;
|
||||||
|
if (whitelist.indexOf(req.header('Origin')) !== -1) {
|
||||||
|
corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
|
||||||
|
} else {
|
||||||
|
corsOptions = { origin: false } // disable CORS for this request
|
||||||
|
}
|
||||||
|
callback(null, corsOptions) // callback expects two parameters: error and options
|
||||||
|
}
|
||||||
|
|
||||||
|
app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) {
|
||||||
|
res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('CORS-enabled web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
* `origin`: Configures the **Access-Control-Allow-Origin** CORS header. Possible values:
|
||||||
|
- `Boolean` - set `origin` to `true` to reflect the [request origin](http://tools.ietf.org/html/draft-abarth-origin-09), as defined by `req.header('Origin')`, or set it to `false` to disable CORS.
|
||||||
|
- `String` - set `origin` to a specific origin. For example if you set it to `"http://example.com"` only requests from "http://example.com" will be allowed.
|
||||||
|
- `RegExp` - set `origin` to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern `/example\.com$/` will reflect any request that is coming from an origin ending with "example.com".
|
||||||
|
- `Array` - set `origin` to an array of valid origins. Each origin can be a `String` or a `RegExp`. For example `["http://example1.com", /\.example2\.com$/]` will accept any request from "http://example1.com" or from a subdomain of "example2.com".
|
||||||
|
- `Function` - set `origin` to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signature `err [object], allow [bool]`) as the second.
|
||||||
|
* `methods`: Configures the **Access-Control-Allow-Methods** CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: `['GET', 'PUT', 'POST']`).
|
||||||
|
* `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Type,Authorization') or an array (ex: `['Content-Type', 'Authorization']`). If not specified, defaults to reflecting the headers specified in the request's **Access-Control-Request-Headers** header.
|
||||||
|
* `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Range,X-Content-Range') or an array (ex: `['Content-Range', 'X-Content-Range']`). If not specified, no custom headers are exposed.
|
||||||
|
* `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. Set to `true` to pass the header, otherwise it is omitted.
|
||||||
|
* `maxAge`: Configures the **Access-Control-Max-Age** CORS header. Set to an integer to pass the header, otherwise it is omitted.
|
||||||
|
* `preflightContinue`: Pass the CORS preflight response to the next handler.
|
||||||
|
* `optionsSuccessStatus`: Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`.
|
||||||
|
|
||||||
|
The default configuration is the equivalent of:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"origin": "*",
|
||||||
|
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
|
||||||
|
"preflightContinue": false,
|
||||||
|
"optionsSuccessStatus": 204
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For details on the effect of each CORS header, read [this](http://www.html5rocks.com/en/tutorials/cors/) article on HTML5 Rocks.
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
A demo that illustrates CORS working (and not working) using jQuery is available here: [http://node-cors-client.herokuapp.com/](http://node-cors-client.herokuapp.com/)
|
||||||
|
|
||||||
|
Code for that demo can be found here:
|
||||||
|
|
||||||
|
* Client: [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client)
|
||||||
|
* Server: [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
[Troy Goode](https://github.com/TroyGoode) ([troygoode@gmail.com](mailto:troygoode@gmail.com))
|
||||||
|
|
||||||
|
[coveralls-image]: https://img.shields.io/coveralls/expressjs/cors/master.svg
|
||||||
|
[coveralls-url]: https://coveralls.io/r/expressjs/cors?branch=master
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/cors.svg
|
||||||
|
[downloads-url]: https://npmjs.org/package/cors
|
||||||
|
[npm-image]: https://img.shields.io/npm/v/cors.svg
|
||||||
|
[npm-url]: https://npmjs.org/package/cors
|
||||||
|
[travis-image]: https://img.shields.io/travis/expressjs/cors/master.svg
|
||||||
|
[travis-url]: https://travis-ci.org/expressjs/cors
|
238
node_modules/cors/lib/index.js
generated
vendored
Normal file
238
node_modules/cors/lib/index.js
generated
vendored
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var assign = require('object-assign');
|
||||||
|
var vary = require('vary');
|
||||||
|
|
||||||
|
var defaults = {
|
||||||
|
origin: '*',
|
||||||
|
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||||
|
preflightContinue: false,
|
||||||
|
optionsSuccessStatus: 204
|
||||||
|
};
|
||||||
|
|
||||||
|
function isString(s) {
|
||||||
|
return typeof s === 'string' || s instanceof String;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isOriginAllowed(origin, allowedOrigin) {
|
||||||
|
if (Array.isArray(allowedOrigin)) {
|
||||||
|
for (var i = 0; i < allowedOrigin.length; ++i) {
|
||||||
|
if (isOriginAllowed(origin, allowedOrigin[i])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else if (isString(allowedOrigin)) {
|
||||||
|
return origin === allowedOrigin;
|
||||||
|
} else if (allowedOrigin instanceof RegExp) {
|
||||||
|
return allowedOrigin.test(origin);
|
||||||
|
} else {
|
||||||
|
return !!allowedOrigin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureOrigin(options, req) {
|
||||||
|
var requestOrigin = req.headers.origin,
|
||||||
|
headers = [],
|
||||||
|
isAllowed;
|
||||||
|
|
||||||
|
if (!options.origin || options.origin === '*') {
|
||||||
|
// allow any origin
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Origin',
|
||||||
|
value: '*'
|
||||||
|
}]);
|
||||||
|
} else if (isString(options.origin)) {
|
||||||
|
// fixed origin
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Origin',
|
||||||
|
value: options.origin
|
||||||
|
}]);
|
||||||
|
headers.push([{
|
||||||
|
key: 'Vary',
|
||||||
|
value: 'Origin'
|
||||||
|
}]);
|
||||||
|
} else {
|
||||||
|
isAllowed = isOriginAllowed(requestOrigin, options.origin);
|
||||||
|
// reflect origin
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Origin',
|
||||||
|
value: isAllowed ? requestOrigin : false
|
||||||
|
}]);
|
||||||
|
headers.push([{
|
||||||
|
key: 'Vary',
|
||||||
|
value: 'Origin'
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureMethods(options) {
|
||||||
|
var methods = options.methods;
|
||||||
|
if (methods.join) {
|
||||||
|
methods = options.methods.join(','); // .methods is an array, so turn it into a string
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Allow-Methods',
|
||||||
|
value: methods
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureCredentials(options) {
|
||||||
|
if (options.credentials === true) {
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Allow-Credentials',
|
||||||
|
value: 'true'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureAllowedHeaders(options, req) {
|
||||||
|
var allowedHeaders = options.allowedHeaders || options.headers;
|
||||||
|
var headers = [];
|
||||||
|
|
||||||
|
if (!allowedHeaders) {
|
||||||
|
allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
|
||||||
|
headers.push([{
|
||||||
|
key: 'Vary',
|
||||||
|
value: 'Access-Control-Request-Headers'
|
||||||
|
}]);
|
||||||
|
} else if (allowedHeaders.join) {
|
||||||
|
allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string
|
||||||
|
}
|
||||||
|
if (allowedHeaders && allowedHeaders.length) {
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Headers',
|
||||||
|
value: allowedHeaders
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureExposedHeaders(options) {
|
||||||
|
var headers = options.exposedHeaders;
|
||||||
|
if (!headers) {
|
||||||
|
return null;
|
||||||
|
} else if (headers.join) {
|
||||||
|
headers = headers.join(','); // .headers is an array, so turn it into a string
|
||||||
|
}
|
||||||
|
if (headers && headers.length) {
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Expose-Headers',
|
||||||
|
value: headers
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureMaxAge(options) {
|
||||||
|
var maxAge = (typeof options.maxAge === 'number' || options.maxAge) && options.maxAge.toString()
|
||||||
|
if (maxAge && maxAge.length) {
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Max-Age',
|
||||||
|
value: maxAge
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyHeaders(headers, res) {
|
||||||
|
for (var i = 0, n = headers.length; i < n; i++) {
|
||||||
|
var header = headers[i];
|
||||||
|
if (header) {
|
||||||
|
if (Array.isArray(header)) {
|
||||||
|
applyHeaders(header, res);
|
||||||
|
} else if (header.key === 'Vary' && header.value) {
|
||||||
|
vary(res, header.value);
|
||||||
|
} else if (header.value) {
|
||||||
|
res.setHeader(header.key, header.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cors(options, req, res, next) {
|
||||||
|
var headers = [],
|
||||||
|
method = req.method && req.method.toUpperCase && req.method.toUpperCase();
|
||||||
|
|
||||||
|
if (method === 'OPTIONS') {
|
||||||
|
// preflight
|
||||||
|
headers.push(configureOrigin(options, req));
|
||||||
|
headers.push(configureCredentials(options, req));
|
||||||
|
headers.push(configureMethods(options, req));
|
||||||
|
headers.push(configureAllowedHeaders(options, req));
|
||||||
|
headers.push(configureMaxAge(options, req));
|
||||||
|
headers.push(configureExposedHeaders(options, req));
|
||||||
|
applyHeaders(headers, res);
|
||||||
|
|
||||||
|
if (options.preflightContinue) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
// Safari (and potentially other browsers) need content-length 0,
|
||||||
|
// for 204 or they just hang waiting for a body
|
||||||
|
res.statusCode = options.optionsSuccessStatus;
|
||||||
|
res.setHeader('Content-Length', '0');
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// actual response
|
||||||
|
headers.push(configureOrigin(options, req));
|
||||||
|
headers.push(configureCredentials(options, req));
|
||||||
|
headers.push(configureExposedHeaders(options, req));
|
||||||
|
applyHeaders(headers, res);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function middlewareWrapper(o) {
|
||||||
|
// if options are static (either via defaults or custom options passed in), wrap in a function
|
||||||
|
var optionsCallback = null;
|
||||||
|
if (typeof o === 'function') {
|
||||||
|
optionsCallback = o;
|
||||||
|
} else {
|
||||||
|
optionsCallback = function (req, cb) {
|
||||||
|
cb(null, o);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return function corsMiddleware(req, res, next) {
|
||||||
|
optionsCallback(req, function (err, options) {
|
||||||
|
if (err) {
|
||||||
|
next(err);
|
||||||
|
} else {
|
||||||
|
var corsOptions = assign({}, defaults, options);
|
||||||
|
var originCallback = null;
|
||||||
|
if (corsOptions.origin && typeof corsOptions.origin === 'function') {
|
||||||
|
originCallback = corsOptions.origin;
|
||||||
|
} else if (corsOptions.origin) {
|
||||||
|
originCallback = function (origin, cb) {
|
||||||
|
cb(null, corsOptions.origin);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originCallback) {
|
||||||
|
originCallback(req.headers.origin, function (err2, origin) {
|
||||||
|
if (err2 || !origin) {
|
||||||
|
next(err2);
|
||||||
|
} else {
|
||||||
|
corsOptions.origin = origin;
|
||||||
|
cors(corsOptions, req, res, next);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// can pass either an options hash, an options delegate, or nothing
|
||||||
|
module.exports = middlewareWrapper;
|
||||||
|
|
||||||
|
}());
|
41
node_modules/cors/package.json
generated
vendored
Normal file
41
node_modules/cors/package.json
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"name": "cors",
|
||||||
|
"description": "Node.js CORS middleware",
|
||||||
|
"version": "2.8.5",
|
||||||
|
"author": "Troy Goode <troygoode@gmail.com> (https://github.com/troygoode/)",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"cors",
|
||||||
|
"express",
|
||||||
|
"connect",
|
||||||
|
"middleware"
|
||||||
|
],
|
||||||
|
"repository": "expressjs/cors",
|
||||||
|
"main": "./lib/index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"object-assign": "^4",
|
||||||
|
"vary": "^1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"after": "0.8.2",
|
||||||
|
"eslint": "2.13.1",
|
||||||
|
"express": "4.16.3",
|
||||||
|
"mocha": "5.2.0",
|
||||||
|
"nyc": "13.1.0",
|
||||||
|
"supertest": "3.3.0"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib/index.js",
|
||||||
|
"CONTRIBUTING.md",
|
||||||
|
"HISTORY.md",
|
||||||
|
"LICENSE",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "npm run lint && nyc --reporter=html --reporter=text mocha --require test/support/env",
|
||||||
|
"lint": "eslint lib test"
|
||||||
|
}
|
||||||
|
}
|
90
node_modules/object-assign/index.js
generated
vendored
Normal file
90
node_modules/object-assign/index.js
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
object-assign
|
||||||
|
(c) Sindre Sorhus
|
||||||
|
@license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
/* eslint-disable no-unused-vars */
|
||||||
|
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
||||||
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||||
|
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
|
||||||
|
|
||||||
|
function toObject(val) {
|
||||||
|
if (val === null || val === undefined) {
|
||||||
|
throw new TypeError('Object.assign cannot be called with null or undefined');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldUseNative() {
|
||||||
|
try {
|
||||||
|
if (!Object.assign) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect buggy property enumeration order in older V8 versions.
|
||||||
|
|
||||||
|
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
|
||||||
|
var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
|
||||||
|
test1[5] = 'de';
|
||||||
|
if (Object.getOwnPropertyNames(test1)[0] === '5') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
||||||
|
var test2 = {};
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
test2['_' + String.fromCharCode(i)] = i;
|
||||||
|
}
|
||||||
|
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
|
||||||
|
return test2[n];
|
||||||
|
});
|
||||||
|
if (order2.join('') !== '0123456789') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
||||||
|
var test3 = {};
|
||||||
|
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
|
||||||
|
test3[letter] = letter;
|
||||||
|
});
|
||||||
|
if (Object.keys(Object.assign({}, test3)).join('') !==
|
||||||
|
'abcdefghijklmnopqrst') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
// We don't expect any of the above to throw, but better to be safe.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = shouldUseNative() ? Object.assign : function (target, source) {
|
||||||
|
var from;
|
||||||
|
var to = toObject(target);
|
||||||
|
var symbols;
|
||||||
|
|
||||||
|
for (var s = 1; s < arguments.length; s++) {
|
||||||
|
from = Object(arguments[s]);
|
||||||
|
|
||||||
|
for (var key in from) {
|
||||||
|
if (hasOwnProperty.call(from, key)) {
|
||||||
|
to[key] = from[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getOwnPropertySymbols) {
|
||||||
|
symbols = getOwnPropertySymbols(from);
|
||||||
|
for (var i = 0; i < symbols.length; i++) {
|
||||||
|
if (propIsEnumerable.call(from, symbols[i])) {
|
||||||
|
to[symbols[i]] = from[symbols[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return to;
|
||||||
|
};
|
21
node_modules/object-assign/license
generated
vendored
Normal file
21
node_modules/object-assign/license
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
42
node_modules/object-assign/package.json
generated
vendored
Normal file
42
node_modules/object-assign/package.json
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"name": "object-assign",
|
||||||
|
"version": "4.1.1",
|
||||||
|
"description": "ES2015 `Object.assign()` ponyfill",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "sindresorhus/object-assign",
|
||||||
|
"author": {
|
||||||
|
"name": "Sindre Sorhus",
|
||||||
|
"email": "sindresorhus@gmail.com",
|
||||||
|
"url": "sindresorhus.com"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "xo && ava",
|
||||||
|
"bench": "matcha bench.js"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"object",
|
||||||
|
"assign",
|
||||||
|
"extend",
|
||||||
|
"properties",
|
||||||
|
"es2015",
|
||||||
|
"ecmascript",
|
||||||
|
"harmony",
|
||||||
|
"ponyfill",
|
||||||
|
"prollyfill",
|
||||||
|
"polyfill",
|
||||||
|
"shim",
|
||||||
|
"browser"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"ava": "^0.16.0",
|
||||||
|
"lodash": "^4.16.4",
|
||||||
|
"matcha": "^0.7.0",
|
||||||
|
"xo": "^0.16.0"
|
||||||
|
}
|
||||||
|
}
|
61
node_modules/object-assign/readme.md
generated
vendored
Normal file
61
node_modules/object-assign/readme.md
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
# object-assign [](https://travis-ci.org/sindresorhus/object-assign)
|
||||||
|
|
||||||
|
> ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com)
|
||||||
|
|
||||||
|
|
||||||
|
## Use the built-in
|
||||||
|
|
||||||
|
Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari),
|
||||||
|
support `Object.assign()` :tada:. If you target only those environments, then by all
|
||||||
|
means, use `Object.assign()` instead of this package.
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install --save object-assign
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
const objectAssign = require('object-assign');
|
||||||
|
|
||||||
|
objectAssign({foo: 0}, {bar: 1});
|
||||||
|
//=> {foo: 0, bar: 1}
|
||||||
|
|
||||||
|
// multiple sources
|
||||||
|
objectAssign({foo: 0}, {bar: 1}, {baz: 2});
|
||||||
|
//=> {foo: 0, bar: 1, baz: 2}
|
||||||
|
|
||||||
|
// overwrites equal keys
|
||||||
|
objectAssign({foo: 0}, {foo: 1}, {foo: 2});
|
||||||
|
//=> {foo: 2}
|
||||||
|
|
||||||
|
// ignores null and undefined sources
|
||||||
|
objectAssign({foo: 0}, null, {bar: 1}, undefined);
|
||||||
|
//=> {foo: 0, bar: 1}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### objectAssign(target, [source, ...])
|
||||||
|
|
||||||
|
Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones.
|
||||||
|
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign)
|
||||||
|
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()`
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
23
package-lock.json
generated
23
package-lock.json
generated
|
@ -9,6 +9,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"cors": "^2.8.5",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
"nodemailer": "^6.10.0"
|
"nodemailer": "^6.10.0"
|
||||||
|
@ -1874,6 +1875,19 @@
|
||||||
"node": ">=6.6.0"
|
"node": ">=6.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cors": {
|
||||||
|
"version": "2.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||||
|
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"object-assign": "^4",
|
||||||
|
"vary": "^1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/corser": {
|
"node_modules/corser": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
|
||||||
|
@ -3877,6 +3891,15 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/object-assign": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-inspect": {
|
"node_modules/object-inspect": {
|
||||||
"version": "1.13.4",
|
"version": "1.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
"typescript": "^5.8.2"
|
"typescript": "^5.8.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"cors": "^2.8.5",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
"nodemailer": "^6.10.0"
|
"nodemailer": "^6.10.0"
|
||||||
|
|
Loading…
Reference in a new issue