├── .DS_Store
├── .github
├── FUNDING.yml
└── workflows
│ └── codeql.yml
├── .gitignore
├── .npmignore
├── LICENSE.md
├── README.md
├── SECURITY.md
├── build.js
├── config.json
├── ecosystem.config.js
├── examples
├── .DS_Store
├── OCAPI-Proxy-Setup.png
├── OCAPI-Proxy-Tester.png
├── OCAPI-Proxy.postman_collection.json
├── diagram-middleware.png
├── pm2-example.png
└── postman-example.png
├── html
└── index.html
├── libProxy.js
├── ocapi-proxy.js
├── package-lock.json
├── package.json
└── sample-config.json
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnfacey/ocapi-proxy/584afea07f99151cf9e247fe4ae7f70e9622b35d/.DS_Store
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: johnfacey
4 | ko_fi: johnfacey
5 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ "master" ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ "master" ]
20 | schedule:
21 | - cron: '43 11 * * 6'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'javascript' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Use only 'java' to analyze code written in Java, Kotlin or both
38 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
39 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
40 |
41 | steps:
42 | - name: Checkout repository
43 | uses: actions/checkout@v3
44 |
45 | # Initializes the CodeQL tools for scanning.
46 | - name: Initialize CodeQL
47 | uses: github/codeql-action/init@v2
48 | with:
49 | languages: ${{ matrix.language }}
50 | # If you wish to specify custom queries, you can do so here or in a config file.
51 | # By default, queries listed here will override any specified in a config file.
52 | # Prefix the list here with "+" to use these queries and those in the config file.
53 |
54 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
55 | # queries: security-extended,security-and-quality
56 |
57 |
58 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
59 | # If this step fails, then you should remove it and run the build manually (see below)
60 | - name: Autobuild
61 | uses: github/codeql-action/autobuild@v2
62 |
63 | # ℹ️ Command-line programs to run using the OS shell.
64 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
65 |
66 | # If the Autobuild fails above, remove it and uncomment the following three lines.
67 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
68 |
69 | # - run: |
70 | # echo "Run, Build Application using script"
71 | # ./location_of_script_within_repo/buildscript.sh
72 |
73 | - name: Perform CodeQL Analysis
74 | uses: github/codeql-action/analyze@v2
75 | with:
76 | category: "/language:${{matrix.language}}"
77 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | config.json
2 | node_modules
3 | .vscode
4 | logs
5 | local.json
6 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | local.json
2 | .*
3 | *.swp
4 | *~
5 | *.iml
6 | .*.haste_cache.*
7 | .DS_Store
8 | npm-debug.log
9 | node_modules
10 | scripts
11 | src
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | This software is released under the MIT license:
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software is furnished to do so,
8 | subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Salesforce Commerce Cloud OCAPI Proxy
2 |  
3 |
4 |
5 | [](https://nodei.co/npm/ocapi-proxy/)
6 |
7 | This project will serve as a local Node.js based Proxy server that will forward requests to an Salesforce Commerce Cloud OCAPI instance.
8 | This can be used for purposes such as testing 3rd party apps using OCAPI as well as integration for mobile/browser apps.
9 | The configuration of site_id, client_id are configured at the proxy level rather than in the app directly.
10 |
11 |
12 | ## Welcome:
13 |
14 | 
15 |
16 |
17 | ## Getting Started
18 |
19 | Edit the config.json to match the server you are using.
20 | If you are using a service such as https://ngrok.com you may need to add the url to your Business Manager allowed origins.
21 |
22 | **NOTE:** This package only forwards OCAPI requests from one point to another. The main purpose is for routing data around CORS and is typically useful for Mobile Applications. x-dw-client-id as a header attribute must be used instead of client_id as a url parameter.
23 |
24 | ## Updates
25 |
26 | Updated UI Interface with Request and Response sections.
27 | Removed Autolaunch of UI.
28 | Cors changes to express have been added.
29 | UI can be compltely disabled in config.json as well as Google Anaylrics by making the value ""
30 | Errors will now return a json format if the SFCC instance can be reached.
31 | This will resolve issues with Postman not getting back a json result and aid in debugging.
32 |
33 | ## Prerequisites
34 | ```
35 | Required:
36 | Node.js
37 | Salesforce Commerce Cloud Sandbox - Configured for OCAPI
38 |
39 | Optional:
40 | Postman or another rest API tool.
41 | ngrok - If you need to get a public url to your localhost
42 | ```
43 | ## Installing
44 | ```
45 | npm install ocapi-proxy
46 | ```
47 |
48 | ## Running
49 |
50 | From the command line:
51 | ```
52 | npm start or node ocapi-proxy.js
53 |
54 |
55 | ```
56 |
57 | Example:
58 | ```
59 | npm start ocapi-proxy.js
60 | ```
61 | 
62 |
63 | You will need a config.json (one will be generated on first launch)
64 | To edit the port, domain, etc.. modify the config.json file.
65 | server: your Salesforce Commerce Cloud server (currently all calls are https)
66 | site_id: SFCC Site ID
67 | version: SFCC OCAPI Version
68 | port_ui: Port for browser testing requests.
69 | port: Port that proxy listens for requests.
70 |
71 | Example:
72 | ```
73 | {
74 | "server": "yoursandbox.demandware.net",
75 | "site_id": "SiteGenesis",
76 | "version": "v23_2",
77 | "client_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
78 | "port": 8080,
79 | "port_ui": 80,
80 | "UA": "UA-XXXX-XXXX", //Optional: Universal Analytics ID
81 | "rate_limit": "", //Optional: 15 minutes default
82 | "rate_max": "", //Optional: number of calls that can be made
83 | "windowMs": limit, // 15 minutes or config file entry
84 | "max": max, // Limit each IP to 100 requests per `window` (here, per 15 minutes)
85 | }
86 |
87 | ```
88 |
89 | ## OCAPI Commands
90 |
91 | You can send OCAPI commands to your local proxy.
92 | Specify the host to make the call.
93 | Send the endpoint as the **callurl** header attribute.
94 | All other attributes can be sent similar to a direct OCAPI call.
95 | This ensures that the Proxy communicates with OCAPI as middleware.
96 |
97 | Example:
98 |
99 | 
100 |
101 | ## Deployment/Development
102 |
103 | This is currently a work in progress. Please report any issues you find.
104 | Latest: Fixes to logging added dates to log files.
105 | Updated contact info for [Github](https://github.com/johnfacey) and [Twitter](https://twitter.com/johnfacey).
106 |
107 | ## OCAPI Output Modifications
108 |
109 | Currently **Authorization** and **ETag** headers are returned into the body from the output proxy rather than in the header. These are not needed in 19.X+
110 |
111 | ## Universal Analytics
112 |
113 | The Proxy will communicate with Google Universal Analytics if a "UA" attribute is found in the config file. You may leave this attribute blank or remove it from the config. Currently all UA requests are send as a event tag with the url of the Commerce Cloud Instance.
114 |
115 | ## Proxy Testing UI
116 |
117 | 
118 |
119 | NEW Proxy UI for testing from a web browser interface. Config attribute "port_ui" added to config.json
120 |
121 | ## Files / Links
122 | * [**Postman Collection**](./examples/OCAPI-Proxy.postman_collection.json)
123 | * [**Example: config.json**](./sample-config.json)
124 |
125 | ## File Structure
126 | ```
127 | Within the download you'll find the following directories and files:
128 | |-- Root
129 | |-- .gitignore
130 | |-- .npmignore
131 | |-- build.js
132 | |-- config.json
133 | |-- ecosystem.config.js
134 | |-- libProxy.js
135 | |-- LICENSE.md
136 | |-- ocapi-proxy.js
137 | |-- package-lock.json
138 | |-- package.json
139 | |-- README.md
140 | |-- sample-config.json
141 | |-- SECURITY.md
142 | |-- .vscode
143 | | |-- launch.json
144 | |-- examples
145 | | |-- diagram-middleware.png
146 | | |-- OCAPI-Proxy-Tester.png
147 | | |-- OCAPI-Proxy.postman_collection.json
148 | | |-- pm2-example.png
149 | | |-- postman-example.png
150 | |-- html
151 | | |-- index.html
152 | |-- logs
153 | ```
154 |
155 | ## Logging
156 |
157 | The Proxy will generate logs where the current proxy has been executed in the logs directory.
158 |
159 | ## Built With
160 |
161 | * [**Node.js**](https://nodejs.org)
162 | * [**Express**](https://expressjs.com) - Minimalist Web Framework for Node.js
163 | * [**jsonfile**](https://www.npmjs.com/package/jsonfile) - read/write JSON files in Node.js
164 | * [**universal-analytics**](https://www.npmjs.com/package/universal-analytics) - Google Universal Analytics
165 | * [**open**](https://www.npmjs.com/package/open) - Open (NPM)
166 | * [**Mddir**](https://www.npmjs.com/package/mddir) - Mddir (NPM)
167 |
168 |
169 | ## Authors
170 |
171 | * **John Facey II** - *Lead*
172 | [](https://github.com/johnfacey)
173 | [](https://twitter.com/johnfacey)
174 | [](https://ko-fi.com/M4M13CMPP)
175 |
176 | ## License
177 |
178 | [](https://opensource.org/licenses/MIT)
179 |
180 | See the [LICENSE.md](LICENSE.md) file for details
181 |
182 | ## Acknowledgments
183 |
184 | * [**Salesforce Commerce Cloud**](https://www.salesforce.com/products/commerce-cloud/overview)
185 | * [**Node.js**](https://nodejs.org)
186 | * [**Visual Studio Code**](https://code.visualstudio.com)
187 | * [**ngrok**](https://ngrok.com)
188 | * [**jQuery**](https://jQuery.com)
189 | * [**Bootstrap**](https://getbootstrap.com)
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/build.js:
--------------------------------------------------------------------------------
1 | var request = require('request');
2 | var express = require('express');
3 | var bodyParser = require('body-parser');
4 | var jsonfile = require('jsonfile');
5 | var fs = require('fs');
6 | var file = './config.json';
7 |
8 | writeConfig = function () {
9 | var obj = {
10 | "server": "yoursandbox.demandware.net",
11 | "site_id": "SiteGenesis",
12 | "version": "v23_2",
13 | "client_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
14 | "port":8080,
15 | "port_ui": 80,
16 | "UA": "UA-XXXX-XXXX",
17 | "rate_limit": "",
18 | "rate_max": ""
19 | };
20 | jsonfile.writeFile(file, obj, function (err) {
21 | if (err != null) {
22 | console.error(err);
23 | }
24 | });
25 |
26 | console.log("Creating config.json");
27 | try {
28 | fs.mkdirSync("./logs");
29 | } catch (err) {
30 |
31 | }
32 | };
33 |
34 | writeConfig();
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "server":"development-na02-hbc.demandware.net",
3 | "site_id":"TheBay",
4 | "version":"v21_3",
5 | "client_id":"74e20e81-40f4-4ad2-bb8b-b2e77f410012",
6 | "port":8080,
7 | "port_ui": 80,
8 | "UA": "UA-XXXX-XXXX"
9 | }
10 |
--------------------------------------------------------------------------------
/ecosystem.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | apps : [{
3 | name: 'ocapi-proxy',
4 | script: 'ocapi-proxy.js',
5 |
6 | // Options reference: https://pm2.io/doc/en/runtime/reference/ecosystem-file/
7 | args: 'one two',
8 | instances: 1,
9 | autorestart: true,
10 | watch: false,
11 | max_memory_restart: '1G',
12 | env: {
13 | NODE_ENV: 'development'
14 | },
15 | env_production: {
16 | NODE_ENV: 'production'
17 | }
18 | }],
19 |
20 | deploy : {
21 | production : {
22 | user : 'node',
23 | host : '212.83.163.1',
24 | ref : 'origin/master',
25 | repo : 'git@github.com:repo.git',
26 | path : '/var/www/production',
27 | 'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production'
28 | }
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/examples/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnfacey/ocapi-proxy/584afea07f99151cf9e247fe4ae7f70e9622b35d/examples/.DS_Store
--------------------------------------------------------------------------------
/examples/OCAPI-Proxy-Setup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnfacey/ocapi-proxy/584afea07f99151cf9e247fe4ae7f70e9622b35d/examples/OCAPI-Proxy-Setup.png
--------------------------------------------------------------------------------
/examples/OCAPI-Proxy-Tester.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnfacey/ocapi-proxy/584afea07f99151cf9e247fe4ae7f70e9622b35d/examples/OCAPI-Proxy-Tester.png
--------------------------------------------------------------------------------
/examples/OCAPI-Proxy.postman_collection.json:
--------------------------------------------------------------------------------
1 | {
2 | "info": {
3 | "_postman_id": "b4cc8832-9d39-46b5-af22-cf61db921f03",
4 | "name": "OCAPI-Proxy",
5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
6 | },
7 | "item": [
8 | {
9 | "name": "Customer Auth ",
10 | "event": [
11 | {
12 | "listen": "test",
13 | "script": {
14 | "id": "48c03b10-7936-49d1-9251-fef4cd896343",
15 | "exec": [
16 | "var jsonData = JSON.parse(responseBody);",
17 | "postman.setEnvironmentVariable(\"Bearer\", postman.getResponseHeader('Authorization'));",
18 | "postman.setEnvironmentVariable(\"customer_id\",jsonData.customer_id);",
19 | "postman.setEnvironmentVariable(\"customer_no\",jsonData.customer_no);",
20 | "postman.setEnvironmentVariable(\"email\",jsonData.email);",
21 | "tests['Authorization: '+postman.getResponseHeader('Authorization')] = postman.getResponseHeader('Authorization');",
22 | ""
23 | ],
24 | "type": "text/javascript"
25 | }
26 | }
27 | ],
28 | "request": {
29 | "auth": {
30 | "type": "basic",
31 | "basic": [
32 | {
33 | "key": "password",
34 | "value": "XXXXXX",
35 | "type": "string"
36 | },
37 | {
38 | "key": "username",
39 | "value": "user@demandware.com",
40 | "type": "string"
41 | },
42 | {
43 | "key": "saveHelperData",
44 | "value": true,
45 | "type": "boolean"
46 | },
47 | {
48 | "key": "showPassword",
49 | "value": false,
50 | "type": "boolean"
51 | }
52 | ]
53 | },
54 | "method": "POST",
55 | "header": [
56 | {
57 | "key": "Content-Type",
58 | "value": "application/json"
59 | },
60 | {
61 | "warning": "This is a duplicate header and will be overridden by the Authorization header generated by Postman.",
62 | "key": "Authorization",
63 | "value": "Basic MzYyZjAxMDItNjU0Yy00ODFiLTk1MjktNzMyOGQ0YTU3MDhlOk16WXlaakF4TURJdE5qVTBZeTAwT0RGaUxUazFNamt0TnpNeU9HUTBZVFUzTURobE9nPT0=",
64 | "disabled": true
65 | },
66 | {
67 | "key": "x-dw-client-id",
68 | "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
69 | },
70 | {
71 | "key": "Origin",
72 | "value": "https://{{url}}",
73 | "disabled": true
74 | },
75 | {
76 | "key": "x-dw-client-id",
77 | "type": "text",
78 | "value": "5003458a-2365-4abe-8ade-25f46b582cf6",
79 | "disabled": true
80 | },
81 | {
82 | "key": "callurl",
83 | "value": "customers/auth",
84 | "type": "text"
85 | }
86 | ],
87 | "body": {
88 | "mode": "raw",
89 | "raw": "{ \"type\" : \"guest\"}"
90 | },
91 | "url": {
92 | "raw": "http://localhost:8080",
93 | "protocol": "http",
94 | "host": [
95 | "localhost"
96 | ],
97 | "port": "8080"
98 | }
99 | },
100 | "response": []
101 | }
102 | ]
103 | }
--------------------------------------------------------------------------------
/examples/diagram-middleware.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnfacey/ocapi-proxy/584afea07f99151cf9e247fe4ae7f70e9622b35d/examples/diagram-middleware.png
--------------------------------------------------------------------------------
/examples/pm2-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnfacey/ocapi-proxy/584afea07f99151cf9e247fe4ae7f70e9622b35d/examples/pm2-example.png
--------------------------------------------------------------------------------
/examples/postman-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnfacey/ocapi-proxy/584afea07f99151cf9e247fe4ae7f70e9622b35d/examples/postman-example.png
--------------------------------------------------------------------------------
/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
OCAPI Proxy Tester
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | Request
77 |
78 |
79 |
80 |
81 | Response
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/libProxy.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * OCAPI Proxy Constants
4 | */
5 | const request = require('request');
6 | const express = require('express');
7 | const bodyParser = require('body-parser');
8 | const jsonfile = require('jsonfile');
9 | const fs = require('fs');
10 | const ua = require('universal-analytics');
11 | const open = require('open');
12 | const cors = require('cors');
13 | const path = __dirname + '/html/';
14 | const app = express();
15 | const admin = express();
16 | const rateLimit = require('express-rate-limit');
17 | let limit = "";
18 | let max = "";
19 | /**
20 | * OCAPI Proxy Variables
21 | */
22 | let server = "";
23 | let site_id = "SiteGenesis";
24 | let version = "v22_4";
25 | let port = process.env.PORT || 8080;
26 | let adminPort = "";
27 | let UA = "";
28 | let rate_max = 0;
29 | let rate_limit = 0;
30 | let now = new Date();
31 | let loadUI = false;
32 | let logDate = now.getFullYear() + "-" + now.getDay() + "-" + now.getDate();
33 | let message = "";
34 | let logFileName = "./logs/ocapi-proxy-" + logDate + ".log";
35 |
36 | try {
37 | fs.mkdirSync("./logs");
38 | } catch (err) {
39 | console.log('Logs directory already exists');
40 | }
41 |
42 | writeLog = (logMessage) => {
43 | fs.appendFileSync(logFileName, logMessage + "\r\n", (err) => {
44 | if (err) throw err;
45 |
46 | });
47 | };
48 |
49 | var file = './config.json';
50 | try {
51 | if (process.argv[2]) {
52 | file = process.argv[2];
53 | }
54 | } catch (err) {
55 | file = './config.json';
56 | }
57 |
58 | message = "Loading config file: " + file;
59 | console.log(message);
60 | writeLog(message);
61 |
62 |
63 |
64 | readConfig = () => {
65 | try {
66 | if (fs.existsSync(file)) {
67 | //file exists --read file
68 | jsonfile.readFile(file, (err, obj) => {
69 | config = obj;
70 | if (config == undefined) { //file invalid
71 | message = "Update the config.json or use sample-config.json";
72 | console.log(message);
73 | writeLog(message);
74 | console.log("Exiting ocapi-proxy");
75 | return false;
76 | } else {
77 | port = process.env.PORT || config.port;
78 | adminPort = config.port_ui || "";
79 | site_id = config.site_id;
80 | server = config.server;
81 | version = config.version;
82 | client_id = config.client_id;
83 | if (config.UA != undefined && config.UA != "") {
84 | UA = config.UA;
85 | }
86 |
87 | if (config.rate_limit != undefined && config.rate_limit != "") {
88 | limit = config.rate_limit;
89 | } else {
90 | limit = 15 * 60 * 1000 // 15 minutes
91 | }
92 |
93 | if (config.rate_max != undefined && config.rate_max != "") {
94 | max = config.rate_max;
95 | } else {
96 | max = 100;
97 | }
98 |
99 | app.listen(port, () => {
100 | return console.log('OCAPI Proxy Port: ' + port);
101 | });
102 |
103 | if (adminPort != "") {
104 | admin.listen(adminPort, () => {
105 | var adminHost = 'http://localhost:' + adminPort;
106 | var message = "OCAPI UI: " + adminHost;
107 | writeLog(message);
108 | console.log(message);
109 | });
110 | }
111 |
112 | return true;
113 | }
114 | });
115 | } else {
116 | writeConfig();
117 | }
118 | } catch (err) {
119 | console.log(err);
120 | writeLog(err);
121 | writeConfig();
122 | }
123 |
124 | };
125 |
126 | writeConfig = () => {
127 |
128 | var obj = {
129 | "server": "yoursandbox.demandware.net",
130 | "site_id": "SiteGenesis",
131 | "version": "v23_2",
132 | "client_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
133 | "port": port,
134 | "port_ui": adminPort,
135 | "UA": ""
136 | };
137 | jsonfile.writeFile(file, obj, (err) => {
138 | if (err != null) {
139 | console.log(err);
140 | writeLog(err);
141 | }
142 | });
143 | message = "Creating config.json";
144 | console.log(message);
145 | writeLog(message);
146 | };
147 |
148 |
149 | callbackAdmin = (error, response, body) => {
150 | response.send("Test Callback");
151 | }
152 |
153 | AdminCall = (req, resp) => {
154 | var adminRequest = req;
155 | var adminResponse = resp;
156 | var options = {
157 | method: req.method,
158 | body: adminRequest.body
159 | };
160 | request(options, callbackAdmin);
161 | }
162 |
163 |
164 |
165 | ProxyCall = (req, resp) => {
166 | var proxyRequest = req;
167 | var proxyResponse = resp;
168 | var callurl = "https://" + server + "/s/" + site_id + "/dw/shop/" + version + "/" + proxyRequest.headers.callurl;
169 | var options = {
170 | url: callurl, //proxyRequest.headers.callurl,
171 | method: req.method,
172 | headers: {
173 | 'callurl': proxyRequest.headers.callurl
174 | },
175 | body: JSON.stringify(proxyRequest.body)
176 | };
177 |
178 | options.headers["x-dw-client-id"] = client_id;
179 |
180 | if (proxyRequest.headers.hasOwnProperty("x-dw-http-method-override")) {
181 | options.headers["x-dw-http-method-override"] = proxyRequest.headers["x-dw-http-method-override"];
182 | }
183 | if (proxyRequest.headers.hasOwnProperty("user-agent")) {
184 | options.headers["user-agent"] = proxyRequest.headers["user-agent"];
185 | }
186 |
187 | if (proxyRequest.headers.hasOwnProperty("authorization")) {
188 | options.headers.Authorization = proxyRequest.headers.authorization;
189 | }
190 |
191 | if (proxyRequest.headers.hasOwnProperty("etag")) {
192 | options.headers.ETag = proxyRequest.headers.etag;
193 | }
194 |
195 | request(options, callback);
196 | if (UA != "") {
197 |
198 | try {
199 | var visitor = ua(UA); //UA-XXXX-XX
200 | visitor.event("OCAPI", callurl).send();
201 |
202 | } catch (err) {
203 | console.log(err);
204 | writeLog(err);
205 | }
206 | }
207 |
208 |
209 | callback = (error, response, body) => {
210 | try {
211 | if (!error && response.statusCode == 200) {
212 | writeLog(body);
213 | console.log(chalk.green(body));
214 | } else {
215 | //error
216 | console.log(chalk.red("Check Config/Ports - " + error.code + ":" + error.message));
217 | writeLog("Check Config/Ports - " + error.code + ":" + error.message);
218 | jsonError = {
219 | "code": error.code,
220 | "message": error.message,
221 | "timestamp": new Date().getTime()
222 | }
223 | jsonError = JSON.stringify(jsonError);
224 | proxyResponse.send(jsonError);
225 | return;
226 | }
227 |
228 | writeLog(body);
229 | console.log(body);
230 | var jsonBody = JSON.parse(body);
231 |
232 | if (response.headers.hasOwnProperty("authorization")) {
233 | jsonBody.Authorization = response.headers.authorization;
234 | }
235 |
236 | if (response.headers.hasOwnProperty("etag")) {
237 | jsonBody.ETag = response.headers.etag;
238 | }
239 | jsonBody = JSON.stringify(jsonBody);
240 | proxyResponse.send(jsonBody);
241 |
242 | } catch (err) {
243 | console.log(err);
244 | writeLog(err);
245 | }
246 |
247 | }
248 | }
249 |
250 | exports.start = () => {
251 |
252 | var configFileValid = readConfig();
253 | if (configFileValid) {
254 |
255 | } else {
256 | //process.exit();
257 | }
258 |
259 | var jsonParser = bodyParser.json();
260 |
261 | app.use(bodyParser.urlencoded({
262 | extended: true
263 | }));
264 | limiter = rateLimit({
265 | windowMs: limit, // 15 minutes or config file entry
266 | max: max, // Limit each IP to max per windowMs
267 | standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
268 | legacyHeaders: false, // Disable the `X-RateLimit-*` headers
269 | })
270 |
271 | app.use(cors());
272 | admin.use(cors());
273 |
274 | app.use(limiter);
275 | admin.use(limiter);
276 |
277 | app.all('/', jsonParser, (request, response) => {
278 |
279 | response.setHeader('Content-Type', "application/json");
280 | response.setHeader("Access-Control-Allow-Origin", "*");
281 |
282 | var headers = JSON.stringify(request.headers);
283 | var requestBody = request.body;
284 |
285 | ProxyCall(request, response);
286 |
287 | });
288 |
289 | admin.use(bodyParser.urlencoded({
290 | extended: true
291 | }));
292 |
293 | app.use(express.static(__dirname + '/html'));
294 |
295 | admin.all('/', (request, response) => {
296 |
297 | response.setHeader('Content-Type', "text/html");
298 | var headers = JSON.stringify(request.headers);
299 | var requestBody = request.body;
300 |
301 | response.sendFile(path + "index.html");
302 | });
303 |
304 | if (process.argv.slice(2) != null && process.argv.slice(2) != undefined) {
305 | if (process.argv.slice(2) == "loadUI") {
306 | loadUI = true;
307 | }
308 | }
309 |
310 | };
311 |
--------------------------------------------------------------------------------
/ocapi-proxy.js:
--------------------------------------------------------------------------------
1 | var OCAPIProxy = require("./libProxy.js");
2 | OCAPIProxy.start();
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ocapi-proxy",
3 | "version": "2.2.2",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "ocapi-proxy",
9 | "version": "2.2.2",
10 | "hasInstallScript": true,
11 | "license": "MIT",
12 | "dependencies": {
13 | "body-parser": "^1.20.1",
14 | "bootstrap": "^5.2.3",
15 | "btoa": "^1.2.1",
16 | "chalk": "^5.2.0",
17 | "cors": "^2.8.5",
18 | "debug": "^4.3.4",
19 | "express": "^4.18.2",
20 | "express-rate-limit": "^6.7.0",
21 | "fs": "^0.0.1-security",
22 | "jsonfile": "^6.1.0",
23 | "minimist": "^1.2.7",
24 | "open": "^8.4.0",
25 | "qs": "^6.11.0",
26 | "request": "^2.88.2",
27 | "universal-analytics": "^0.5.3"
28 | }
29 | },
30 | "node_modules/@popperjs/core": {
31 | "version": "2.11.8",
32 | "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
33 | "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
34 | "peer": true,
35 | "funding": {
36 | "type": "opencollective",
37 | "url": "https://opencollective.com/popperjs"
38 | }
39 | },
40 | "node_modules/accepts": {
41 | "version": "1.3.8",
42 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
43 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
44 | "dependencies": {
45 | "mime-types": "~2.1.34",
46 | "negotiator": "0.6.3"
47 | },
48 | "engines": {
49 | "node": ">= 0.6"
50 | }
51 | },
52 | "node_modules/ajv": {
53 | "version": "6.12.6",
54 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
55 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
56 | "dependencies": {
57 | "fast-deep-equal": "^3.1.1",
58 | "fast-json-stable-stringify": "^2.0.0",
59 | "json-schema-traverse": "^0.4.1",
60 | "uri-js": "^4.2.2"
61 | },
62 | "funding": {
63 | "type": "github",
64 | "url": "https://github.com/sponsors/epoberezkin"
65 | }
66 | },
67 | "node_modules/array-flatten": {
68 | "version": "1.1.1",
69 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
70 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
71 | },
72 | "node_modules/asn1": {
73 | "version": "0.2.6",
74 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
75 | "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
76 | "dependencies": {
77 | "safer-buffer": "~2.1.0"
78 | }
79 | },
80 | "node_modules/assert-plus": {
81 | "version": "1.0.0",
82 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
83 | "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
84 | "engines": {
85 | "node": ">=0.8"
86 | }
87 | },
88 | "node_modules/asynckit": {
89 | "version": "0.4.0",
90 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
91 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
92 | },
93 | "node_modules/aws-sign2": {
94 | "version": "0.7.0",
95 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
96 | "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
97 | "engines": {
98 | "node": "*"
99 | }
100 | },
101 | "node_modules/aws4": {
102 | "version": "1.13.2",
103 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
104 | "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw=="
105 | },
106 | "node_modules/bcrypt-pbkdf": {
107 | "version": "1.0.2",
108 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
109 | "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
110 | "dependencies": {
111 | "tweetnacl": "^0.14.3"
112 | }
113 | },
114 | "node_modules/body-parser": {
115 | "version": "1.20.3",
116 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
117 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
118 | "dependencies": {
119 | "bytes": "3.1.2",
120 | "content-type": "~1.0.5",
121 | "debug": "2.6.9",
122 | "depd": "2.0.0",
123 | "destroy": "1.2.0",
124 | "http-errors": "2.0.0",
125 | "iconv-lite": "0.4.24",
126 | "on-finished": "2.4.1",
127 | "qs": "6.13.0",
128 | "raw-body": "2.5.2",
129 | "type-is": "~1.6.18",
130 | "unpipe": "1.0.0"
131 | },
132 | "engines": {
133 | "node": ">= 0.8",
134 | "npm": "1.2.8000 || >= 1.4.16"
135 | }
136 | },
137 | "node_modules/body-parser/node_modules/debug": {
138 | "version": "2.6.9",
139 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
140 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
141 | "dependencies": {
142 | "ms": "2.0.0"
143 | }
144 | },
145 | "node_modules/body-parser/node_modules/ms": {
146 | "version": "2.0.0",
147 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
148 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
149 | },
150 | "node_modules/bootstrap": {
151 | "version": "5.3.3",
152 | "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
153 | "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
154 | "funding": [
155 | {
156 | "type": "github",
157 | "url": "https://github.com/sponsors/twbs"
158 | },
159 | {
160 | "type": "opencollective",
161 | "url": "https://opencollective.com/bootstrap"
162 | }
163 | ],
164 | "peerDependencies": {
165 | "@popperjs/core": "^2.11.8"
166 | }
167 | },
168 | "node_modules/btoa": {
169 | "version": "1.2.1",
170 | "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
171 | "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
172 | "bin": {
173 | "btoa": "bin/btoa.js"
174 | },
175 | "engines": {
176 | "node": ">= 0.4.0"
177 | }
178 | },
179 | "node_modules/bytes": {
180 | "version": "3.1.2",
181 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
182 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
183 | "engines": {
184 | "node": ">= 0.8"
185 | }
186 | },
187 | "node_modules/call-bind": {
188 | "version": "1.0.7",
189 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
190 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
191 | "dependencies": {
192 | "es-define-property": "^1.0.0",
193 | "es-errors": "^1.3.0",
194 | "function-bind": "^1.1.2",
195 | "get-intrinsic": "^1.2.4",
196 | "set-function-length": "^1.2.1"
197 | },
198 | "engines": {
199 | "node": ">= 0.4"
200 | },
201 | "funding": {
202 | "url": "https://github.com/sponsors/ljharb"
203 | }
204 | },
205 | "node_modules/caseless": {
206 | "version": "0.12.0",
207 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
208 | "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
209 | },
210 | "node_modules/chalk": {
211 | "version": "5.3.0",
212 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
213 | "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
214 | "engines": {
215 | "node": "^12.17.0 || ^14.13 || >=16.0.0"
216 | },
217 | "funding": {
218 | "url": "https://github.com/chalk/chalk?sponsor=1"
219 | }
220 | },
221 | "node_modules/combined-stream": {
222 | "version": "1.0.8",
223 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
224 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
225 | "dependencies": {
226 | "delayed-stream": "~1.0.0"
227 | },
228 | "engines": {
229 | "node": ">= 0.8"
230 | }
231 | },
232 | "node_modules/content-disposition": {
233 | "version": "0.5.4",
234 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
235 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
236 | "dependencies": {
237 | "safe-buffer": "5.2.1"
238 | },
239 | "engines": {
240 | "node": ">= 0.6"
241 | }
242 | },
243 | "node_modules/content-type": {
244 | "version": "1.0.5",
245 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
246 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
247 | "engines": {
248 | "node": ">= 0.6"
249 | }
250 | },
251 | "node_modules/cookie": {
252 | "version": "0.6.0",
253 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
254 | "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
255 | "engines": {
256 | "node": ">= 0.6"
257 | }
258 | },
259 | "node_modules/cookie-signature": {
260 | "version": "1.0.6",
261 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
262 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
263 | },
264 | "node_modules/core-util-is": {
265 | "version": "1.0.2",
266 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
267 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
268 | },
269 | "node_modules/cors": {
270 | "version": "2.8.5",
271 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
272 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
273 | "dependencies": {
274 | "object-assign": "^4",
275 | "vary": "^1"
276 | },
277 | "engines": {
278 | "node": ">= 0.10"
279 | }
280 | },
281 | "node_modules/dashdash": {
282 | "version": "1.14.1",
283 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
284 | "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
285 | "dependencies": {
286 | "assert-plus": "^1.0.0"
287 | },
288 | "engines": {
289 | "node": ">=0.10"
290 | }
291 | },
292 | "node_modules/debug": {
293 | "version": "4.3.7",
294 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
295 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
296 | "dependencies": {
297 | "ms": "^2.1.3"
298 | },
299 | "engines": {
300 | "node": ">=6.0"
301 | },
302 | "peerDependenciesMeta": {
303 | "supports-color": {
304 | "optional": true
305 | }
306 | }
307 | },
308 | "node_modules/define-data-property": {
309 | "version": "1.1.4",
310 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
311 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
312 | "dependencies": {
313 | "es-define-property": "^1.0.0",
314 | "es-errors": "^1.3.0",
315 | "gopd": "^1.0.1"
316 | },
317 | "engines": {
318 | "node": ">= 0.4"
319 | },
320 | "funding": {
321 | "url": "https://github.com/sponsors/ljharb"
322 | }
323 | },
324 | "node_modules/define-lazy-prop": {
325 | "version": "2.0.0",
326 | "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
327 | "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
328 | "engines": {
329 | "node": ">=8"
330 | }
331 | },
332 | "node_modules/delayed-stream": {
333 | "version": "1.0.0",
334 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
335 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
336 | "engines": {
337 | "node": ">=0.4.0"
338 | }
339 | },
340 | "node_modules/depd": {
341 | "version": "2.0.0",
342 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
343 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
344 | "engines": {
345 | "node": ">= 0.8"
346 | }
347 | },
348 | "node_modules/destroy": {
349 | "version": "1.2.0",
350 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
351 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
352 | "engines": {
353 | "node": ">= 0.8",
354 | "npm": "1.2.8000 || >= 1.4.16"
355 | }
356 | },
357 | "node_modules/ecc-jsbn": {
358 | "version": "0.1.2",
359 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
360 | "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
361 | "dependencies": {
362 | "jsbn": "~0.1.0",
363 | "safer-buffer": "^2.1.0"
364 | }
365 | },
366 | "node_modules/ee-first": {
367 | "version": "1.1.1",
368 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
369 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
370 | },
371 | "node_modules/encodeurl": {
372 | "version": "2.0.0",
373 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
374 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
375 | "engines": {
376 | "node": ">= 0.8"
377 | }
378 | },
379 | "node_modules/es-define-property": {
380 | "version": "1.0.0",
381 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
382 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
383 | "dependencies": {
384 | "get-intrinsic": "^1.2.4"
385 | },
386 | "engines": {
387 | "node": ">= 0.4"
388 | }
389 | },
390 | "node_modules/es-errors": {
391 | "version": "1.3.0",
392 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
393 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
394 | "engines": {
395 | "node": ">= 0.4"
396 | }
397 | },
398 | "node_modules/escape-html": {
399 | "version": "1.0.3",
400 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
401 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
402 | },
403 | "node_modules/etag": {
404 | "version": "1.8.1",
405 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
406 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
407 | "engines": {
408 | "node": ">= 0.6"
409 | }
410 | },
411 | "node_modules/express": {
412 | "version": "4.19.2",
413 | "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
414 | "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
415 | "dependencies": {
416 | "accepts": "~1.3.8",
417 | "array-flatten": "1.1.1",
418 | "body-parser": "1.20.2",
419 | "version": "4.21.0",
420 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
421 | "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==",
422 | "dependencies": {
423 | "accepts": "~1.3.8",
424 | "array-flatten": "1.1.1",
425 | "body-parser": "1.20.3",
426 | "content-disposition": "0.5.4",
427 | "content-type": "~1.0.4",
428 | "cookie": "0.6.0",
429 | "cookie-signature": "1.0.6",
430 | "debug": "2.6.9",
431 | "depd": "2.0.0",
432 | "encodeurl": "~2.0.0",
433 | "escape-html": "~1.0.3",
434 | "etag": "~1.8.1",
435 | "finalhandler": "1.3.1",
436 | "fresh": "0.5.2",
437 | "http-errors": "2.0.0",
438 | "merge-descriptors": "1.0.3",
439 | "methods": "~1.1.2",
440 | "on-finished": "2.4.1",
441 | "parseurl": "~1.3.3",
442 | "path-to-regexp": "0.1.10",
443 | "proxy-addr": "~2.0.7",
444 | "qs": "6.13.0",
445 | "range-parser": "~1.2.1",
446 | "safe-buffer": "5.2.1",
447 | "send": "0.19.0",
448 | "serve-static": "1.16.2",
449 | "setprototypeof": "1.2.0",
450 | "statuses": "2.0.1",
451 | "type-is": "~1.6.18",
452 | "utils-merge": "1.0.1",
453 | "vary": "~1.1.2"
454 | },
455 | "engines": {
456 | "node": ">= 0.10.0"
457 | }
458 | },
459 | "node_modules/express-rate-limit": {
460 | "version": "6.11.2",
461 | "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.11.2.tgz",
462 | "integrity": "sha512-a7uwwfNTh1U60ssiIkuLFWHt4hAC5yxlLGU2VP0X4YNlyEDZAqF4tK3GD3NSitVBrCQmQ0++0uOyFOgC2y4DDw==",
463 | "engines": {
464 | "node": ">= 14"
465 | },
466 | "peerDependencies": {
467 | "express": "^4 || ^5"
468 | }
469 | },
470 | "node_modules/express/node_modules/debug": {
471 | "version": "2.6.9",
472 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
473 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
474 | "dependencies": {
475 | "ms": "2.0.0"
476 | }
477 | },
478 | "node_modules/express/node_modules/ms": {
479 | "version": "2.0.0",
480 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
481 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
482 | },
483 | "node_modules/express/node_modules/qs": {
484 | "version": "6.11.0",
485 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
486 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
487 | "dependencies": {
488 | "side-channel": "^1.0.4"
489 | },
490 | "engines": {
491 | "node": ">=0.6"
492 | },
493 | "funding": {
494 | "url": "https://github.com/sponsors/ljharb"
495 | }
496 | },
497 | "node_modules/extend": {
498 | "version": "3.0.2",
499 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
500 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
501 | },
502 | "node_modules/extsprintf": {
503 | "version": "1.3.0",
504 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
505 | "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
506 | "engines": [
507 | "node >=0.6.0"
508 | ]
509 | },
510 | "node_modules/fast-deep-equal": {
511 | "version": "3.1.3",
512 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
513 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
514 | },
515 | "node_modules/fast-json-stable-stringify": {
516 | "version": "2.1.0",
517 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
518 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
519 | },
520 | "node_modules/finalhandler": {
521 | "version": "1.3.1",
522 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
523 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
524 | "dependencies": {
525 | "debug": "2.6.9",
526 | "encodeurl": "~2.0.0",
527 | "escape-html": "~1.0.3",
528 | "on-finished": "2.4.1",
529 | "parseurl": "~1.3.3",
530 | "statuses": "2.0.1",
531 | "unpipe": "~1.0.0"
532 | },
533 | "engines": {
534 | "node": ">= 0.8"
535 | }
536 | },
537 | "node_modules/finalhandler/node_modules/debug": {
538 | "version": "2.6.9",
539 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
540 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
541 | "dependencies": {
542 | "ms": "2.0.0"
543 | }
544 | },
545 | "node_modules/finalhandler/node_modules/ms": {
546 | "version": "2.0.0",
547 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
548 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
549 | },
550 | "node_modules/forever-agent": {
551 | "version": "0.6.1",
552 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
553 | "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
554 | "engines": {
555 | "node": "*"
556 | }
557 | },
558 | "node_modules/form-data": {
559 | "version": "2.3.3",
560 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
561 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
562 | "dependencies": {
563 | "asynckit": "^0.4.0",
564 | "combined-stream": "^1.0.6",
565 | "mime-types": "^2.1.12"
566 | },
567 | "engines": {
568 | "node": ">= 0.12"
569 | }
570 | },
571 | "node_modules/forwarded": {
572 | "version": "0.2.0",
573 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
574 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
575 | "engines": {
576 | "node": ">= 0.6"
577 | }
578 | },
579 | "node_modules/fresh": {
580 | "version": "0.5.2",
581 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
582 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
583 | "engines": {
584 | "node": ">= 0.6"
585 | }
586 | },
587 | "node_modules/fs": {
588 | "version": "0.0.1-security",
589 | "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
590 | "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="
591 | },
592 | "node_modules/function-bind": {
593 | "version": "1.1.2",
594 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
595 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
596 | "funding": {
597 | "url": "https://github.com/sponsors/ljharb"
598 | }
599 | },
600 | "node_modules/get-intrinsic": {
601 | "version": "1.2.4",
602 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
603 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
604 | "dependencies": {
605 | "es-errors": "^1.3.0",
606 | "function-bind": "^1.1.2",
607 | "has-proto": "^1.0.1",
608 | "has-symbols": "^1.0.3",
609 | "hasown": "^2.0.0"
610 | },
611 | "engines": {
612 | "node": ">= 0.4"
613 | },
614 | "funding": {
615 | "url": "https://github.com/sponsors/ljharb"
616 | }
617 | },
618 | "node_modules/getpass": {
619 | "version": "0.1.7",
620 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
621 | "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
622 | "dependencies": {
623 | "assert-plus": "^1.0.0"
624 | }
625 | },
626 | "node_modules/gopd": {
627 | "version": "1.0.1",
628 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
629 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
630 | "dependencies": {
631 | "get-intrinsic": "^1.1.3"
632 | },
633 | "funding": {
634 | "url": "https://github.com/sponsors/ljharb"
635 | }
636 | },
637 | "node_modules/graceful-fs": {
638 | "version": "4.2.11",
639 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
640 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
641 | "optional": true
642 | },
643 | "node_modules/har-schema": {
644 | "version": "2.0.0",
645 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
646 | "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
647 | "engines": {
648 | "node": ">=4"
649 | }
650 | },
651 | "node_modules/har-validator": {
652 | "version": "5.1.5",
653 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
654 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
655 | "deprecated": "this library is no longer supported",
656 | "dependencies": {
657 | "ajv": "^6.12.3",
658 | "har-schema": "^2.0.0"
659 | },
660 | "engines": {
661 | "node": ">=6"
662 | }
663 | },
664 | "node_modules/has-property-descriptors": {
665 | "version": "1.0.2",
666 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
667 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
668 | "dependencies": {
669 | "es-define-property": "^1.0.0"
670 | },
671 | "funding": {
672 | "url": "https://github.com/sponsors/ljharb"
673 | }
674 | },
675 | "node_modules/has-proto": {
676 | "version": "1.0.3",
677 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
678 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
679 | "engines": {
680 | "node": ">= 0.4"
681 | },
682 | "funding": {
683 | "url": "https://github.com/sponsors/ljharb"
684 | }
685 | },
686 | "node_modules/has-symbols": {
687 | "version": "1.0.3",
688 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
689 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
690 | "engines": {
691 | "node": ">= 0.4"
692 | },
693 | "funding": {
694 | "url": "https://github.com/sponsors/ljharb"
695 | }
696 | },
697 | "node_modules/hasown": {
698 | "version": "2.0.2",
699 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
700 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
701 | "dependencies": {
702 | "function-bind": "^1.1.2"
703 | },
704 | "engines": {
705 | "node": ">= 0.4"
706 | }
707 | },
708 | "node_modules/http-errors": {
709 | "version": "2.0.0",
710 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
711 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
712 | "dependencies": {
713 | "depd": "2.0.0",
714 | "inherits": "2.0.4",
715 | "setprototypeof": "1.2.0",
716 | "statuses": "2.0.1",
717 | "toidentifier": "1.0.1"
718 | },
719 | "engines": {
720 | "node": ">= 0.8"
721 | }
722 | },
723 | "node_modules/http-signature": {
724 | "version": "1.2.0",
725 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
726 | "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
727 | "dependencies": {
728 | "assert-plus": "^1.0.0",
729 | "jsprim": "^1.2.2",
730 | "sshpk": "^1.7.0"
731 | },
732 | "engines": {
733 | "node": ">=0.8",
734 | "npm": ">=1.3.7"
735 | }
736 | },
737 | "node_modules/iconv-lite": {
738 | "version": "0.4.24",
739 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
740 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
741 | "dependencies": {
742 | "safer-buffer": ">= 2.1.2 < 3"
743 | },
744 | "engines": {
745 | "node": ">=0.10.0"
746 | }
747 | },
748 | "node_modules/inherits": {
749 | "version": "2.0.4",
750 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
751 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
752 | },
753 | "node_modules/ipaddr.js": {
754 | "version": "1.9.1",
755 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
756 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
757 | "engines": {
758 | "node": ">= 0.10"
759 | }
760 | },
761 | "node_modules/is-docker": {
762 | "version": "2.2.1",
763 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
764 | "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
765 | "bin": {
766 | "is-docker": "cli.js"
767 | },
768 | "engines": {
769 | "node": ">=8"
770 | },
771 | "funding": {
772 | "url": "https://github.com/sponsors/sindresorhus"
773 | }
774 | },
775 | "node_modules/is-typedarray": {
776 | "version": "1.0.0",
777 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
778 | "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
779 | },
780 | "node_modules/is-wsl": {
781 | "version": "2.2.0",
782 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
783 | "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
784 | "dependencies": {
785 | "is-docker": "^2.0.0"
786 | },
787 | "engines": {
788 | "node": ">=8"
789 | }
790 | },
791 | "node_modules/isstream": {
792 | "version": "0.1.2",
793 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
794 | "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
795 | },
796 | "node_modules/jsbn": {
797 | "version": "0.1.1",
798 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
799 | "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
800 | },
801 | "node_modules/json-schema": {
802 | "version": "0.4.0",
803 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
804 | "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
805 | },
806 | "node_modules/json-schema-traverse": {
807 | "version": "0.4.1",
808 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
809 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
810 | },
811 | "node_modules/json-stringify-safe": {
812 | "version": "5.0.1",
813 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
814 | "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
815 | },
816 | "node_modules/jsonfile": {
817 | "version": "6.1.0",
818 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
819 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
820 | "dependencies": {
821 | "universalify": "^2.0.0"
822 | },
823 | "optionalDependencies": {
824 | "graceful-fs": "^4.1.6"
825 | }
826 | },
827 | "node_modules/jsprim": {
828 | "version": "1.4.2",
829 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
830 | "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
831 | "dependencies": {
832 | "assert-plus": "1.0.0",
833 | "extsprintf": "1.3.0",
834 | "json-schema": "0.4.0",
835 | "verror": "1.10.0"
836 | },
837 | "engines": {
838 | "node": ">=0.6.0"
839 | }
840 | },
841 | "node_modules/media-typer": {
842 | "version": "0.3.0",
843 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
844 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
845 | "engines": {
846 | "node": ">= 0.6"
847 | }
848 | },
849 | "node_modules/merge-descriptors": {
850 | "version": "1.0.3",
851 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
852 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
853 | "funding": {
854 | "url": "https://github.com/sponsors/sindresorhus"
855 | }
856 | },
857 | "node_modules/methods": {
858 | "version": "1.1.2",
859 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
860 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
861 | "engines": {
862 | "node": ">= 0.6"
863 | }
864 | },
865 | "node_modules/mime": {
866 | "version": "1.6.0",
867 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
868 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
869 | "bin": {
870 | "mime": "cli.js"
871 | },
872 | "engines": {
873 | "node": ">=4"
874 | }
875 | },
876 | "node_modules/mime-db": {
877 | "version": "1.52.0",
878 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
879 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
880 | "engines": {
881 | "node": ">= 0.6"
882 | }
883 | },
884 | "node_modules/mime-types": {
885 | "version": "2.1.35",
886 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
887 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
888 | "dependencies": {
889 | "mime-db": "1.52.0"
890 | },
891 | "engines": {
892 | "node": ">= 0.6"
893 | }
894 | },
895 | "node_modules/minimist": {
896 | "version": "1.2.8",
897 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
898 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
899 | "funding": {
900 | "url": "https://github.com/sponsors/ljharb"
901 | }
902 | },
903 | "node_modules/ms": {
904 | "version": "2.1.3",
905 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
906 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
907 | },
908 | "node_modules/negotiator": {
909 | "version": "0.6.3",
910 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
911 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
912 | "engines": {
913 | "node": ">= 0.6"
914 | }
915 | },
916 | "node_modules/oauth-sign": {
917 | "version": "0.9.0",
918 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
919 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
920 | "engines": {
921 | "node": "*"
922 | }
923 | },
924 | "node_modules/object-assign": {
925 | "version": "4.1.1",
926 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
927 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
928 | "engines": {
929 | "node": ">=0.10.0"
930 | }
931 | },
932 | "node_modules/object-inspect": {
933 | "version": "1.13.2",
934 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
935 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
936 | "engines": {
937 | "node": ">= 0.4"
938 | },
939 | "funding": {
940 | "url": "https://github.com/sponsors/ljharb"
941 | }
942 | },
943 | "node_modules/on-finished": {
944 | "version": "2.4.1",
945 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
946 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
947 | "dependencies": {
948 | "ee-first": "1.1.1"
949 | },
950 | "engines": {
951 | "node": ">= 0.8"
952 | }
953 | },
954 | "node_modules/open": {
955 | "version": "8.4.2",
956 | "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
957 | "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
958 | "dependencies": {
959 | "define-lazy-prop": "^2.0.0",
960 | "is-docker": "^2.1.1",
961 | "is-wsl": "^2.2.0"
962 | },
963 | "engines": {
964 | "node": ">=12"
965 | },
966 | "funding": {
967 | "url": "https://github.com/sponsors/sindresorhus"
968 | }
969 | },
970 | "node_modules/parseurl": {
971 | "version": "1.3.3",
972 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
973 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
974 | "engines": {
975 | "node": ">= 0.8"
976 | }
977 | },
978 | "node_modules/path-to-regexp": {
979 | "version": "0.1.10",
980 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
981 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w=="
982 | },
983 | "node_modules/performance-now": {
984 | "version": "2.1.0",
985 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
986 | "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
987 | },
988 | "node_modules/proxy-addr": {
989 | "version": "2.0.7",
990 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
991 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
992 | "dependencies": {
993 | "forwarded": "0.2.0",
994 | "ipaddr.js": "1.9.1"
995 | },
996 | "engines": {
997 | "node": ">= 0.10"
998 | }
999 | },
1000 | "node_modules/psl": {
1001 | "version": "1.9.0",
1002 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
1003 | "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
1004 | },
1005 | "node_modules/punycode": {
1006 | "version": "2.3.1",
1007 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
1008 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
1009 | "engines": {
1010 | "node": ">=6"
1011 | }
1012 | },
1013 | "node_modules/qs": {
1014 | "version": "6.13.0",
1015 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
1016 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
1017 | "dependencies": {
1018 | "side-channel": "^1.0.6"
1019 | },
1020 | "engines": {
1021 | "node": ">=0.6"
1022 | },
1023 | "funding": {
1024 | "url": "https://github.com/sponsors/ljharb"
1025 | }
1026 | },
1027 | "node_modules/range-parser": {
1028 | "version": "1.2.1",
1029 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1030 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
1031 | "engines": {
1032 | "node": ">= 0.6"
1033 | }
1034 | },
1035 | "node_modules/raw-body": {
1036 | "version": "2.5.2",
1037 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
1038 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
1039 | "dependencies": {
1040 | "bytes": "3.1.2",
1041 | "http-errors": "2.0.0",
1042 | "iconv-lite": "0.4.24",
1043 | "unpipe": "1.0.0"
1044 | },
1045 | "engines": {
1046 | "node": ">= 0.8"
1047 | }
1048 | },
1049 | "node_modules/request": {
1050 | "version": "2.88.2",
1051 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
1052 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
1053 | "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
1054 | "dependencies": {
1055 | "aws-sign2": "~0.7.0",
1056 | "aws4": "^1.8.0",
1057 | "caseless": "~0.12.0",
1058 | "combined-stream": "~1.0.6",
1059 | "extend": "~3.0.2",
1060 | "forever-agent": "~0.6.1",
1061 | "form-data": "~2.3.2",
1062 | "har-validator": "~5.1.3",
1063 | "http-signature": "~1.2.0",
1064 | "is-typedarray": "~1.0.0",
1065 | "isstream": "~0.1.2",
1066 | "json-stringify-safe": "~5.0.1",
1067 | "mime-types": "~2.1.19",
1068 | "oauth-sign": "~0.9.0",
1069 | "performance-now": "^2.1.0",
1070 | "qs": "~6.5.2",
1071 | "safe-buffer": "^5.1.2",
1072 | "tough-cookie": "~2.5.0",
1073 | "tunnel-agent": "^0.6.0",
1074 | "uuid": "^3.3.2"
1075 | },
1076 | "engines": {
1077 | "node": ">= 6"
1078 | }
1079 | },
1080 | "node_modules/request/node_modules/qs": {
1081 | "version": "6.5.3",
1082 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
1083 | "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
1084 | "engines": {
1085 | "node": ">=0.6"
1086 | }
1087 | },
1088 | "node_modules/safe-buffer": {
1089 | "version": "5.2.1",
1090 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1091 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1092 | "funding": [
1093 | {
1094 | "type": "github",
1095 | "url": "https://github.com/sponsors/feross"
1096 | },
1097 | {
1098 | "type": "patreon",
1099 | "url": "https://www.patreon.com/feross"
1100 | },
1101 | {
1102 | "type": "consulting",
1103 | "url": "https://feross.org/support"
1104 | }
1105 | ]
1106 | },
1107 | "node_modules/safer-buffer": {
1108 | "version": "2.1.2",
1109 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1110 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1111 | },
1112 | "node_modules/send": {
1113 | "version": "0.19.0",
1114 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
1115 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
1116 | "dependencies": {
1117 | "debug": "2.6.9",
1118 | "depd": "2.0.0",
1119 | "destroy": "1.2.0",
1120 | "encodeurl": "~1.0.2",
1121 | "escape-html": "~1.0.3",
1122 | "etag": "~1.8.1",
1123 | "fresh": "0.5.2",
1124 | "http-errors": "2.0.0",
1125 | "mime": "1.6.0",
1126 | "ms": "2.1.3",
1127 | "on-finished": "2.4.1",
1128 | "range-parser": "~1.2.1",
1129 | "statuses": "2.0.1"
1130 | },
1131 | "engines": {
1132 | "node": ">= 0.8.0"
1133 | }
1134 | },
1135 | "node_modules/send/node_modules/debug": {
1136 | "version": "2.6.9",
1137 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
1138 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
1139 | "dependencies": {
1140 | "ms": "2.0.0"
1141 | }
1142 | },
1143 | "node_modules/send/node_modules/debug/node_modules/ms": {
1144 | "version": "2.0.0",
1145 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1146 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
1147 | },
1148 | "node_modules/send/node_modules/encodeurl": {
1149 | "version": "1.0.2",
1150 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
1151 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
1152 | "engines": {
1153 | "node": ">= 0.8"
1154 | }
1155 | },
1156 | "node_modules/serve-static": {
1157 | "version": "1.16.2",
1158 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
1159 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
1160 | "dependencies": {
1161 | "encodeurl": "~2.0.0",
1162 | "escape-html": "~1.0.3",
1163 | "parseurl": "~1.3.3",
1164 | "send": "0.19.0"
1165 | },
1166 | "engines": {
1167 | "node": ">= 0.8.0"
1168 | }
1169 | },
1170 | "node_modules/set-function-length": {
1171 | "version": "1.2.2",
1172 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
1173 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
1174 | "dependencies": {
1175 | "define-data-property": "^1.1.4",
1176 | "es-errors": "^1.3.0",
1177 | "function-bind": "^1.1.2",
1178 | "get-intrinsic": "^1.2.4",
1179 | "gopd": "^1.0.1",
1180 | "has-property-descriptors": "^1.0.2"
1181 | },
1182 | "engines": {
1183 | "node": ">= 0.4"
1184 | }
1185 | },
1186 | "node_modules/setprototypeof": {
1187 | "version": "1.2.0",
1188 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
1189 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
1190 | },
1191 | "node_modules/side-channel": {
1192 | "version": "1.0.6",
1193 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
1194 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
1195 | "dependencies": {
1196 | "call-bind": "^1.0.7",
1197 | "es-errors": "^1.3.0",
1198 | "get-intrinsic": "^1.2.4",
1199 | "object-inspect": "^1.13.1"
1200 | },
1201 | "engines": {
1202 | "node": ">= 0.4"
1203 | },
1204 | "funding": {
1205 | "url": "https://github.com/sponsors/ljharb"
1206 | }
1207 | },
1208 | "node_modules/sshpk": {
1209 | "version": "1.18.0",
1210 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
1211 | "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
1212 | "dependencies": {
1213 | "asn1": "~0.2.3",
1214 | "assert-plus": "^1.0.0",
1215 | "bcrypt-pbkdf": "^1.0.0",
1216 | "dashdash": "^1.12.0",
1217 | "ecc-jsbn": "~0.1.1",
1218 | "getpass": "^0.1.1",
1219 | "jsbn": "~0.1.0",
1220 | "safer-buffer": "^2.0.2",
1221 | "tweetnacl": "~0.14.0"
1222 | },
1223 | "bin": {
1224 | "sshpk-conv": "bin/sshpk-conv",
1225 | "sshpk-sign": "bin/sshpk-sign",
1226 | "sshpk-verify": "bin/sshpk-verify"
1227 | },
1228 | "engines": {
1229 | "node": ">=0.10.0"
1230 | }
1231 | },
1232 | "node_modules/statuses": {
1233 | "version": "2.0.1",
1234 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
1235 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
1236 | "engines": {
1237 | "node": ">= 0.8"
1238 | }
1239 | },
1240 | "node_modules/toidentifier": {
1241 | "version": "1.0.1",
1242 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
1243 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
1244 | "engines": {
1245 | "node": ">=0.6"
1246 | }
1247 | },
1248 | "node_modules/tough-cookie": {
1249 | "version": "2.5.0",
1250 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
1251 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
1252 | "dependencies": {
1253 | "psl": "^1.1.28",
1254 | "punycode": "^2.1.1"
1255 | },
1256 | "engines": {
1257 | "node": ">=0.8"
1258 | }
1259 | },
1260 | "node_modules/tunnel-agent": {
1261 | "version": "0.6.0",
1262 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
1263 | "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
1264 | "dependencies": {
1265 | "safe-buffer": "^5.0.1"
1266 | },
1267 | "engines": {
1268 | "node": "*"
1269 | }
1270 | },
1271 | "node_modules/tweetnacl": {
1272 | "version": "0.14.5",
1273 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
1274 | "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
1275 | },
1276 | "node_modules/type-is": {
1277 | "version": "1.6.18",
1278 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1279 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1280 | "dependencies": {
1281 | "media-typer": "0.3.0",
1282 | "mime-types": "~2.1.24"
1283 | },
1284 | "engines": {
1285 | "node": ">= 0.6"
1286 | }
1287 | },
1288 | "node_modules/universal-analytics": {
1289 | "version": "0.5.3",
1290 | "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.5.3.tgz",
1291 | "integrity": "sha512-HXSMyIcf2XTvwZ6ZZQLfxfViRm/yTGoRgDeTbojtq6rezeyKB0sTBcKH2fhddnteAHRcHiKgr/ACpbgjGOC6RQ==",
1292 | "dependencies": {
1293 | "debug": "^4.3.1",
1294 | "uuid": "^8.0.0"
1295 | },
1296 | "engines": {
1297 | "node": ">=12.18.2"
1298 | }
1299 | },
1300 | "node_modules/universal-analytics/node_modules/uuid": {
1301 | "version": "8.3.2",
1302 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
1303 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
1304 | "bin": {
1305 | "uuid": "dist/bin/uuid"
1306 | }
1307 | },
1308 | "node_modules/universalify": {
1309 | "version": "2.0.1",
1310 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
1311 | "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
1312 | "engines": {
1313 | "node": ">= 10.0.0"
1314 | }
1315 | },
1316 | "node_modules/unpipe": {
1317 | "version": "1.0.0",
1318 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1319 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
1320 | "engines": {
1321 | "node": ">= 0.8"
1322 | }
1323 | },
1324 | "node_modules/uri-js": {
1325 | "version": "4.4.1",
1326 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
1327 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
1328 | "dependencies": {
1329 | "punycode": "^2.1.0"
1330 | }
1331 | },
1332 | "node_modules/utils-merge": {
1333 | "version": "1.0.1",
1334 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1335 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
1336 | "engines": {
1337 | "node": ">= 0.4.0"
1338 | }
1339 | },
1340 | "node_modules/uuid": {
1341 | "version": "3.4.0",
1342 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
1343 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
1344 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
1345 | "bin": {
1346 | "uuid": "bin/uuid"
1347 | }
1348 | },
1349 | "node_modules/vary": {
1350 | "version": "1.1.2",
1351 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1352 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
1353 | "engines": {
1354 | "node": ">= 0.8"
1355 | }
1356 | },
1357 | "node_modules/verror": {
1358 | "version": "1.10.0",
1359 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
1360 | "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
1361 | "engines": [
1362 | "node >=0.6.0"
1363 | ],
1364 | "dependencies": {
1365 | "assert-plus": "^1.0.0",
1366 | "core-util-is": "1.0.2",
1367 | "extsprintf": "^1.2.0"
1368 | }
1369 | }
1370 | }
1371 | }
1372 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ocapi-proxy",
3 | "version": "2.2.3",
4 | "description": "Salesforce Commerce Cloud OCAPI Proxy Router",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/johnfacey/ocapi-proxy.git"
8 | },
9 | "main": "ocapi-proxy.js",
10 | "scripts": {
11 | "start": "node ocapi-proxy.js",
12 | "test": "echo \"Error: no test specified\" && exit 1",
13 | "build-fs": "node build.js",
14 | "postinstall": "npm run-script build-fs"
15 | },
16 | "keywords": [
17 | "sfcc",
18 | "salesforce",
19 | "ocapi",
20 | "express",
21 | "demandware",
22 | "open",
23 | "commerce",
24 | "commerce cloud",
25 | "open commerce",
26 | "node",
27 | "proxy",
28 | "bootstrap",
29 | "jquery",
30 | "web service",
31 | "proxy",
32 | "router",
33 | "server"
34 | ],
35 | "author": "John K. Facey II",
36 | "license": "MIT",
37 | "dependencies": {
38 | "body-parser": "^1.20.1",
39 | "bootstrap": "^5.2.3",
40 | "btoa": "^1.2.1",
41 | "chalk": "^5.2.0",
42 | "cors": "^2.8.5",
43 | "debug": "^4.3.4",
44 | "express": "^4.18.2",
45 | "express-rate-limit": "^6.7.0",
46 | "fs": "^0.0.1-security",
47 | "jsonfile": "^6.1.0",
48 | "minimist": "^1.2.7",
49 | "open": "^8.4.0",
50 | "qs": "^6.11.0",
51 | "request": "^2.88.2",
52 | "universal-analytics": "^0.5.3"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/sample-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "server": "{instance}.demandware.net",
3 | "site_id": "SiteGenesis",
4 | "version" : "v23_2",
5 | "client_id" : "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
6 | "port" : 8080,
7 | "port_ui": 80,
8 | "UA" : "UA-XXXX-XX",
9 | "rate_limit": "",
10 | "rate_max": ""
11 | }
--------------------------------------------------------------------------------