diff --git a/.glitch-assets b/.glitch-assets
new file mode 100644
index 00000000..d4da864d
--- /dev/null
+++ b/.glitch-assets
@@ -0,0 +1,7 @@
+{"name":"drag-in-files.svg","date":"2016-10-22T16:17:49.954Z","url":"https://cdn.hyperdev.com/drag-in-files.svg","type":"image/svg","size":7646,"imageWidth":276,"imageHeight":276,"thumbnail":"https://cdn.hyperdev.com/drag-in-files.svg","thumbnailWidth":276,"thumbnailHeight":276,"dominantColor":"rgb(102, 153, 205)","uuid":"adSBq97hhhpFNUna"}
+{"name":"click-me.svg","date":"2016-10-23T16:17:49.954Z","url":"https://cdn.hyperdev.com/click-me.svg","type":"image/svg","size":7116,"imageWidth":276,"imageHeight":276,"thumbnail":"https://cdn.hyperdev.com/click-me.svg","thumbnailWidth":276,"thumbnailHeight":276,"dominantColor":"rgb(243, 185, 186)","uuid":"adSBq97hhhpFNUnb"}
+{"name":"paste-me.svg","date":"2016-10-24T16:17:49.954Z","url":"https://cdn.hyperdev.com/paste-me.svg","type":"image/svg","size":7242,"imageWidth":276,"imageHeight":276,"thumbnail":"https://cdn.hyperdev.com/paste-me.svg","thumbnailWidth":276,"thumbnailHeight":276,"dominantColor":"rgb(42, 179, 185)","uuid":"adSBq97hhhpFNUnc"}
+{"uuid":"adSBq97hhhpFNUna","deleted":true}
+{"uuid":"adSBq97hhhpFNUnb","deleted":true}
+{"uuid":"adSBq97hhhpFNUnc","deleted":true}
+{"name":"observer.mp3","date":"2021-10-01T05:55:14.870Z","url":"https://cdn.glitch.com/ae86c621-1098-461e-a007-91cc0028fe6c%2Fobserver.mp3","type":"audio/mpeg","size":2672430,"thumbnail":"https://cdn.glitch.com/ae86c621-1098-461e-a007-91cc0028fe6c%2Fthumbnails%2Fobserver.mp3","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"xazoFV4X5S34izaE"}
diff --git a/README.md b/README.md
index 3ae10a92..bb6e2e54 100644
--- a/README.md
+++ b/README.md
@@ -1,61 +1,5 @@
-Assignment 4 - Creative Coding: Interactive Multimedia Experiences
-===
+Audio Visualizer
-Due: October 4th, by 11:59 AM.
+hosting link: https://a4-praisex.glitch.me/
-For this assignment we will focus on client-side development using popular audio/graphics/visualization technologies. The goal of this assignment is to refine our JavaScript knowledge while exploring the multimedia capabilities of the browser.
-
-[WebAudio / Canvas / Three Tutorial](https://github.com/cs4241-21a/cs4241-21a.github.io/blob/main/webaudio_canvas_three.md)
-[SVG + D3 tutorial](https://github.com/cs4241-21a/cs4241-21a.github.io/blob/main/using_svg_and_d3.md)
-
-Baseline Requirements
----
-
-Your application is required to implement the following functionalities:
-
-- A server created using Express. This server can be as simple as needed.
-- A client-side interactive experience using at least one of the following web technologies frameworks.
- - [Three.js](https://threejs.org/): A library for 3D graphics / VR experiences
- - [D3.js](https://d3js.org): A library that is primarily used for interactive data visualizations
- - [Canvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API): A 2D raster drawing API included in all modern browsers
- - [SVG](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API): A 2D vector drawing framework that enables shapes to be defined via XML.
- - [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API): An API for audio synthesis, analysis, processing, and file playback.
-- A user interface for interaction with your project, which must expose at least four parameters for user control. [tweakpane](https://cocopon.github.io/tweakpane/) is highly recommended for this, but you can also use regular HTML ` ` tags (the `range` type is useful to create sliders). You might also explore interaction by tracking mouse movement via the `window.onmousemove` event handler in tandem with the `event.clientX` and `event.clientY` properties. Consider using the [Pointer Events API](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events) to ensure that that both mouse and touch events will both be supported in your app.
-- Your application should display basic documentation for the user interface when the application first loads.
-
-The interactive experience should possess a reasonable level of complexity. Some examples:
-### Three.js
-- A generative algorithm creates simple agents that move through a virtual world. Your interface controls the behavior / appearance of these agents.
-- A simple 3D game... you really want this to be a simple as possible or it will be outside the scope of this assignment.
-- An 3D audio visualization of a song of your choosing. User interaction should control aspects of the visualization.
-### Canvas
-- Implement a generative algorithm such as [Conway's Game of Life](https://bitstorm.org/gameoflife/) (or 1D cellular automata) and provide interactive controls. Note that the Game of Life has been created by 100s of people using ; we'll be checking to ensure that your implementation is not a copy of these.
-- Design a 2D audio visualizer of a song of your choosing. User interaction should control visual aspects of the experience.
-### Web Audio API
-- Create a screen-based musical instrument using the Web Audio API. You can use projects such as [Interface.js](http://charlie-roberts.com/interface/) or [Nexus UI](https://nexus-js.github.io/ui/api/#Piano) to provide common musical interface elements, or use dat.GUI in combination with mouse/touch events (use the Pointer Events API). Your GUI should enable users to control aspects of sound synthesis. If you want to use higher-level instruments instead of the raw WebAudio API sounds, consider trying the instruments provided by [Tone.js]() or [Gibber](https://github.com/charlieroberts/gibber.audio.lib).
-### D3.js
-- Create visualizations using the datasets found at [Awesome JSON Datasets](https://github.com/jdorfman/Awesome-JSON-Datasets). Experiment with providing different visualizations of the same data set, and providing users interactive control over visualization parameters and/or data filtering. Alternatively, create a single visualization with using one of the more complicated techniques shown at [d3js.org](d3js.org) and provide meaningful points of interaction for users.
-
-Deliverables
----
-
-Do the following to complete this assignment:
-
-1. Implement your project with the above requirements.
-3. Test your project to make sure that when someone goes to your main page on Glitch/Heroku/etc., it displays correctly.
-4. Ensure that your project has the proper naming scheme `a4-firstname-lastname` so we can find it.
-5. Fork this repository and modify the README to the specifications below. *NOTE: If you don't use Glitch for hosting (where we can see the files) then you must include all project files that you author in your repo for this assignment*.
-6. Create and submit a Pull Request to the original repo. Name the pull request using the following template: `a4-firstname-lastname`.
-
-Sample Readme (delete the above when you're ready to submit, and modify the below so with your links and descriptions)
----
-
-## Your Web Application Title
-
-your hosting link e.g. http://a4-charlieroberts.glitch.me
-
-Include a very brief summary of your project here. Images are encouraged when needed, along with concise, high-level text. Be sure to include:
-
-- the goal of the application
-- challenges you faced in realizing the application
-- the instructions you present in the website should be clear enough to use the application, but if you feel any need to provide additional instructions please do so here.
+the goal of this application was to use three.js to make an audio visualiser of a song. Three.js is very complicated so I ran into a lot of errors with syncing the audio up with the 3d object, as well as having tweakpane edit attributes of the object. Also once the audio was synced with the music there wasnt much I could do, so it only rotates.
diff --git a/assets/observer.mp3 b/assets/observer.mp3
new file mode 100644
index 00000000..055d13ae
Binary files /dev/null and b/assets/observer.mp3 differ
diff --git a/node_modules/cors/CONTRIBUTING.md b/node_modules/cors/CONTRIBUTING.md
new file mode 100644
index 00000000..591b09a1
--- /dev/null
+++ b/node_modules/cors/CONTRIBUTING.md
@@ -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)
diff --git a/node_modules/cors/HISTORY.md b/node_modules/cors/HISTORY.md
new file mode 100644
index 00000000..5762bce9
--- /dev/null
+++ b/node_modules/cors/HISTORY.md
@@ -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 "*"
diff --git a/node_modules/cors/LICENSE b/node_modules/cors/LICENSE
new file mode 100644
index 00000000..fd10c843
--- /dev/null
+++ b/node_modules/cors/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2013 Troy Goode
+
+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.
diff --git a/node_modules/cors/README.md b/node_modules/cors/README.md
new file mode 100644
index 00000000..732b847e
--- /dev/null
+++ b/node_modules/cors/README.md
@@ -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
diff --git a/node_modules/cors/lib/index.js b/node_modules/cors/lib/index.js
new file mode 100644
index 00000000..5475aecd
--- /dev/null
+++ b/node_modules/cors/lib/index.js
@@ -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;
+
+}());
diff --git a/node_modules/cors/package.json b/node_modules/cors/package.json
new file mode 100644
index 00000000..386160ca
--- /dev/null
+++ b/node_modules/cors/package.json
@@ -0,0 +1,78 @@
+{
+ "_from": "cors",
+ "_id": "cors@2.8.5",
+ "_inBundle": false,
+ "_integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "_location": "/cors",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "tag",
+ "registry": true,
+ "raw": "cors",
+ "name": "cors",
+ "escapedName": "cors",
+ "rawSpec": "",
+ "saveSpec": null,
+ "fetchSpec": "latest"
+ },
+ "_requiredBy": [
+ "#USER",
+ "/"
+ ],
+ "_resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+ "_shasum": "eac11da51592dd86b9f06f6e7ac293b3df875d29",
+ "_spec": "cors",
+ "_where": "C:\\Users\\reeli\\OneDrive\\Desktop\\a4-creative-coding",
+ "author": {
+ "name": "Troy Goode",
+ "email": "troygoode@gmail.com",
+ "url": "https://github.com/troygoode/"
+ },
+ "bugs": {
+ "url": "https://github.com/expressjs/cors/issues"
+ },
+ "bundleDependencies": false,
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "deprecated": false,
+ "description": "Node.js CORS middleware",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "files": [
+ "lib/index.js",
+ "CONTRIBUTING.md",
+ "HISTORY.md",
+ "LICENSE",
+ "README.md"
+ ],
+ "homepage": "https://github.com/expressjs/cors#readme",
+ "keywords": [
+ "cors",
+ "express",
+ "connect",
+ "middleware"
+ ],
+ "license": "MIT",
+ "main": "./lib/index.js",
+ "name": "cors",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/expressjs/cors.git"
+ },
+ "scripts": {
+ "lint": "eslint lib test",
+ "test": "npm run lint && nyc --reporter=html --reporter=text mocha --require test/support/env"
+ },
+ "version": "2.8.5"
+}
diff --git a/node_modules/express/History.md b/node_modules/express/History.md
new file mode 100644
index 00000000..6e62a6dd
--- /dev/null
+++ b/node_modules/express/History.md
@@ -0,0 +1,3477 @@
+4.17.1 / 2019-05-25
+===================
+
+ * Revert "Improve error message for `null`/`undefined` to `res.status`"
+
+4.17.0 / 2019-05-16
+===================
+
+ * Add `express.raw` to parse bodies into `Buffer`
+ * Add `express.text` to parse bodies into string
+ * Improve error message for non-strings to `res.sendFile`
+ * Improve error message for `null`/`undefined` to `res.status`
+ * Support multiple hosts in `X-Forwarded-Host`
+ * deps: accepts@~1.3.7
+ * deps: body-parser@1.19.0
+ - Add encoding MIK
+ - Add petabyte (`pb`) support
+ - Fix parsing array brackets after index
+ - deps: bytes@3.1.0
+ - deps: http-errors@1.7.2
+ - deps: iconv-lite@0.4.24
+ - deps: qs@6.7.0
+ - deps: raw-body@2.4.0
+ - deps: type-is@~1.6.17
+ * deps: content-disposition@0.5.3
+ * deps: cookie@0.4.0
+ - Add `SameSite=None` support
+ * deps: finalhandler@~1.1.2
+ - Set stricter `Content-Security-Policy` header
+ - deps: parseurl@~1.3.3
+ - deps: statuses@~1.5.0
+ * deps: parseurl@~1.3.3
+ * deps: proxy-addr@~2.0.5
+ - deps: ipaddr.js@1.9.0
+ * deps: qs@6.7.0
+ - Fix parsing array brackets after index
+ * deps: range-parser@~1.2.1
+ * deps: send@0.17.1
+ - Set stricter CSP header in redirect & error responses
+ - deps: http-errors@~1.7.2
+ - deps: mime@1.6.0
+ - deps: ms@2.1.1
+ - deps: range-parser@~1.2.1
+ - deps: statuses@~1.5.0
+ - perf: remove redundant `path.normalize` call
+ * deps: serve-static@1.14.1
+ - Set stricter CSP header in redirect response
+ - deps: parseurl@~1.3.3
+ - deps: send@0.17.1
+ * deps: setprototypeof@1.1.1
+ * deps: statuses@~1.5.0
+ - Add `103 Early Hints`
+ * deps: type-is@~1.6.18
+ - deps: mime-types@~2.1.24
+ - perf: prevent internal `throw` on invalid type
+
+4.16.4 / 2018-10-10
+===================
+
+ * Fix issue where `"Request aborted"` may be logged in `res.sendfile`
+ * Fix JSDoc for `Router` constructor
+ * deps: body-parser@1.18.3
+ - Fix deprecation warnings on Node.js 10+
+ - Fix stack trace for strict json parse error
+ - deps: depd@~1.1.2
+ - deps: http-errors@~1.6.3
+ - deps: iconv-lite@0.4.23
+ - deps: qs@6.5.2
+ - deps: raw-body@2.3.3
+ - deps: type-is@~1.6.16
+ * deps: proxy-addr@~2.0.4
+ - deps: ipaddr.js@1.8.0
+ * deps: qs@6.5.2
+ * deps: safe-buffer@5.1.2
+
+4.16.3 / 2018-03-12
+===================
+
+ * deps: accepts@~1.3.5
+ - deps: mime-types@~2.1.18
+ * deps: depd@~1.1.2
+ - perf: remove argument reassignment
+ * deps: encodeurl@~1.0.2
+ - Fix encoding `%` as last character
+ * deps: finalhandler@1.1.1
+ - Fix 404 output for bad / missing pathnames
+ - deps: encodeurl@~1.0.2
+ - deps: statuses@~1.4.0
+ * deps: proxy-addr@~2.0.3
+ - deps: ipaddr.js@1.6.0
+ * deps: send@0.16.2
+ - Fix incorrect end tag in default error & redirects
+ - deps: depd@~1.1.2
+ - deps: encodeurl@~1.0.2
+ - deps: statuses@~1.4.0
+ * deps: serve-static@1.13.2
+ - Fix incorrect end tag in redirects
+ - deps: encodeurl@~1.0.2
+ - deps: send@0.16.2
+ * deps: statuses@~1.4.0
+ * deps: type-is@~1.6.16
+ - deps: mime-types@~2.1.18
+
+4.16.2 / 2017-10-09
+===================
+
+ * Fix `TypeError` in `res.send` when given `Buffer` and `ETag` header set
+ * perf: skip parsing of entire `X-Forwarded-Proto` header
+
+4.16.1 / 2017-09-29
+===================
+
+ * deps: send@0.16.1
+ * deps: serve-static@1.13.1
+ - Fix regression when `root` is incorrectly set to a file
+ - deps: send@0.16.1
+
+4.16.0 / 2017-09-28
+===================
+
+ * Add `"json escape"` setting for `res.json` and `res.jsonp`
+ * Add `express.json` and `express.urlencoded` to parse bodies
+ * Add `options` argument to `res.download`
+ * Improve error message when autoloading invalid view engine
+ * Improve error messages when non-function provided as middleware
+ * Skip `Buffer` encoding when not generating ETag for small response
+ * Use `safe-buffer` for improved Buffer API
+ * deps: accepts@~1.3.4
+ - deps: mime-types@~2.1.16
+ * deps: content-type@~1.0.4
+ - perf: remove argument reassignment
+ - perf: skip parameter parsing when no parameters
+ * deps: etag@~1.8.1
+ - perf: replace regular expression with substring
+ * deps: finalhandler@1.1.0
+ - Use `res.headersSent` when available
+ * deps: parseurl@~1.3.2
+ - perf: reduce overhead for full URLs
+ - perf: unroll the "fast-path" `RegExp`
+ * deps: proxy-addr@~2.0.2
+ - Fix trimming leading / trailing OWS in `X-Forwarded-For`
+ - deps: forwarded@~0.1.2
+ - deps: ipaddr.js@1.5.2
+ - perf: reduce overhead when no `X-Forwarded-For` header
+ * deps: qs@6.5.1
+ - Fix parsing & compacting very deep objects
+ * deps: send@0.16.0
+ - Add 70 new types for file extensions
+ - Add `immutable` option
+ - Fix missing `